arkgate 3.0.4 → 3.1.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.
- package/CHANGELOG.md +82 -1
- package/README.md +29 -9
- package/bin/ark-check.mjs +69 -54
- package/bin/ark-mcp.mjs +267 -26
- package/bin/ark.mjs +50 -3
- package/bin/lib/adapter-contract.mjs +27 -1
- package/bin/lib/agent-gates.mjs +9 -0
- package/bin/lib/analysis-engine.mjs +7 -1169
- package/bin/lib/ci-and-commands.mjs +4 -0
- package/bin/lib/codex-home.mjs +10 -1
- package/bin/lib/doctor-plan.mjs +37 -9
- package/bin/lib/host-support-matrix.mjs +6 -2
- package/bin/lib/install-migrate.mjs +81 -25
- package/bin/lib/mcp-adoption.mjs +8 -0
- package/bin/lib/policy-delta-io.mjs +161 -0
- package/bin/lib/prepare-change.mjs +186 -0
- package/bin/lib/remediation.mjs +24 -0
- package/bin/lib/skill-install.mjs +302 -22
- package/bin/lib/violations.mjs +2 -2
- package/bin/lib/weakest-link.mjs +61 -12
- package/bin/lib/write-path-capabilities.mjs +70 -2
- package/bin/lib/write-path-detect.mjs +18 -11
- package/dist/eslint/index.cjs +3 -977
- package/dist/eslint/index.js +3 -931
- package/dist/index.cjs +6 -1960
- package/dist/index.d.cts +152 -5
- package/dist/index.d.ts +152 -5
- package/dist/index.js +6 -1908
- package/docs/agent-guide.md +16 -2
- package/docs/ai-gates.md +35 -3
- package/docs/configuration.md +44 -0
- package/docs/package-surface.md +8 -1
- package/docs/threat-model.md +7 -4
- package/package.json +6 -5
- package/schemas/ark.analysis-result.schema.json +5 -1
- package/schemas/ark.change-map.schema.json +77 -0
- package/server.json +2 -2
- package/templates/skills/ark-upgrade.md +9 -5
- package/docs/ark-check-example.json +0 -87
- package/docs/demos/03-copilot-autopilot.md +0 -93
- package/docs/migrate-from-ark-runtime-kernel.md +0 -174
- package/docs/production-hardening.md +0 -100
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,88 @@ All notable changes to ArkGate (`arkgate`; formerly `ark-runtime-kernel`) are do
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 3.1.0 — 2026-07-15
|
|
8
|
+
|
|
9
|
+
Deterministic change integrity. **No breaking** CLI or `ark.config.json` changes. **No gate
|
|
10
|
+
weaken.**
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **T01 policy-transition guard:** the public analysis API and generated CLI engine classify
|
|
15
|
+
`ark.config.json` changes as `strengthening`, `neutral`, `judgment-required`, or `weakening`.
|
|
16
|
+
`--strict-merge` compares the Git merge-base contract when available; explicit
|
|
17
|
+
`--policy-base` / `--policy-base-ref` inputs are also supported.
|
|
18
|
+
- **Hash-bound acknowledgement:** weakening and judgment-required findings fail until
|
|
19
|
+
`--policy-ack` supplies the exact base/candidate policy hashes, complete finding-id set, and a
|
|
20
|
+
non-empty reason. Any later contract edit invalidates the acknowledgement.
|
|
21
|
+
- **CI base provenance:** generated workflows fetch full history and the composite Action passes
|
|
22
|
+
the PR/push base SHA through `ARK_POLICY_BASE_REF`.
|
|
23
|
+
- **MCP parity:** `ark_policy_delta` exposes the same read-only classifier for explicit base and
|
|
24
|
+
candidate contracts and returns blocking transitions as tool errors.
|
|
25
|
+
- **T02 atomic change preflight:** public `preflightChange(...)`, CLI
|
|
26
|
+
`ark preflight --changes <change-set.json>`, and MCP `ark_prepare_change` evaluate one complete
|
|
27
|
+
create/update/delete candidate without writing. Schema `1.0` includes per-file content
|
|
28
|
+
fingerprints plus policy, compiler, base-tree, and candidate-tree fingerprints.
|
|
29
|
+
- **Batch safety:** duplicate normalized paths, stale delete targets, lexical root escapes, and
|
|
30
|
+
symlink escapes fail closed; cross-file forbidden edges and cycles are reported before commit.
|
|
31
|
+
- **T03 optional architecture change map:** strict schema `1.0` describes canonical operations,
|
|
32
|
+
resolved layers, and local edges. CLI/MCP preflight binds its deterministic hash; no map is
|
|
33
|
+
installed by default. Both published schema subpaths are parity-checked with the Domain contract.
|
|
34
|
+
- **T04 honest structural convergence:** map-enabled preflight compares the explicit complete
|
|
35
|
+
candidate with the current supplied base through the shared analysis IR. Stable findings separate
|
|
36
|
+
satisfied, missing, contradictory, and unplanned file/edge work; structural drift rejects the
|
|
37
|
+
batch without writes, while every result states behavioral completion was not evaluated.
|
|
38
|
+
- **T05 actionable, context-independent enforcement:** blocking diagnostics expose one deterministic
|
|
39
|
+
`nextAction` across JSON and human output. Doctor and hook repair JSON separate supported,
|
|
40
|
+
installed, active, and bypassable enforcement with evidence and operation coverage; MCP-only and
|
|
41
|
+
locally unverifiable required-status state remain labeled honestly.
|
|
42
|
+
- **Complete-patch hook parity:** governed Codex `ApplyPatch` create/update/delete sets use the same
|
|
43
|
+
atomic preflight as CLI/MCP before per-file safety checks, catching batch-only edges and cycles.
|
|
44
|
+
Codex remains advisory/bypassable at the host level.
|
|
45
|
+
- **Fixed Phase T evaluation:** `npm run eval:change-integrity` proves identical no-context hashes and
|
|
46
|
+
verdicts, CLI/MCP/hook/final diagnostic parity, one concise casual denial, prewritten feature
|
|
47
|
+
acceptance, and strict Ark green without a live LLM or required planning file.
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- **Compatibility/release:** analysis-result `1.1` preserves `1.0` TypeScript values; first-push
|
|
51
|
+
zero SHAs and resumable npm release assets are handled safely.
|
|
52
|
+
|
|
53
|
+
Release note: `docs/releases/3.1.0.md`.
|
|
54
|
+
|
|
55
|
+
## 3.0.5 — 2026-07-14
|
|
56
|
+
|
|
57
|
+
Codex host skill catalog + residual honesty. **No breaking** CLI or `ark.config.json`
|
|
58
|
+
changes. **No gate weaken.**
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- **Codex `/ark-*` skills not invocable:** install wrote flat `.codex/prompts/*.md`, which
|
|
63
|
+
Codex does not load as skills. Repo catalog is now `.agents/skills/<name>/SKILL.md`
|
|
64
|
+
(Agent Skills REPO scope); optional home catalog is `$CODEX_HOME/skills/<name>/SKILL.md`
|
|
65
|
+
via `--codex-home`. Post-install verifies AGENTS.md `/ark-*` refs against each selected
|
|
66
|
+
host catalog.
|
|
67
|
+
- **Temp-root MCP footgun:** `--codex-home` no longer rebinds primary `[mcp_servers.ark]` in
|
|
68
|
+
the default `~/.codex/config.toml` when the project root is a temp/upgrade path (skills may
|
|
69
|
+
still refresh under an isolated or real home).
|
|
70
|
+
- **Multi-host skill hints:** Codex legacy-prompts-only debt no longer suppresses missing/stale
|
|
71
|
+
skill reports for Claude/Cursor/other hosts in doctor and `ark-check` human output.
|
|
72
|
+
- **Deferred Codex home debt severity:** outside a Codex session, home skill gaps are dim/info
|
|
73
|
+
(not warn) and are not Top actions; when the session host is Codex they stay warn + fix.
|
|
74
|
+
|
|
75
|
+
### Added
|
|
76
|
+
|
|
77
|
+
- **Skill parity sensors:** missing / stale / legacy-prompts-only for repo and home catalogs,
|
|
78
|
+
with package `arkVersion` stamps; doctor and JSON expose concrete refresh fixes
|
|
79
|
+
(`--skills-only --tools codex` and/or `--codex-home`).
|
|
80
|
+
- **CI fail-closed detection:** workflows with ark-check but only `--strict-config` (or no
|
|
81
|
+
strict flags) surface `enforcement-ci-not-fail-closed` (warn) with a `--strict-merge` fix.
|
|
82
|
+
`--strict` / `--strict-merge` / `--require-gates` count as fail-closed. Merge-gate inventory
|
|
83
|
+
evidence requires that fail-closed profile.
|
|
84
|
+
- **Codex write-path honesty:** install and doctor state local Codex write is advisory (MCP +
|
|
85
|
+
best-effort hooks; not Claude/Grok hard-write + repair); CI `--strict-merge` + required
|
|
86
|
+
status is the hard merge backstop.
|
|
87
|
+
|
|
88
|
+
Release note: `docs/releases/3.0.5.md`.
|
|
8
89
|
|
|
9
90
|
## 3.0.4 — 2026-07-14
|
|
10
91
|
|
package/README.md
CHANGED
|
@@ -136,7 +136,7 @@ npx arkgate-check --install-agent-gates --force
|
|
|
136
136
|
npx arkgate-check --doctor
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
Full checklist (CI, MCP, Codex, imports): **[
|
|
139
|
+
Full checklist (CI, MCP, Codex, imports): **[migrate-from-ark-runtime-kernel.md](https://github.com/pedroknigge/arkgate/blob/main/docs/migrate-from-ark-runtime-kernel.md)**.
|
|
140
140
|
|
|
141
141
|
---
|
|
142
142
|
|
|
@@ -199,6 +199,20 @@ constrain + validate + optional `autoPatch` + `judgmentBrief`). PreToolUse hooks
|
|
|
199
199
|
never silent write). Cursor/Codex MCP calls remain advisory. See
|
|
200
200
|
[docs/ai-gates.md](docs/ai-gates.md).
|
|
201
201
|
|
|
202
|
+
For a complete multi-file architecture-source candidate, use MCP **`ark_prepare_change`** or
|
|
203
|
+
`ark preflight --changes change-set.json --json`. Creates, updates, and deletes are evaluated as
|
|
204
|
+
one read-only graph, so an edge or cycle that appears only across the batch is rejected before any
|
|
205
|
+
project file is written. With `--change-map map.json` (or MCP `changeMap`), the same verdict also
|
|
206
|
+
classifies planned structure as satisfied, missing, contradictory, or unplanned. This is structural
|
|
207
|
+
convergence only: behavioral completion is always reported as not evaluated.
|
|
208
|
+
|
|
209
|
+
Every blocking diagnostic carries stable rule/location/evidence fields plus one deterministic
|
|
210
|
+
`nextAction`; human CLI/hook text prints that same action. A complete Codex `ApplyPatch` payload is
|
|
211
|
+
reconstructed and sent through the same atomic engine before per-file safety checks. Codex remains
|
|
212
|
+
honestly bypassable/advisory because not every Code Mode write dispatches the project hook. The
|
|
213
|
+
verdict depends only on the explicit contract and candidate—not `AGENTS.md`, skills, injected prose,
|
|
214
|
+
or an LLM.
|
|
215
|
+
|
|
202
216
|
| Need | Skill | Not |
|
|
203
217
|
|------|--------|-----|
|
|
204
218
|
| Only the apply loop for plan **A** (edges) | `/ark-loop` | empty A + design residual → explore |
|
|
@@ -245,12 +259,16 @@ ark.config.json
|
|
|
245
259
|
|
|
246
260
|
- **Presets:** hexagonal, layered, feature-sliced, monorepo, ui-surface, vertical-slice, ddd-bounded-contexts (+ aliases clean-architecture / onion-architecture). Layers start optional; doctor suggests tightening populated cores. Cross-slice / cross-context bans use optional `peerIsolation` rules.
|
|
247
261
|
- **Versioned config:** generated contracts include `$schema` + `schemaVersion`; CLI, MCP, and
|
|
248
|
-
ESLint validate through the same loader. Unknown keys fail with their JSON path.
|
|
249
|
-
|
|
262
|
+
ESLint validate through the same loader. Unknown keys fail with their JSON path. Strict merge
|
|
263
|
+
also compares the contract transition and blocks unacknowledged weakening with hashes and stable
|
|
264
|
+
finding ids. See the [configuration and editor guide](docs/configuration.md).
|
|
250
265
|
- **Frameworks:** Nest / Next / express / library layouts get sensible globs on init so day-one coverage is real.
|
|
251
266
|
- **Brownfield:** baseline ratchet, refuse to freeze a wrong contract, `/ark-adopt` for mature trees.
|
|
252
267
|
- **Agents:** `ark start` asks for (or detects) one active host and writes one compact router, not copied skill packs, in at most five project files and 25 KB. Use `ark-check --install-agent-gates --skills-only --tools <host>` later when you explicitly want the full `/ark-*` skill set. Reports are opt-in with `ark-check --report`.
|
|
253
268
|
- **Write protocol (2.10 / Track W):** mechanical-safe **autoPatch** on the write gate (`import type`); MCP **`ark_prepare_write`** (place + validate + patch + judgmentBrief); opt-in hook **`--hook-repair`** (`ARK_REPAIR_JSON`); doctor **`writePath`** (repair vs reject-only); loop-cost eval (`npm run eval:loop-cost`). Port-proof inject is **judgment** (arity change), not silent auto-apply.
|
|
269
|
+
- **Enforcement ladder (Phase T):** doctor JSON exposes `writePath.enforcementLadder` with separate
|
|
270
|
+
`supported`, `installed`, `active`, `bypassable`, evidence, operation coverage, and required-status
|
|
271
|
+
honesty. Hook repair JSON carries the operation-scoped ladder; MCP alone remains advisory.
|
|
254
272
|
- **Fail-closed CI (2.11):** `--strict-merge` combines config coverage, shared gate-file
|
|
255
273
|
presence, and bypass diagnostics for dynamic imports, TypeScript suppressions, explicit `any`
|
|
256
274
|
casts, InMemory runtime defaults, and disabled peer isolation. `--strict` is a compatibility
|
|
@@ -288,12 +306,14 @@ npx arkgate start --tools codex --apply # select the host explicitly
|
|
|
288
306
|
npx arkgate start --install --apply # also add arkgate to package.json (explicit only)
|
|
289
307
|
npx arkgate start --remove-host codex # preview compact-host removal; add --apply to confirm
|
|
290
308
|
npx arkgate-check --doctor # health + Adoption gaps (not just fitness)
|
|
291
|
-
npx arkgate-check --doctor --json #
|
|
309
|
+
npx arkgate-check --doctor --json # adoption + explicit writePath.enforcementLadder
|
|
292
310
|
npx arkgate-check --strict # fail-closed CI + installed-gate/safety checks
|
|
293
311
|
npx arkgate-check --plan # safe-to-auto-fix vs your call
|
|
294
312
|
npx arkgate-check --coverage # Governed: N%
|
|
295
313
|
npx arkgate-check --report ark-report.html # showcase HTML (opens in browser on local TTY; --no-open to skip)
|
|
296
314
|
npx arkgate-check --baseline # only NEW violations fail
|
|
315
|
+
npx arkgate preflight --changes changes.json --json # atomic read-only batch verdict
|
|
316
|
+
npx arkgate preflight --changes changes.json --change-map map.json --json # intent hash + structural convergence
|
|
297
317
|
npx arkgate upgrade # package + gates/skills + MCP/Codex normalize
|
|
298
318
|
```
|
|
299
319
|
|
|
@@ -314,7 +334,7 @@ separate experimental package:
|
|
|
314
334
|
|
|
315
335
|
```ts
|
|
316
336
|
import { createStrictArkKernelFromConfig } from '@arkgate/runtime';
|
|
317
|
-
// see
|
|
337
|
+
// see the repository production-hardening and package-surface guides
|
|
318
338
|
```
|
|
319
339
|
|
|
320
340
|
The stable `arkgate` package does not bundle runtime implementation. The deprecated
|
|
@@ -328,7 +348,7 @@ The kernel’s default stores (`InMemoryEventBuffer`, `InMemoryAuditStore`,
|
|
|
328
348
|
`InMemoryReadModelStore`, `InMemoryWorkflowStore`) are **reference in-memory only**:
|
|
329
349
|
fine for tests, demos, and single-process local work — they **do not** survive restarts
|
|
330
350
|
and are **not** production durability. Implement the store interfaces (or inject your own)
|
|
331
|
-
for real systems. Details: [
|
|
351
|
+
for real systems. Details: [production-hardening.md](https://github.com/pedroknigge/arkgate/blob/main/docs/production-hardening.md).
|
|
332
352
|
|
|
333
353
|
---
|
|
334
354
|
|
|
@@ -340,12 +360,12 @@ for real systems. Details: [docs/production-hardening.md](docs/production-harden
|
|
|
340
360
|
| **Package surface (stable vs experimental)** | [docs/package-surface.md](docs/package-surface.md) |
|
|
341
361
|
| Wire Claude / Cursor / Codex / Grok + **ESLint (CI-parity)** | [docs/ai-gates.md](docs/ai-gates.md) |
|
|
342
362
|
| **TypeScript 5 / 6 / 7 support** | [docs/typescript-support.md](docs/typescript-support.md) |
|
|
343
|
-
| Migrate from `ark-runtime-kernel` | [docs/migrate-from-ark-runtime-kernel.md](docs/migrate-from-ark-runtime-kernel.md) |
|
|
363
|
+
| Migrate from `ark-runtime-kernel` | [docs/migrate-from-ark-runtime-kernel.md](https://github.com/pedroknigge/arkgate/blob/main/docs/migrate-from-ark-runtime-kernel.md) |
|
|
344
364
|
| Messy existing repo | [docs/brownfield-adoption.md](docs/brownfield-adoption.md) |
|
|
345
365
|
| Agent / MCP tools | [docs/agent-guide.md](docs/agent-guide.md) |
|
|
346
366
|
| Demos | [docs/demos/](docs/demos/) |
|
|
347
367
|
| Examples | [examples/](examples/README.md) |
|
|
348
|
-
|
|
|
368
|
+
| Latest release (3.1.0) | [release notes](docs/releases/3.1.0.md) · [3.0.0 baseline](docs/releases/3.0.0.md) |
|
|
349
369
|
| Roadmap | [ROADMAP.md](ROADMAP.md) · [Changelog](CHANGELOG.md) |
|
|
350
370
|
|
|
351
371
|
---
|
|
@@ -363,7 +383,7 @@ npm run check:architecture # Ark gates itself
|
|
|
363
383
|
**npm:** [`arkgate`](https://www.npmjs.com/package/arkgate) · formerly `ark-runtime-kernel`
|
|
364
384
|
**Product:** **ArkGate** — architecture co-pilot / gate for AI TypeScript (not a runtime kernel).
|
|
365
385
|
CLI: `arkgate` · `arkgate-check` · `arkgate-mcp` (aliases `ark` / `ark-check` / `ark-mcp` still work for one major).
|
|
366
|
-
MCP registry: `io.github.pedroknigge/arkgate
|
|
386
|
+
MCP registry: [`io.github.pedroknigge/arkgate`](https://registry.modelcontextprotocol.io/) (`server.json` @ package version).
|
|
367
387
|
**Source:** [github.com/pedroknigge/arkgate](https://github.com/pedroknigge/arkgate)
|
|
368
388
|
|
|
369
389
|
Node ≥ 18 · **MIT**.
|
package/bin/ark-check.mjs
CHANGED
|
@@ -33,7 +33,9 @@ import {
|
|
|
33
33
|
loadTypeScript,
|
|
34
34
|
detectSkillGaps,
|
|
35
35
|
detectCodexHomeGap,
|
|
36
|
-
|
|
36
|
+
detectCodexRepoSkillGap,
|
|
37
|
+
codexConcernIsActive,
|
|
38
|
+
printSkillAndCodexGapHints,
|
|
37
39
|
missingGates,
|
|
38
40
|
staleRunnerGateFiles,
|
|
39
41
|
brokenMcpGateFiles,
|
|
@@ -44,7 +46,6 @@ import {
|
|
|
44
46
|
arkPackageVersion,
|
|
45
47
|
compactRouterHost,
|
|
46
48
|
REQUIRED_GATE_FILES,
|
|
47
|
-
codexPromptsDir,
|
|
48
49
|
detectWritePathCapabilities,
|
|
49
50
|
} from './lib/agent-gates.mjs';
|
|
50
51
|
import { syncBaselineIntoCheckSurfaces } from './lib/field-install.mjs';
|
|
@@ -98,6 +99,7 @@ import {
|
|
|
98
99
|
} from './lib/config-warnings.mjs';
|
|
99
100
|
import { runArchitectureScan } from './lib/architecture-scan.mjs';
|
|
100
101
|
import { validateHardWriteRequest } from './lib/enforcement-profiles.mjs';
|
|
102
|
+
import { analyzePolicyTransition } from './lib/policy-delta-io.mjs';
|
|
101
103
|
|
|
102
104
|
|
|
103
105
|
function parseArgs(argv) {
|
|
@@ -109,6 +111,7 @@ function parseArgs(argv) {
|
|
|
109
111
|
tsconfig: undefined,
|
|
110
112
|
json: false,
|
|
111
113
|
strictConfig: false,
|
|
114
|
+
strictMerge: false,
|
|
112
115
|
requireGates: false,
|
|
113
116
|
requireWriteHook: undefined,
|
|
114
117
|
init: false,
|
|
@@ -118,6 +121,9 @@ function parseArgs(argv) {
|
|
|
118
121
|
force: false,
|
|
119
122
|
skillsOnly: false,
|
|
120
123
|
baseline: undefined,
|
|
124
|
+
policyBase: undefined,
|
|
125
|
+
policyBaseRef: undefined,
|
|
126
|
+
policyAck: undefined,
|
|
121
127
|
updateBaseline: false,
|
|
122
128
|
noCache: false,
|
|
123
129
|
coverage: false,
|
|
@@ -148,6 +154,7 @@ function parseArgs(argv) {
|
|
|
148
154
|
else if (arg === '--strict' || arg === '--strict-merge') {
|
|
149
155
|
args.strictConfig = true;
|
|
150
156
|
args.requireGates = true;
|
|
157
|
+
args.strictMerge = true;
|
|
151
158
|
}
|
|
152
159
|
else if (arg === '--strict-config') args.strictConfig = true;
|
|
153
160
|
else if (arg === '--require-gates') args.requireGates = true;
|
|
@@ -204,6 +211,9 @@ function parseArgs(argv) {
|
|
|
204
211
|
const next = argv[i + 1];
|
|
205
212
|
args.baseline = next && !next.startsWith('-') ? argv[++i] : '.ark-baseline.json';
|
|
206
213
|
}
|
|
214
|
+
else if (arg === '--policy-base') args.policyBase = requireValue(arg, i++);
|
|
215
|
+
else if (arg === '--policy-base-ref') args.policyBaseRef = requireValue(arg, i++);
|
|
216
|
+
else if (arg === '--policy-ack') args.policyAck = requireValue(arg, i++);
|
|
207
217
|
else if (arg === '--root') args.root = path.resolve(requireValue(arg, i++));
|
|
208
218
|
else if (arg === '--config') args.config = requireValue(arg, i++);
|
|
209
219
|
else if (arg === '--manifest') args.manifest = requireValue(arg, i++);
|
|
@@ -229,7 +239,7 @@ function usage() {
|
|
|
229
239
|
return [
|
|
230
240
|
'Usage: arkgate-check | ark-check (identical bins; product name ArkGate)',
|
|
231
241
|
' ark-check --version',
|
|
232
|
-
' ark-check --root <project> --config <ark.config.json> [--manifest <ark.manifest.json>] [--tsconfig <tsconfig.json>] [--strict-merge | --strict | --strict-config] [--require-gates] [--require-write-hook <host>] [--json] [--baseline [file]] [--report [file.html]] [--no-cache]',
|
|
242
|
+
' ark-check --root <project> --config <ark.config.json> [--manifest <ark.manifest.json>] [--tsconfig <tsconfig.json>] [--strict-merge | --strict | --strict-config] [--policy-base <file> | --policy-base-ref <git-ref>] [--policy-ack <file>] [--require-gates] [--require-write-hook <host>] [--json] [--baseline [file]] [--report [file.html]] [--no-cache]',
|
|
233
243
|
' ark-check --coverage [--json] per-layer file counts + full unclassified list (report only, exit 0)',
|
|
234
244
|
' ark-check --plan [--json] classified remediation plan (mechanical-safe / judgment / deferred) + goal; report only',
|
|
235
245
|
' ark-check --recommend [--json] [--write-plan] application-shape plan; --write-plan emits ark-adoption-plan.json',
|
|
@@ -286,6 +296,10 @@ function usage() {
|
|
|
286
296
|
'Use --strict-merge for the fail-closed CI profile: --strict-config + --require-gates',
|
|
287
297
|
'plus the security diagnostics surfaced by doctor. --strict is a compatibility alias.',
|
|
288
298
|
'This merge profile never depends on an editor/agent hook.',
|
|
299
|
+
'When a Git merge base is available, --strict-merge classifies the ark.config.json',
|
|
300
|
+
'transition. Weakening or judgment-required findings fail unless --policy-ack names',
|
|
301
|
+
'every finding and is bound to both policy hashes. Use --policy-base/--policy-base-ref',
|
|
302
|
+
'for an explicit comparison; ARK_POLICY_BASE_REF is the CI environment equivalent.',
|
|
289
303
|
'Add --require-write-hook claude|grok to validate a hard local write boundary for that',
|
|
290
304
|
'specific host. Cursor and Codex expose advisory MCP tools plus the shared CI check;',
|
|
291
305
|
'merge blocking requires repository policy to make that status required.',
|
|
@@ -301,8 +315,8 @@ function usage() {
|
|
|
301
315
|
'(instruction-tier rule files derived from the same contract).',
|
|
302
316
|
'It also installs the /ark-* skills shipped in templates/skills/ into each',
|
|
303
317
|
'detected tool\'s command location (.claude/skills/, .cursor/commands/,',
|
|
304
|
-
'.
|
|
305
|
-
'.github/prompts/).',
|
|
318
|
+
'.agents/skills/ (Codex REPO catalog), .grok/skills/, .windsurf/workflows/,',
|
|
319
|
+
'.clinerules/workflows/, .github/prompts/).',
|
|
306
320
|
'Kiro, Roo, Continue, and Gemini have no command mechanism and receive only their',
|
|
307
321
|
'rule file. Existing files are never overwritten without --force, so re-running',
|
|
308
322
|
'after an update only adds what is missing. --skills-only restricts the write to',
|
|
@@ -1059,6 +1073,15 @@ async function main() {
|
|
|
1059
1073
|
|
|
1060
1074
|
const root = args.root;
|
|
1061
1075
|
const config = readConfig(root, args.config);
|
|
1076
|
+
const policyDelta = analyzePolicyTransition({
|
|
1077
|
+
root,
|
|
1078
|
+
configPath: args.config,
|
|
1079
|
+
candidateConfig: config,
|
|
1080
|
+
strictMerge: args.strictMerge,
|
|
1081
|
+
basePath: args.policyBase,
|
|
1082
|
+
baseRef: args.policyBaseRef,
|
|
1083
|
+
acknowledgementPath: args.policyAck,
|
|
1084
|
+
});
|
|
1062
1085
|
const manifest = readManifest(root, args.manifest);
|
|
1063
1086
|
const rules = manifest?.architecture?.rules ?? config.rules;
|
|
1064
1087
|
const files = collectGovernedFiles(root, config);
|
|
@@ -1215,7 +1238,9 @@ async function main() {
|
|
|
1215
1238
|
// Soft/advisory warnings (failsStrict === false) never fail --strict-config.
|
|
1216
1239
|
const strictWarnings = warnings.filter((w) => w.failsStrict !== false);
|
|
1217
1240
|
const ok =
|
|
1218
|
-
activeViolations.length === 0 &&
|
|
1241
|
+
activeViolations.length === 0 &&
|
|
1242
|
+
(!args.strictConfig || strictWarnings.length === 0) &&
|
|
1243
|
+
(policyDelta?.valid ?? true);
|
|
1219
1244
|
|
|
1220
1245
|
if (args.plan) {
|
|
1221
1246
|
const cov = computeCoverage(root, config, files, rules);
|
|
@@ -1229,6 +1254,8 @@ async function main() {
|
|
|
1229
1254
|
|
|
1230
1255
|
const skillGaps = detectSkillGaps(root);
|
|
1231
1256
|
const codexHomeGap = detectCodexHomeGap(root);
|
|
1257
|
+
const codexRepoSkillGap = detectCodexRepoSkillGap(root);
|
|
1258
|
+
const codexSessionActive = codexConcernIsActive();
|
|
1232
1259
|
|
|
1233
1260
|
if (args.report) {
|
|
1234
1261
|
const exampleByLayer = new Map();
|
|
@@ -1372,7 +1399,16 @@ async function main() {
|
|
|
1372
1399
|
warnings,
|
|
1373
1400
|
...(activeViolations.length > 0 ? { summary: summarizeViolations(activeViolations) } : {}),
|
|
1374
1401
|
...(skillGaps.length > 0 ? { skillGaps } : {}),
|
|
1375
|
-
...(codexHomeGap
|
|
1402
|
+
...(codexHomeGap
|
|
1403
|
+
? {
|
|
1404
|
+
codexHomeGap: {
|
|
1405
|
+
...codexHomeGap,
|
|
1406
|
+
deferred: !codexSessionActive,
|
|
1407
|
+
},
|
|
1408
|
+
}
|
|
1409
|
+
: {}),
|
|
1410
|
+
...(codexRepoSkillGap ? { codexRepoSkillGap } : {}),
|
|
1411
|
+
...(policyDelta ? { policyDelta } : {}),
|
|
1376
1412
|
}, null, 2));
|
|
1377
1413
|
} else {
|
|
1378
1414
|
for (const warning of warnings) {
|
|
@@ -1391,7 +1427,22 @@ async function main() {
|
|
|
1391
1427
|
)
|
|
1392
1428
|
);
|
|
1393
1429
|
}
|
|
1394
|
-
if (
|
|
1430
|
+
if (policyDelta && !policyDelta.valid) {
|
|
1431
|
+
for (const finding of policyDelta.findings.filter(
|
|
1432
|
+
({ classification }) =>
|
|
1433
|
+
classification === 'weakening' || classification === 'judgment-required'
|
|
1434
|
+
)) {
|
|
1435
|
+
console.error(
|
|
1436
|
+
`${color.red('policy')} ${finding.classification} ${finding.path}: ${finding.message}`
|
|
1437
|
+
);
|
|
1438
|
+
console.error(` Next: ${finding.nextAction}`);
|
|
1439
|
+
}
|
|
1440
|
+
console.error(
|
|
1441
|
+
`Policy transition blocked (${policyDelta.basePolicyHash} → ${policyDelta.candidatePolicyHash}). ` +
|
|
1442
|
+
'Provide --policy-ack with the exact hashes, finding ids, and a non-empty reason.'
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
if (activeViolations.length === 0 && (policyDelta?.valid ?? true)) {
|
|
1395
1446
|
const advisoryOnly = warnings.length > 0 && strictWarnings.length === 0;
|
|
1396
1447
|
if (warnings.length === 0) {
|
|
1397
1448
|
console.log(`${color.green('✔')} Ark check passed.${baselineNote}`);
|
|
@@ -1410,7 +1461,9 @@ async function main() {
|
|
|
1410
1461
|
}
|
|
1411
1462
|
} else {
|
|
1412
1463
|
console.error(
|
|
1413
|
-
|
|
1464
|
+
activeViolations.length > 0
|
|
1465
|
+
? `${color.red('✖')} ${activeViolations.length} violation(s).${baselineNote}`
|
|
1466
|
+
: `${color.red('✖')} Policy transition rejected.${baselineNote}`
|
|
1414
1467
|
);
|
|
1415
1468
|
}
|
|
1416
1469
|
|
|
@@ -1420,30 +1473,13 @@ async function main() {
|
|
|
1420
1473
|
printViolationBreakdown(summarizeViolations(activeViolations), { toStderr: true });
|
|
1421
1474
|
}
|
|
1422
1475
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
`${missingTotal} /ark-* skill(s) not installed for ${tools} (this Ark version ships them). ` +
|
|
1431
|
-
`Install: ${arkCommand(root, 'ark-check', '--install-agent-gates')}`
|
|
1432
|
-
)
|
|
1433
|
-
);
|
|
1434
|
-
}
|
|
1435
|
-
if (staleTotal > 0) {
|
|
1436
|
-
// Stale skills already exist, so refreshing needs --force. --skills-only
|
|
1437
|
-
// scopes the overwrite to the canonical skills, leaving a customized
|
|
1438
|
-
// AGENTS.md / settings / CI untouched (a bare --force would clobber them).
|
|
1439
|
-
console.log(
|
|
1440
|
-
color.dim(
|
|
1441
|
-
`${staleTotal} /ark-* skill(s) outdated for ${tools} (this Ark ships newer versions). ` +
|
|
1442
|
-
`Refresh: ${arkCommand(root, 'ark-check', '--install-agent-gates --skills-only --force')}`
|
|
1443
|
-
)
|
|
1444
|
-
);
|
|
1445
|
-
}
|
|
1446
|
-
}
|
|
1476
|
+
printSkillAndCodexGapHints(root, {
|
|
1477
|
+
skillGaps,
|
|
1478
|
+
codexHomeGap,
|
|
1479
|
+
codexRepoSkillGap,
|
|
1480
|
+
codexSessionActive,
|
|
1481
|
+
color,
|
|
1482
|
+
});
|
|
1447
1483
|
|
|
1448
1484
|
const staleRunners = staleRunnerGateFiles(root);
|
|
1449
1485
|
if (staleRunners.length > 0) {
|
|
@@ -1464,27 +1500,6 @@ async function main() {
|
|
|
1464
1500
|
)
|
|
1465
1501
|
);
|
|
1466
1502
|
}
|
|
1467
|
-
|
|
1468
|
-
if (codexHomeGap) {
|
|
1469
|
-
const parts = [];
|
|
1470
|
-
if (codexHomeGap.missing > 0) parts.push(`${codexHomeGap.missing} missing`);
|
|
1471
|
-
if (codexHomeGap.stale > 0) parts.push(`${codexHomeGap.stale} outdated`);
|
|
1472
|
-
// Advisory always; when session host is known and not Codex, say so so
|
|
1473
|
-
// /ark-upgrade does not chase home prompts as Incomplete.
|
|
1474
|
-
const activeHost = detectActiveAgentHost();
|
|
1475
|
-
const deferredNote =
|
|
1476
|
-
activeHost != null && activeHost !== 'codex'
|
|
1477
|
-
? ' Deferred unless you use Codex — not a blocker for Grok/Claude/Cursor. '
|
|
1478
|
-
: ' ';
|
|
1479
|
-
console.log(
|
|
1480
|
-
color.dim(
|
|
1481
|
-
`/ark-* skills in ${codexPromptsDir()} are behind this Ark (${parts.join(', ')}).` +
|
|
1482
|
-
deferredNote +
|
|
1483
|
-
`Codex loads them from $CODEX_HOME/prompts, not the repo. ` +
|
|
1484
|
-
`When using Codex: ${arkCommand(root, 'ark-check', '--install-agent-gates --skills-only --codex-home --force')}`
|
|
1485
|
-
)
|
|
1486
|
-
);
|
|
1487
|
-
}
|
|
1488
1503
|
}
|
|
1489
1504
|
|
|
1490
1505
|
if (args.watch) {
|