arkgate 4.1.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +81 -3
  2. package/README.md +15 -4
  3. package/bin/ark-check-runtime.mjs +16 -5
  4. package/bin/ark-mcp-runtime.mjs +766 -64
  5. package/bin/lib/agent-gates.mjs +1 -0
  6. package/bin/lib/ci-and-commands.mjs +16 -7
  7. package/bin/lib/codex-home.mjs +90 -8
  8. package/bin/lib/design-smells.mjs +71 -9
  9. package/bin/lib/doctor-plan.mjs +36 -36
  10. package/bin/lib/effective-contract-load.mjs +73 -9
  11. package/bin/lib/enforcement-state.mjs +1 -1
  12. package/bin/lib/gate-files.mjs +441 -9
  13. package/bin/lib/github-enforcement.mjs +16 -3
  14. package/bin/lib/hook-templates.mjs +12 -11
  15. package/bin/lib/html-report-evolution.mjs +114 -0
  16. package/bin/lib/html-report.mjs +11 -89
  17. package/bin/lib/import-resolve.mjs +33 -11
  18. package/bin/lib/install-activation.mjs +87 -0
  19. package/bin/lib/install-migrate.mjs +66 -50
  20. package/bin/lib/managed-upgrade.mjs +10 -41
  21. package/bin/lib/mcp-adoption.mjs +15 -5
  22. package/bin/lib/pilot-loop.mjs +25 -8
  23. package/bin/lib/project-identity.mjs +103 -0
  24. package/bin/lib/report-snapshot-context.mjs +28 -0
  25. package/bin/lib/resident-hook.mjs +33 -9
  26. package/bin/lib/rules-inventory.mjs +100 -8
  27. package/bin/lib/skill-install.mjs +272 -22
  28. package/bin/lib/skill-write.mjs +899 -0
  29. package/bin/lib/start-preview.mjs +84 -1
  30. package/bin/lib/upgrade-command.mjs +2 -5
  31. package/dist/index.cjs +13 -13
  32. package/dist/index.d.ts +194 -2
  33. package/dist/index.js +13 -13
  34. package/docs/README.md +5 -3
  35. package/docs/agent-guide.md +110 -14
  36. package/docs/ai-gates.md +103 -18
  37. package/docs/assets/ark-write-gate.svg +2 -2
  38. package/docs/enthusiast/how-to-agent-gates.md +6 -0
  39. package/docs/package-surface.md +14 -9
  40. package/docs/product-voice.md +13 -1
  41. package/package.json +3 -1
  42. package/schemas/ark.project-identity.schema.json +116 -0
  43. package/server.json +2 -2
  44. package/templates/skills/ark-adopt.md +9 -0
  45. package/templates/skills/ark-architect.md +12 -2
  46. package/templates/skills/ark-autopilot.md +9 -0
  47. package/templates/skills/ark-contract.md +11 -1
  48. package/templates/skills/ark-coverage.md +9 -0
  49. package/templates/skills/ark-explain.md +13 -1
  50. package/templates/skills/ark-explore.md +9 -0
  51. package/templates/skills/ark-fix.md +10 -1
  52. package/templates/skills/ark-loop.md +11 -2
  53. package/templates/skills/ark-place.md +17 -6
  54. package/templates/skills/ark-runtime.md +8 -0
  55. package/templates/skills/ark-think.md +14 -2
  56. package/templates/skills/ark-upgrade.md +9 -0
package/CHANGELOG.md CHANGED
@@ -5,13 +5,91 @@ in the immutable pre-2.0 archive linked below.
5
5
 
6
6
  ## Unreleased
7
7
 
8
- ## 4.1.1 — 2026-07-25 (prepared)
8
+ ## 4.2.0 — 2026-07-30 (prepared)
9
+
10
+ **Minor** over 4.1.1. Phase WI — workspace identity, activation truth, and safe multi-repository
11
+ skill installation. Adds a stable MCP project-identity contract, exact-root `ark_identity`
12
+ handshake, and project-bound `ark_manifest`; cross-project/config paths fail before Layers or
13
+ ArkRules analysis; Codex setup distinguishes files configured on disk from a runtime observed
14
+ after restart. **No required config migration.** Legacy MCP calls remain callable but explicitly
15
+ non-authoritative until bound. Codex remains advisory at write time. **Status: prepared**
16
+ (`arkgate@4.2.0` not published yet).
17
+
18
+ ### Added
19
+
20
+ - **Project identity contract:** public `ark.project-identity` JSON schema, root API exports,
21
+ stable `projectId`, independent contract/runtime identities, and package-isolation coverage.
22
+ - **MCP handshake and manifest:** `ark_identity` plus shared `project.expectedRoot` /
23
+ `expectedProjectId` input on every tool. The initial handshake requires the exact project root;
24
+ descendants require the matching project id. Project-bound `ark_manifest` is authoritative
25
+ after binding; compatibility `ark://manifest` reads are always unverified/non-authoritative.
26
+ Project-bound results and errors carry identity, binding state, and `authoritative`.
27
+ - **Verdict facets:** `ark_check.verdict` separates identity, analysis completeness, graph,
28
+ coverage, active gates, and overall result without removing legacy `ok`.
29
+ - **Portable evidence:** focused Linux, macOS, and Windows CI for native canonical paths,
30
+ activation, and multi-repo skill behavior.
31
+ - **Report provenance:** architecture snapshots record the Git `HEAD`, branch when attached, and
32
+ dirty-worktree state with a shell-free, best-effort probe.
33
+
34
+ ### Fixed
35
+
36
+ - **Wrong-project MCP reuse:** a process bound to project A rejects project B, config/manifest/
37
+ tsconfig escapes, nested Ark roots, and external write/change paths before returning placement,
38
+ golden-pattern, Layers, or ArkRules analysis.
39
+ - **Skill MCP ordering:** every shipped `/ark-*` skill now requires a matched `ark_identity`
40
+ preflight before consuming any MCP analysis and carries the exact root plus returned project id
41
+ on each later call; stale/mismatched hosts fall back to the workspace-local CLI.
42
+ - **Codex activation truth:** install/start/doctor say configured + restart required until a live
43
+ identity match; compact setup reports partial installs and removes only exact ArkGate-owned
44
+ project TOML.
45
+ - **Gate-presence false green:** `--require-gates` now implies strict config validation and checks
46
+ semantic Ark content in AGENTS, project-rooted MCP/Codex compact registrations, and fail-closed
47
+ CI instead of accepting placeholder files. Backgrounded `ark-check ... &` is not accepted as
48
+ merge enforcement. Native Windows launcher paths are recognized.
49
+ - **Same-machine skill churn:** managed upgrades no longer rewrite an unchanged skill only to
50
+ refresh `arkVersion`; repo catalogs remain isolated.
51
+ - **Shared Codex downgrade:** ArkGate 4.2.0+ installers cannot replace a newer managed
52
+ `$CODEX_HOME/skills` entry with an older bundle, including with `--force`; identical installs
53
+ are idempotent and report why they were skipped. Pre-4.2 binaries do not understand this
54
+ protocol, so legacy repos must be upgraded before they write the optional home catalog.
55
+ Versioned catalog metadata + an install lock prevent
56
+ reintroducing retired skills and serialize concurrent repos. A durable pending-catalog journal
57
+ preserves that version floor across interrupted writes; same/newer retries recover it, while
58
+ corrupt metadata fails safe before skill mutation.
59
+ - **Path aliases and junctions:** hook paths retain the caller spelling while MCP/resident
60
+ identities canonicalize root, config, manifest, tsconfig, launcher, and missing-tail import
61
+ paths. macOS `/var` → `/private/var` aliases and Windows junctions therefore reach the same
62
+ resident endpoint without turning in-project writes into external paths or losing import edges.
63
+ Windows cross-drive import targets are rejected as external even though `path.relative()`
64
+ returns an absolute drive-qualified path for them.
65
+ - **ArkRules inventory noise:** actual governed layer, generated/test/fixture context, technical
66
+ constants, and error-constructor metadata suppress false business-rule pilots while preserving
67
+ eligible Domain/controller candidates.
68
+ - **Design guidance truth:** UI business-rule pilots now route Domain → Application → UI; local
69
+ permission/UI-state `canEdit` helpers are not flagged by name alone; god-module pilots exclude
70
+ seed/fixture/demo/migration/generated files; design-weak labels retain the observed
71
+ SUGGEST/ADAPT/ENFORCE mode.
72
+ - **Cross-version report deltas:** evolution reports no longer present an Ark score delta when the
73
+ origin and current snapshots were produced by different ArkGate versions. Raw coverage, file,
74
+ violation, layer, rule, and gate facts remain visible.
75
+
76
+ ### Compatibility
77
+
78
+ - No required `ark.config.json` migration and no new ArkRules sensor family.
79
+ - Existing MCP clients continue to work with `binding.status = "unverified"` and
80
+ `authoritative = false`; generated instructions require `ark_identity` followed by
81
+ `ark_manifest`. Standard `ark://manifest` resource reads remain compatibility-only and
82
+ non-authoritative.
83
+ - `projectId` is stable for one canonical local checkout across process restarts and contract
84
+ edits. It is intentionally not a cross-machine or cross-operating-system content id.
85
+
86
+ ## 4.1.1 — 2026-07-25 (published)
9
87
 
10
88
  **Patch** over 4.1.0. Phase EH — enforcement evidence modeling + documentation truth (field Codex
11
89
  feedback + public-lane claims audit). Honesty and doctor/CI evidence taxonomy; first-push-safe CI
12
90
  base-ref; report `.gitignore` coverage without defeating `!` exceptions. **No required config
13
91
  migration.** Does not invent hard-write for Codex/Cursor/OpenCode. Does not close Z09 / RB-11.
14
- **Status: prepared** (not on npm until publish).
92
+ **Status: published** (`arkgate@4.1.1` on npm `latest`).
15
93
 
16
94
  ### Added
17
95
 
@@ -59,7 +137,7 @@ write-root split, SPA/lib classification vacuum fixes, ESLint path-alias parity,
59
137
  false-positive tuning, ArkRules merge-plane honesty, type-edge placement debt, rules-inventory
60
138
  UI noise reduction, migrate-contract retrofit, and config write containment.
61
139
  **No required config migration.** Does not weaken write gate or CI value edges. Does not close
62
- Z09 / RB-11 field claims. **Status: published** (`arkgate@4.1.0` on npm `latest` at ship time).
140
+ Z09 / RB-11 field claims. **Status: published** (`arkgate@4.1.0`; superseded by 4.1.1 on `latest`).
63
141
 
64
142
  ### Added
65
143
 
package/README.md CHANGED
@@ -16,8 +16,9 @@ and makes sure a “green” check means something real.
16
16
 
17
17
  </div>
18
18
 
19
- > **ArkGate 4.1.0** is on npm `latest`. Tree prepares **4.1.1** (Phase EH honesty + CI/report fixes) — [4.1.1 notes](docs/releases/4.1.1.md) (**prepared**, not on npm until publish).
20
- > [4.1.0 notes](docs/releases/4.1.0.md) · [4.0.1](docs/releases/4.0.1.md) · [Docs hub](docs/README.md) · [Product voice](docs/product-voice.md)
19
+ > **ArkGate 4.2.0** is prepared (workspace identity + safe multi-repo skills);
20
+ > **4.1.1** remains on npm `latest` until publication.
21
+ > [4.2.0 candidate](docs/releases/4.2.0.md) · [4.1.1](docs/releases/4.1.1.md) · [4.1.0](docs/releases/4.1.0.md) · [Docs hub](docs/README.md) · [Product voice](docs/product-voice.md)
21
22
 
22
23
  ---
23
24
 
@@ -110,6 +111,7 @@ GitHub **status context** that runs the CLI — not “CI file present,” and n
110
111
  Cursor/Codex/OpenCode never get a fake hard write claim.
111
112
 
112
113
  This table describes the supported profile **after its files are installed and the host loads/trusts them**. A hard local boundary covers only the listed hook operations; alternate tools, direct filesystem writes, and human edits still rely on CI. MCP validation is advisory because the agent must call it. The CI check blocks a merge only when the repository makes that status required. Repair **envelopes** may be emitted without reinjection being guaranteed; silent auto-apply never happens. Run `arkgate-check --doctor` (or `ark-check --doctor`) for the evidence actually detected in the current repository.
114
+
113
115
  <!-- arkgate-host-support:end -->
114
116
 
115
117
  #### Why the hard guarantee lives at the merge gate
@@ -130,6 +132,12 @@ the gate.
130
132
 
131
133
  Setup per host: [docs/ai-gates.md](docs/ai-gates.md) · Develop path: [docs/develop.md](docs/develop.md)
132
134
 
135
+ For authoritative MCP contract evidence, call `ark_identity` with the exact project root, then
136
+ call `ark_manifest` with that root plus the returned project id. A contained descendant requires
137
+ the matching id. The legacy `ark://manifest` resource remains compatibility-only and always
138
+ unverified/non-authoritative because standard `resources/read` cannot portably carry that
139
+ expectation.
140
+
133
141
  ---
134
142
 
135
143
  ## Why not only ESLint / Nx / cruiser?
@@ -138,7 +146,7 @@ Setup per host: [docs/ai-gates.md](docs/ai-gates.md) · Develop path: [docs/deve
138
146
  |--|:---:|:---:|
139
147
  | CI import rules | ✅ | ✅ |
140
148
  | Hard-block AI writes on supported hosts | ✅ | ❌ |
141
- | Contract agents can read (`ark://manifest`) | ✅ | ❌ |
149
+ | Project-bound contract agents can read (`ark_manifest`) | ✅ | ❌ |
142
150
  | Placement + preflight for multi-file changes | ✅ | ❌ |
143
151
  | Honest governed % + dual plan (edges vs shape) | ✅ | ❌ |
144
152
  | Opt-in intra-layer ArkRules (structure + invariants) | ✅ | ❌ |
@@ -186,7 +194,10 @@ for real systems. Details: [docs/production-hardening.md](docs/production-harden
186
194
  | Config · package surface · TS | [configuration](docs/configuration.md) · [package-surface](docs/package-surface.md) · [typescript-support](docs/typescript-support.md) |
187
195
  | Brownfield | [docs/brownfield-adoption.md](docs/brownfield-adoption.md) |
188
196
  | Security | [SECURITY.md](SECURITY.md) |
189
- | Current published (4.1.0) | [docs/releases/4.1.0.md](docs/releases/4.1.0.md) · [CHANGELOG](CHANGELOG.md) |
197
+ | Prepared candidate (4.2.0) | [docs/releases/4.2.0.md](docs/releases/4.2.0.md) · [CHANGELOG](CHANGELOG.md) |
198
+ | Current published (4.1.1) | [docs/releases/4.1.1.md](docs/releases/4.1.1.md) |
199
+ | Previous (4.1.0) | [docs/releases/4.1.0.md](docs/releases/4.1.0.md) |
200
+ | Previous patch (4.0.1) | [docs/releases/4.0.1.md](docs/releases/4.0.1.md) |
190
201
  | Previous (4.0.0) | [docs/releases/4.0.0.md](docs/releases/4.0.0.md) |
191
202
  | Previous (3.9.2) | [docs/releases/3.9.2.md](docs/releases/3.9.2.md) |
192
203
  | History / maintainer evidence | [docs/archive/](docs/archive/README.md) |
@@ -169,7 +169,10 @@ function parseArgs(argv) {
169
169
  args.strictMerge = true;
170
170
  }
171
171
  else if (arg === '--strict-config') args.strictConfig = true;
172
- else if (arg === '--require-gates') args.requireGates = true;
172
+ else if (arg === '--require-gates') {
173
+ args.requireGates = true;
174
+ args.strictConfig = true;
175
+ }
173
176
  else if (arg === '--require-write-hook') {
174
177
  args.requireWriteHook = requireValue(arg, i++).trim().toLowerCase();
175
178
  }
@@ -323,9 +326,9 @@ function usage() {
323
326
  'specific host. Cursor and Codex expose advisory MCP tools plus the shared CI check;',
324
327
  'merge blocking requires repository policy to make that status required.',
325
328
  '',
326
- '--require-gates fails the check when AGENTS.md, .mcp.json, or the generated CI',
327
- 'workflow is missing, so "installed but never configured" is a red CI. Combine it',
328
- 'with --strict-config to enforce gate presence and architecture in one run.',
329
+ '--require-gates implies --strict-config and fails when the Ark contract in AGENTS.md,',
330
+ 'the project-rooted Ark server in .mcp.json, or fail-closed CI is missing/invalid.',
331
+ 'Included but unclassified source files therefore stay red instead of false-green.',
329
332
  '',
330
333
  '--install-agent-gates writes AGENTS.md, .mcp.json, and the CI workflow for every',
331
334
  'project, plus tool-specific templates. Known tools: claude, cursor, codex, grok',
@@ -1255,7 +1258,7 @@ async function main() {
1255
1258
  if (args.requireGates) {
1256
1259
  const compactHost = compactRouterHost(args.root);
1257
1260
  console.log(
1258
- 'Ark gates present (merge profile): ' +
1261
+ 'Ark gate artifacts found on disk (merge profile; runtime activation not implied): ' +
1259
1262
  (compactHost
1260
1263
  ? `AGENTS.md, compact host registration (${compactHost})`
1261
1264
  : REQUIRED_GATE_FILES.join(', '))
@@ -1467,10 +1470,13 @@ async function main() {
1467
1470
  if (args.rulesInventory) {
1468
1471
  const { buildRulesInventory, inventoryToExtractionCard } = await import('./lib/rules-inventory.mjs');
1469
1472
  const fileContents = {};
1473
+ const fileLayers = {};
1470
1474
  for (const file of files.slice(0, 400)) {
1471
1475
  const rel = normalize(path.relative(root, file));
1472
1476
  try {
1473
1477
  fileContents[rel] = fs.readFileSync(file, 'utf8');
1478
+ const layer = layerForFile(root, file, config.layers);
1479
+ if (layer) fileLayers[rel] = layer;
1474
1480
  } catch {
1475
1481
  /* skip unreadable */
1476
1482
  }
@@ -1488,6 +1494,11 @@ async function main() {
1488
1494
  }
1489
1495
  const inventory = buildRulesInventory({
1490
1496
  fileContents,
1497
+ fileLayers,
1498
+ layerContexts: (config.layers ?? []).map((layer) => ({
1499
+ name: layer.name,
1500
+ intentPrefixes: layer.intentPrefixes ?? [],
1501
+ })),
1491
1502
  contractedRuleIds: contracted,
1492
1503
  });
1493
1504
  const nextPilot =