arkgate 4.1.0 → 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.
- package/CHANGELOG.md +124 -2
- package/README.md +24 -14
- package/bin/ark-check-runtime.mjs +16 -5
- package/bin/ark-mcp-runtime.mjs +766 -64
- package/bin/lib/agent-gates.mjs +1 -0
- package/bin/lib/ark-gitignore.mjs +88 -0
- package/bin/lib/ci-and-commands.mjs +33 -8
- package/bin/lib/codex-home.mjs +90 -8
- package/bin/lib/design-smells.mjs +71 -9
- package/bin/lib/doctor-plan.mjs +47 -39
- package/bin/lib/effective-contract-load.mjs +73 -9
- package/bin/lib/enforcement-honesty.mjs +78 -22
- package/bin/lib/enforcement-state.mjs +1 -1
- package/bin/lib/gate-files.mjs +441 -9
- package/bin/lib/github-enforcement.mjs +168 -7
- package/bin/lib/hook-templates.mjs +12 -11
- package/bin/lib/host-support-matrix.mjs +91 -17
- package/bin/lib/html-report-depth.mjs +13 -2
- package/bin/lib/html-report-evolution.mjs +114 -0
- package/bin/lib/html-report.mjs +18 -97
- package/bin/lib/import-resolve.mjs +33 -11
- package/bin/lib/install-activation.mjs +87 -0
- package/bin/lib/install-migrate.mjs +66 -50
- package/bin/lib/managed-upgrade.mjs +10 -41
- package/bin/lib/mcp-adoption.mjs +15 -5
- package/bin/lib/pilot-loop.mjs +25 -8
- package/bin/lib/project-identity.mjs +103 -0
- package/bin/lib/report-snapshot-context.mjs +28 -0
- package/bin/lib/resident-hook.mjs +33 -9
- package/bin/lib/rules-inventory.mjs +100 -8
- package/bin/lib/skill-install.mjs +272 -22
- package/bin/lib/skill-write.mjs +899 -0
- package/bin/lib/start-preview.mjs +84 -1
- package/bin/lib/upgrade-command.mjs +2 -5
- package/bin/lib/write-path-detect.mjs +2 -2
- package/dist/index.cjs +13 -13
- package/dist/index.d.ts +194 -2
- package/dist/index.js +13 -13
- package/docs/README.md +6 -4
- package/docs/agent-guide.md +115 -17
- package/docs/ai-gates.md +133 -25
- package/docs/assets/ark-write-gate.svg +2 -2
- package/docs/develop.md +16 -6
- package/docs/enthusiast/how-to-agent-gates.md +6 -0
- package/docs/package-surface.md +16 -9
- package/docs/product-voice.md +22 -4
- package/docs/use.md +3 -1
- package/package.json +3 -1
- package/schemas/ark.project-identity.schema.json +116 -0
- package/server.json +2 -2
- package/templates/skills/ark-adopt.md +9 -0
- package/templates/skills/ark-architect.md +12 -2
- package/templates/skills/ark-autopilot.md +9 -0
- package/templates/skills/ark-contract.md +11 -1
- package/templates/skills/ark-coverage.md +9 -0
- package/templates/skills/ark-explain.md +13 -1
- package/templates/skills/ark-explore.md +9 -0
- package/templates/skills/ark-fix.md +10 -1
- package/templates/skills/ark-loop.md +11 -2
- package/templates/skills/ark-place.md +17 -6
- package/templates/skills/ark-runtime.md +8 -0
- package/templates/skills/ark-think.md +14 -2
- package/templates/skills/ark-upgrade.md +9 -0
package/docs/README.md
CHANGED
|
@@ -52,13 +52,15 @@ These are **not** the day-to-day product path. They stay in the repo for evidenc
|
|
|
52
52
|
| Area | Path |
|
|
53
53
|
|------|------|
|
|
54
54
|
| Release notes (by version) | [releases/](releases/) · [CHANGELOG.md](../CHANGELOG.md) |
|
|
55
|
-
| Epic plans (seeded + shipped) | [plans/](plans/) |
|
|
55
|
+
| Epic plans (seeded + shipped) | [plans/](plans/) · active: [workspace identity and activation truth](plans/workspace-identity-activation-truth/README.md) (`WI01`, 4.2.0 corrective minor) |
|
|
56
56
|
| Claims audit | [audit/claims-matrix.md](audit/claims-matrix.md) |
|
|
57
57
|
| Field adoption kit (scaffolding, not closed) | [field/](field/) |
|
|
58
58
|
| Runtime hardening (experimental) | [production-hardening.md](production-hardening.md) |
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
Prepared candidate: [releases/4.2.0.md](releases/4.2.0.md) (`arkgate@4.2.0`, not published).
|
|
61
|
+
|
|
62
|
+
Current published: [releases/4.1.1.md](releases/4.1.1.md) (`arkgate@4.1.1` on npm `latest`).
|
|
63
|
+
Previous: [releases/4.1.0.md](releases/4.1.0.md) (`arkgate@4.1.0`).
|
|
62
64
|
Previous major: [releases/4.0.0.md](releases/4.0.0.md) (`arkgate@4.0.0`).
|
|
63
65
|
Config: [configuration.md](configuration.md) · Agent skills dual-plane: [agent-guide.md](agent-guide.md).
|
|
64
66
|
|
|
@@ -68,5 +70,5 @@ Config: [configuration.md](configuration.md) · Agent skills dual-plane: [agent-
|
|
|
68
70
|
|
|
69
71
|
1. **Audience first** — every page should be use, develop, or contribute.
|
|
70
72
|
2. **One primary flow** — `start` → doctor → optional guided work.
|
|
71
|
-
3. **Honest hardness** — host write guarantees differ;
|
|
73
|
+
3. **Honest hardness** — host write guarantees differ; a **required GitHub status context** running the merge CLI is the shared hard boundary.
|
|
72
74
|
4. **History is not the product** — version archaeology lives under `releases/` and `plans/`, not the front door.
|
package/docs/agent-guide.md
CHANGED
|
@@ -40,9 +40,18 @@ npx ark-check --install-agent-gates --skills-only --force
|
|
|
40
40
|
|
|
41
41
|
**Write-path honesty:** Claude/Grok/Antigravity can hard-block listed PreToolUse ops when
|
|
42
42
|
installed and trusted. Cursor/Codex/OpenCode remain **advisory at write**. For every host, the
|
|
43
|
-
repository-wide hard boundary is a **required
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
repository-wide hard boundary is a **required GitHub status context** that runs
|
|
44
|
+
`arkgate-check --strict-merge` (alias `ark-check --strict-merge`) — the CLI name is not the
|
|
45
|
+
status context name. Never claim Cursor/Codex/OpenCode hard write. Soft-write alone does not mean
|
|
46
|
+
the project is unfinished; doctor keeps it as an environment residual. See [ai-gates.md](ai-gates.md)
|
|
47
|
+
and the README host matrix.
|
|
48
|
+
|
|
49
|
+
**MCP project identity (4.2.0):** before trusting project-specific MCP evidence, call
|
|
50
|
+
`ark_identity` with `project.expectedRoot` set to the exact project's absolute root. Reuse that
|
|
51
|
+
root plus the returned `projectIdentity.projectId` on every later Ark tool call. A descendant
|
|
52
|
+
path is authoritative only when that matching project id is also supplied. Only
|
|
53
|
+
`binding.status: "matched"` with `authoritative: true` is authoritative; calls that omit the
|
|
54
|
+
expectation remain compatible but are explicitly `unverified`.
|
|
46
55
|
|
|
47
56
|
## Architecture playbook and `ark-check --recommend`
|
|
48
57
|
|
|
@@ -110,6 +119,10 @@ baseline. Do not `--reset-origin` unless the user explicitly wants a new baselin
|
|
|
110
119
|
`ark-check --report --no-archive` still creates `origin.*` on the first report (or on an explicit
|
|
111
120
|
reset) and refreshes `latest.*`; it skips only the timestamped JSON file under
|
|
112
121
|
`.ark/reports/history/`.
|
|
122
|
+
Snapshots record best-effort, shell-free Git provenance (`HEAD`, attached branch, and dirty
|
|
123
|
+
worktree state). Evolution keeps raw metrics visible across ArkGate upgrades, but an Ark score
|
|
124
|
+
delta is comparable—and therefore rendered—only when origin and current snapshots use the same
|
|
125
|
+
ArkGate version.
|
|
113
126
|
|
|
114
127
|
Once the **raw** graph has zero violations (the baseline is deliberately ignored) and governed
|
|
115
128
|
coverage is at least 50%, `ark-check --ratchet-cores` changes `optional: true` to
|
|
@@ -128,7 +141,9 @@ brownfield Align/Stabilize + seed Shape B. `/ark-loop` = plan A only. Empty plan
|
|
|
128
141
|
“architecture healthy” if design-weak residual remains. Full routing table: full-install
|
|
129
142
|
`AGENTS.md` / [README expert skills](../README.md#expert-skills-escapes--not-onboarding).
|
|
130
143
|
|
|
131
|
-
**Design fitness (3.0.1+ / Phase Q 3.0.3):** after edges are clean, doctor can still
|
|
144
|
+
**Design fitness (3.0.1+ / Phase Q 3.0.3):** after checked edges are clean, doctor can still
|
|
145
|
+
report **SUGGEST / ADAPT / ENFORCE · design-weak** using the mode it actually observed; a weak
|
|
146
|
+
design does not imply that enforcement is active.
|
|
132
147
|
|
|
133
148
|
```bash
|
|
134
149
|
npx ark-check --doctor --json # designFitness, designSmells[].outcome, postGreenPath, goldenPattern, pilotLoop
|
|
@@ -143,7 +158,10 @@ npx ark-check --doctor --fail-on-new-smells --base-ref origin/main --json # opt-
|
|
|
143
158
|
**Pilot loop (Q04):** when design-weak, `pilotLoop.nextPilot` is **one** extraction card
|
|
144
159
|
(pilot target, move, success, kill-switch). Apply **that one pilot only**, then re-doctor.
|
|
145
160
|
Success = reduced smell evidence on pilot paths; residual outside the pilot may remain.
|
|
146
|
-
Never
|
|
161
|
+
Never select seed/fixture/demo/migration/generated files as god-module pilots. A real UI business
|
|
162
|
+
rule moves Domain → Application → UI; local permission/UI-state helpers are not selected by their
|
|
163
|
+
`canEdit`-style name alone. Never multi-pilot batch; never mechanical-safe; never claim healthy
|
|
164
|
+
finished while design-weak.
|
|
147
165
|
|
|
148
166
|
**AI-velocity evidence (Q05):** deterministic fixture bench (no live LLM) compares the same
|
|
149
167
|
feature add on design-weak vs golden-path trees. Run `npm run eval:ai-velocity`; metric is
|
|
@@ -454,7 +472,7 @@ npx arkgate-check --install-agent-gates --tools claude,cursor,codex,grok,antigra
|
|
|
454
472
|
|------|-----------------|-------------|
|
|
455
473
|
| Claude Code | `.claude/settings.json` hook + `.mcp.json` / `claude mcp add` | `.claude/skills/<name>/SKILL.md` |
|
|
456
474
|
| Cursor | `.cursor/mcp.json` + `.cursor/rules/ark.mdc` | `.cursor/commands/` |
|
|
457
|
-
| OpenAI Codex | `.codex/config.toml` (project primary, relative `--root
|
|
475
|
+
| OpenAI Codex | `.codex/config.toml` (project primary, relative `--root .`; configured on disk is not runtime-active until restart + `ark_identity` match); optional legacy `$CODEX_HOME/config.toml` fallback uses absolute roots and scoped secondaries — see [ai-gates.md](ai-gates.md) | **Repo:** `.agents/skills/<name>/SKILL.md`; **home:** `$CODEX_HOME/skills/<name>/SKILL.md` (`--codex-home`) |
|
|
458
476
|
| **Grok Build** | `.grok/hooks/ark-write-gate.json` + `.grok/config.toml` / `.mcp.json` | `.grok/skills/<name>/SKILL.md` |
|
|
459
477
|
| Google Antigravity | `.agents/hooks.json` (+ `GEMINI.md` for shared Gemini consumers) | `.agents/skills/<name>/SKILL.md` |
|
|
460
478
|
| OpenCode | `opencode.json` MCP (`type: local`; advisory) | `.opencode/skills/<name>/SKILL.md` |
|
|
@@ -462,6 +480,11 @@ npx arkgate-check --install-agent-gates --tools claude,cursor,codex,grok,antigra
|
|
|
462
480
|
This is a path reference, not a guarantee table. Full copy-paste setups:
|
|
463
481
|
[ai-gates.md](ai-gates.md). Skill inventory: main
|
|
464
482
|
[README](../README.md#other-skills-only-when-you-need-them).
|
|
483
|
+
When several repositories share one machine, repo catalogs stay pinned and isolated; unchanged
|
|
484
|
+
skill bodies are not rewritten for a version stamp. The optional `$CODEX_HOME/skills` catalog is
|
|
485
|
+
monotonic across ArkGate 4.2.0+ installers. Pre-4.2 binaries ignore its metadata and lock, so
|
|
486
|
+
upgrade legacy repos before they write the optional home catalog. See
|
|
487
|
+
[AI gates — Codex skill catalog](ai-gates.md#codex-skill-catalog-skillmd-not-flat-prompts).
|
|
465
488
|
|
|
466
489
|
For an optional executable adoption check, copy the shipped template into a Vitest/Jest suite
|
|
467
490
|
after installing ArkGate:
|
|
@@ -844,17 +867,41 @@ required, and `behavioralCompletion` remains `not-evaluated` even when structure
|
|
|
844
867
|
npx ark-mcp --root . --config ark.config.json [--manifest ark.manifest.json]
|
|
845
868
|
```
|
|
846
869
|
|
|
847
|
-
- **
|
|
848
|
-
`ark.manifest().toJSON()` via `--manifest`. Without that flag, the resource uses every active
|
|
849
|
-
layer and the effective rules from `ark.config.json`; the strict 11-layer profile is the
|
|
850
|
-
fallback only when the project config declares no layers.
|
|
870
|
+
- **Identity handshake** — first call `ark_identity` with:
|
|
851
871
|
|
|
852
|
-
|
|
872
|
+
```json
|
|
873
|
+
{
|
|
874
|
+
"project": {
|
|
875
|
+
"expectedRoot": "/absolute/exact-project-root"
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
Then reuse both `expectedRoot` and the returned `projectIdentity.projectId` as
|
|
881
|
+
`project.expectedProjectId` on every later Ark tool call. `expectedProjectId` without
|
|
882
|
+
`expectedRoot` can detect the wrong id, but it remains non-authoritative because it does not
|
|
883
|
+
prove the current workspace root. The first handshake requires the exact project root; a
|
|
884
|
+
contained descendant becomes authoritative only on later calls that also send the matching
|
|
885
|
+
project id.
|
|
886
|
+
- **Tool `ark_manifest`** — authoritative contract discovery after the identity handshake.
|
|
887
|
+
Serve an exported `ark.manifest().toJSON()` via `--manifest`. Without that flag, the tool uses
|
|
888
|
+
every active layer and the effective rules from `ark.config.json`; the strict 11-layer profile
|
|
889
|
+
is the fallback only when the project config declares no layers. Call it with the same root +
|
|
890
|
+
project id expectation.
|
|
891
|
+
- **Resource `ark://manifest`** — compatibility discovery for standard MCP `resources/read`
|
|
892
|
+
clients. That protocol request has no portable project-expectation field, so Ark always marks
|
|
893
|
+
this resource `unverified` and non-authoritative. It never substitutes for `ark_manifest` in
|
|
894
|
+
a project verdict.
|
|
895
|
+
|
|
896
|
+
The server exposes these twelve tools. Every tool accepts the additive
|
|
897
|
+
`project: { expectedRoot, expectedProjectId? }` input:
|
|
853
898
|
|
|
854
899
|
| Tool | Primary input and purpose |
|
|
855
900
|
|------|---------------------------|
|
|
901
|
+
| `ark_identity` | `{ project: { expectedRoot, expectedProjectId? } }`: return the canonical root/config, stable project id, contract identity, and live runtime identity; use it before every other project-bound surface. |
|
|
902
|
+
| `ark_manifest` | No non-project args: return the machine-readable architecture contract with an authoritative binding after the identity handshake. |
|
|
856
903
|
| `validate_code` | `{ source, layer?, filePath? }`: validate one snippet; infer the layer from `filePath` when possible; return an error result when invalid. |
|
|
857
|
-
| `ark_check` | `{ strict?, baseline? }`: run the full project architecture check
|
|
904
|
+
| `ark_check` | `{ strict?, baseline? }`: run the full project architecture check. `verdict` separates `identity`, `completeness`, `graph`, `coverage`, `gates`, and `overallOk`; no individual green fact substitutes for the combined verdict. |
|
|
858
905
|
| `ark_policy_delta` | `{ baseConfig, candidateConfig?, acknowledgement? }`: classify a complete contract transition; never edits the contract. |
|
|
859
906
|
| `ark_coverage` | No args: report per-layer counts, every unclassified file, unmatched layers, and missing rule edges. |
|
|
860
907
|
| `ark_place` | `{ filePath?, description? }`: resolve or propose a governed home and return its import/global constraints. |
|
|
@@ -862,8 +909,55 @@ The server exposes these nine tools:
|
|
|
862
909
|
| `ark_prepare_change` | `{ changes, changeMap? }`: preflight one complete create/update/delete batch in memory; never writes files. |
|
|
863
910
|
| `ark_recommend` | No args: return the deterministic application-shape plan used by `ark-check --recommend --json`. |
|
|
864
911
|
| `ark_suggest_include` | No args: propose TypeScript/JavaScript include roots from workspaces and nested packages. |
|
|
912
|
+
| `ark_rules_inventory` | No args: inventory possible intra-layer rules using configured layer evidence when available; test/fixture/seed/migration surfaces and narrow technical constants are excluded from extraction pilots. Counts are not a score. |
|
|
913
|
+
|
|
914
|
+
Every project-bound tool success, tool error, and JSON-RPC error data carries:
|
|
865
915
|
|
|
866
|
-
|
|
916
|
+
```json
|
|
917
|
+
{
|
|
918
|
+
"projectIdentity": {
|
|
919
|
+
"schemaVersion": "1.0",
|
|
920
|
+
"projectId": "sha256:…",
|
|
921
|
+
"resolvedRoot": "/absolute/project",
|
|
922
|
+
"resolvedConfigPath": "/absolute/project/ark.config.json",
|
|
923
|
+
"arkgateVersion": "4.2.0",
|
|
924
|
+
"contractHash": "sha256:…",
|
|
925
|
+
"contractSource": "project",
|
|
926
|
+
"runtimeId": "process-specific",
|
|
927
|
+
"processStartedAt": "2026-07-30T00:00:00.000Z"
|
|
928
|
+
},
|
|
929
|
+
"binding": {
|
|
930
|
+
"status": "matched",
|
|
931
|
+
"authoritative": true
|
|
932
|
+
},
|
|
933
|
+
"authoritative": true
|
|
934
|
+
}
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
`projectId` stays stable across process restarts and contract edits; `runtimeId` and
|
|
938
|
+
`processStartedAt` identify this live process. Binding states are:
|
|
939
|
+
|
|
940
|
+
- `matched` — canonical `expectedRoot` is the exact project root, or it is a contained
|
|
941
|
+
descendant and the caller also supplied the matching project id; `authoritative` is `true`;
|
|
942
|
+
- `unverified` — no expectation was supplied, or only the id matched; callable for legacy
|
|
943
|
+
clients, but `authoritative` is `false`;
|
|
944
|
+
- `mismatch` — invalid/wrong root or id; `authoritative` is `false` and Ark returns
|
|
945
|
+
`PROJECT_ROOT_MISMATCH`, `PROJECT_ID_MISMATCH`, or `INVALID_PROJECT_EXPECTATION`.
|
|
946
|
+
|
|
947
|
+
Roots, configs, manifests, TypeScript configs, and project-bound tool paths are canonicalized
|
|
948
|
+
through real paths. A config or file path outside the bound project fails before Ark returns
|
|
949
|
+
placement, golden-pattern, Layers, or ArkRules evidence. The MCP process never retargets itself
|
|
950
|
+
from tool input; disjoint projects need disjoint processes. The compatibility `ark://manifest`
|
|
951
|
+
resource also carries the identity envelope, but its binding is always `unverified` and
|
|
952
|
+
non-authoritative.
|
|
953
|
+
|
|
954
|
+
For `ark_check`, treat `verdict.overallOk` as the combined control-plane fact. It can be true only
|
|
955
|
+
when the binding is matched, analysis is complete, the graph is valid, coverage is complete
|
|
956
|
+
(non-empty, 100% governed, zero unclassified files), and both local-write and CI-merge gate state
|
|
957
|
+
are active. The underlying CLI fields remain present for diagnosis, but are not an authoritative
|
|
958
|
+
whole-project green on their own.
|
|
959
|
+
|
|
960
|
+
Current diagnostic envelopes use schema `1.4` and require `mode`,
|
|
867
961
|
`completeness: "complete" | "partial" | "unavailable"`, and structured
|
|
868
962
|
`completenessReasons`. Resolved results expose `policyHash`, `resolverIdentity`, `factsHash`, and
|
|
869
963
|
`candidateTreeHash`; MCP `ark_check` mirrors CLI `ok`. Single-file `validate_code`,
|
|
@@ -873,7 +967,9 @@ preflight. Consumer-owned 1.0/1.1/1.2 `AdapterResult` values remain accepted by
|
|
|
873
967
|
|
|
874
968
|
For hook-based enforcement, `ark-mcp --hook` runs one-shot: it reads a PreToolUse payload
|
|
875
969
|
from stdin, validates the post-edit file content, and exits `2` with violations on stderr
|
|
876
|
-
to block the write (`0` to allow).
|
|
970
|
+
to block the write (`0` to allow). `--root-env` accepts a prioritized comma-separated
|
|
971
|
+
environment-variable list; ArkGate uses the first populated value and otherwise keeps
|
|
972
|
+
the explicit `--root` fallback. Working Claude Code configuration
|
|
877
973
|
(`.claude/settings.json`):
|
|
878
974
|
|
|
879
975
|
```json
|
|
@@ -885,7 +981,7 @@ to block the write (`0` to allow). Working Claude Code configuration
|
|
|
885
981
|
"hooks": [
|
|
886
982
|
{
|
|
887
983
|
"type": "command",
|
|
888
|
-
"command": "npx ark-mcp --hook --root
|
|
984
|
+
"command": "npx ark-mcp --hook --root . --root-env CLAUDE_PROJECT_DIR"
|
|
889
985
|
}
|
|
890
986
|
]
|
|
891
987
|
}
|
|
@@ -894,8 +990,8 @@ to block the write (`0` to allow). Working Claude Code configuration
|
|
|
894
990
|
}
|
|
895
991
|
```
|
|
896
992
|
|
|
897
|
-
Register the server itself in `.mcp.json` so the agent can
|
|
898
|
-
`validate_code` on demand:
|
|
993
|
+
Register the server itself in `.mcp.json` so the agent can handshake with `ark_identity`, call
|
|
994
|
+
`ark_manifest`, and use `validate_code` on demand:
|
|
899
995
|
|
|
900
996
|
```json
|
|
901
997
|
{
|
|
@@ -908,6 +1004,8 @@ Register the server itself in `.mcp.json` so the agent can read `ark://manifest`
|
|
|
908
1004
|
On Claude/Grok, the installed PreToolUse hook makes matched writes an enforced checkpoint. MCP
|
|
909
1005
|
registration by itself remains advisory on every host because the agent must call the tool.
|
|
910
1006
|
|
|
1007
|
+
Decision rationale: [ADR 0017 — MCP verdicts require explicit project identity](adr/0017-mcp-project-identity-binding.md).
|
|
1008
|
+
|
|
911
1009
|
## Experimental runtime kernel workflow (not the default path)
|
|
912
1010
|
|
|
913
1011
|
This section is for adopters who **opt into** the experimental `@arkgate/runtime` / kernel surfaces.
|
package/docs/ai-gates.md
CHANGED
|
@@ -85,9 +85,12 @@ supported smells on touched paths. Companion plan JSON: `plan.patternBets[]` wit
|
|
|
85
85
|
[package-surface.md](package-surface.md) and [brownfield-adoption.md](brownfield-adoption.md) §6.
|
|
86
86
|
|
|
87
87
|
If your project uses Codex or Grok, treat MCP registration as part of the default
|
|
88
|
-
setup, not an optional extra. Ark works best when the agent can
|
|
88
|
+
setup, not an optional extra. Ark works best when the agent can call `ark_manifest`
|
|
89
89
|
before it writes code; that is the fast path to avoiding architecture drift during
|
|
90
|
-
generation.
|
|
90
|
+
generation. Registration on disk is not runtime proof: after the host starts the server, call
|
|
91
|
+
`ark_identity` with `project.expectedRoot` set to the exact project's absolute root and require
|
|
92
|
+
a `matched`, authoritative binding. Then call `ark_manifest` with that root plus the returned
|
|
93
|
+
project id before using project evidence.
|
|
91
94
|
|
|
92
95
|
## Claude Code — hook (recommended, hard block)
|
|
93
96
|
|
|
@@ -158,7 +161,7 @@ Add to your project's `.claude/settings.json`:
|
|
|
158
161
|
"hooks": [
|
|
159
162
|
{
|
|
160
163
|
"type": "command",
|
|
161
|
-
"command": "npx ark-mcp --hook --hook-repair --root
|
|
164
|
+
"command": "npx ark-mcp --hook --hook-repair --root . --root-env CLAUDE_PROJECT_DIR --config ark.config.json"
|
|
162
165
|
}
|
|
163
166
|
]
|
|
164
167
|
}
|
|
@@ -173,7 +176,7 @@ That's the whole setup. Try asking the agent to import a persistence adapter fro
|
|
|
173
176
|
Ark architecture gate blocked this write to src/domain/order.ts (layer: DomainModel):
|
|
174
177
|
- [FORBIDDEN_PATTERN] Forbidden pattern matched: /from ['"].*\/(infra|adapters|persistence|db)/i (line 1)
|
|
175
178
|
- [FORBIDDEN_IMPORT] Forbidden import target: "../adapters/persistence/pg-order-repository". (line 1)
|
|
176
|
-
Fix the violations and retry.
|
|
179
|
+
Fix the violations and retry. After ark_identity matches, call ark_manifest with the same project expectation for the authoritative contract.
|
|
177
180
|
```
|
|
178
181
|
|
|
179
182
|
## Claude Code — SessionStart context injection (know the rules before the first token)
|
|
@@ -191,7 +194,7 @@ injects into the agent's context at session start:
|
|
|
191
194
|
"hooks": [
|
|
192
195
|
{
|
|
193
196
|
"type": "command",
|
|
194
|
-
"command": "npx ark-mcp --session-context --root
|
|
197
|
+
"command": "npx ark-mcp --session-context --root . --root-env CLAUDE_PROJECT_DIR --config ark.config.json"
|
|
195
198
|
}
|
|
196
199
|
]
|
|
197
200
|
}
|
|
@@ -207,7 +210,7 @@ Ark architecture contract governs this project (ark.config.json is authoritative
|
|
|
207
210
|
Layers:
|
|
208
211
|
- DomainModel: src/domain/** — forbidden globals: fetch, process, Date.now, Math.random
|
|
209
212
|
- PersistenceAdapters: src/adapters/persistence/**
|
|
210
|
-
Rules: 10 denied layer edge(s). Full contract:
|
|
213
|
+
Rules: 10 denied layer edge(s). Full authoritative contract: ark_manifest after ark_identity.
|
|
211
214
|
Baseline: 3 frozen violation(s) — only NEW violations fail; do not add to them.
|
|
212
215
|
After edits run: npx ark-check --root . --config ark.config.json --strict
|
|
213
216
|
```
|
|
@@ -219,9 +222,20 @@ prints nothing and exits 0, so non-Ark projects are untouched.
|
|
|
219
222
|
|
|
220
223
|
## Claude Code — MCP server (contract discovery + on-demand validation)
|
|
221
224
|
|
|
222
|
-
The MCP server exposes
|
|
223
|
-
|
|
224
|
-
|
|
225
|
+
The MCP server exposes tools plus one compatibility resource that agents can use proactively
|
|
226
|
+
(not an exhaustive list — `tools/list` is authoritative):
|
|
227
|
+
|
|
228
|
+
- **`ark_identity`** (tool) — returns the canonical project/config identity and this live MCP
|
|
229
|
+
runtime identity. Call it first with
|
|
230
|
+
`{ "project": { "expectedRoot": "/absolute/exact-project-root" } }`, then reuse the same root
|
|
231
|
+
and returned `projectIdentity.projectId` as `project.expectedProjectId` on later calls. A
|
|
232
|
+
descendant path is authoritative only when that matching id is also supplied.
|
|
233
|
+
- **`ark_manifest`** (tool) — returns the authoritative machine-readable architecture contract
|
|
234
|
+
(layers + rules) after the identity handshake. Call it with the same project expectation before
|
|
235
|
+
generating code.
|
|
236
|
+
- **`ark://manifest`** (resource) — compatibility-only discovery for standard MCP
|
|
237
|
+
`resources/read`. Because that request has no portable project-expectation field, this resource
|
|
238
|
+
is always `unverified` and non-authoritative.
|
|
225
239
|
- **`validate_code`** (tool) — validates a snippet against the architecture on demand (the write-path gate). May return additive **`autoPatch`** (W1) for mechanical-safe import-type rewrites.
|
|
226
240
|
- **`ark_prepare_write`** (tool) — **W2:** place + constrain + validate + optional autoPatch + judgmentBrief + contentHash in one call (composes `ark_place` + write gate).
|
|
227
241
|
- **`ark_prepare_change`** (tool) — **T02–T05:** read-only atomic create/update/delete preflight with cross-file edge/cycle findings and candidate fingerprints. Optional `changeMap` accepts strict schema `1.0` intent and returns its hash plus satisfied/missing/contradictory/unplanned structural convergence; behavioral completion is not evaluated. Omission is supported. MCP registration remains advisory unless the host makes invocation non-bypassable.
|
|
@@ -235,7 +249,20 @@ The MCP server exposes a resource and tools agents can use proactively (not an e
|
|
|
235
249
|
- **`ark_check`** (tool) — runs the full architecture check and returns structured violations (applies the baseline automatically when one exists).
|
|
236
250
|
- **`ark_coverage`** (tool) — per-layer file counts, the full unclassified-file list, and layers whose patterns match nothing.
|
|
237
251
|
|
|
238
|
-
|
|
252
|
+
Every Ark tool accepts the additive `project` expectation. Project-bound tool successes and
|
|
253
|
+
errors carry `projectIdentity`, `binding`, and `authoritative`. A legacy call with no expectation
|
|
254
|
+
stays callable but returns `binding.status: "unverified"` and `authoritative: false`; a wrong
|
|
255
|
+
root/id returns a mismatch before project evidence. Absolute project paths and
|
|
256
|
+
config/manifest/tsconfig inputs are real-path contained inside the server root. The process never
|
|
257
|
+
switches projects from input. The compatibility resource carries the same identity envelope but
|
|
258
|
+
is always unverified/non-authoritative.
|
|
259
|
+
|
|
260
|
+
`ark_check.verdict` keeps `identity`, `completeness`, `graph`, `coverage`, and `gates` separate.
|
|
261
|
+
Only `overallOk` combines them; a graph-clean result cannot paint an unverified binding,
|
|
262
|
+
incomplete analysis, empty/partial coverage, or inactive gates green.
|
|
263
|
+
|
|
264
|
+
Tools appear in the agent's tool list automatically — no skill or doc-reading needed — so the
|
|
265
|
+
agent can query the contract instead of shelling out and parsing.
|
|
239
266
|
|
|
240
267
|
```bash
|
|
241
268
|
claude mcp add ark -- npx ark-mcp --root . --config ark.config.json
|
|
@@ -283,7 +310,8 @@ alwaysApply: true
|
|
|
283
310
|
Before writing or editing any TypeScript source file, call the `validate_code`
|
|
284
311
|
tool from the `ark` MCP server with the full post-edit file content and its
|
|
285
312
|
path. If it reports violations, fix them before writing. The architecture
|
|
286
|
-
contract is available
|
|
313
|
+
contract is available authoritatively from `ark_manifest` after `ark_identity`
|
|
314
|
+
matches. `ark://manifest` is compatibility-only and always unverified.
|
|
287
315
|
```
|
|
288
316
|
|
|
289
317
|
Your repository backstop in Cursor is CI: `ark-check` fails its check on anything that slips
|
|
@@ -295,8 +323,9 @@ Recommended for Ark projects.
|
|
|
295
323
|
|
|
296
324
|
Codex 0.123+ dispatches `PreToolUse` for the native `apply_patch` handler. Ark installs
|
|
297
325
|
`.codex/hooks.json` with `ApplyPatch|apply_patch|Write|Edit|MultiEdit` aliases and reconstructs
|
|
298
|
-
every added or updated file in a multi-file patch before allowing it. The hook
|
|
299
|
-
|
|
326
|
+
every added or updated file in a multi-file patch before allowing it. The hook passes
|
|
327
|
+
`--root . --root-env CODEX_PROJECT_DIR`: ArkGate reads the environment directly without
|
|
328
|
+
POSIX shell expansion and safely falls back to the hook working directory.
|
|
300
329
|
|
|
301
330
|
This hook is best-effort in Codex Code Mode: some hosts execute deferred nested `apply_patch`
|
|
302
331
|
calls without dispatching the project `PreToolUse` event. ArkGate therefore does not treat the
|
|
@@ -307,8 +336,10 @@ required CI status is the hard repository boundary.
|
|
|
307
336
|
npx ark-check --install-agent-gates --tools codex
|
|
308
337
|
```
|
|
309
338
|
|
|
310
|
-
The generated hook includes `--hook-repair`, so a rejected patch
|
|
311
|
-
repair envelope as Claude
|
|
339
|
+
The generated hook includes `--hook-repair`, so a rejected patch **may emit** a structured
|
|
340
|
+
repair envelope (same JSON shape as Claude/Grok). **Reinjection is not guaranteed** on Codex —
|
|
341
|
+
local write stays advisory/bypassable; the host must re-apply any fix, and required CI remains
|
|
342
|
+
the hard merge boundary. Codex still needs hook trust enabled for the project.
|
|
312
343
|
|
|
313
344
|
Modern Codex resolves MCP servers from the active project's `.codex/config.toml`. Ark writes
|
|
314
345
|
that file with relative paths, so every repository owns its primary `ark` binding without
|
|
@@ -328,8 +359,45 @@ command = "npx"
|
|
|
328
359
|
args = ["arkgate-mcp", "--root", ".", "--config", "ark.config.json"]
|
|
329
360
|
```
|
|
330
361
|
|
|
331
|
-
|
|
332
|
-
|
|
362
|
+
This file means **configured on disk**, not active. Install and compact
|
|
363
|
+
`ark start --tools codex --json` therefore report the setup-time state explicitly:
|
|
364
|
+
|
|
365
|
+
```json
|
|
366
|
+
{
|
|
367
|
+
"runtimeActivation": {
|
|
368
|
+
"configuredOnDisk": true,
|
|
369
|
+
"restartRequired": true,
|
|
370
|
+
"runtimeObserved": false,
|
|
371
|
+
"identityMatch": "unverified",
|
|
372
|
+
"active": false
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Then **restart Codex** — it does not hot-load MCP servers — and call:
|
|
378
|
+
|
|
379
|
+
```json
|
|
380
|
+
{
|
|
381
|
+
"tool": "ark_identity",
|
|
382
|
+
"arguments": {
|
|
383
|
+
"project": {
|
|
384
|
+
"expectedRoot": "/absolute/exact-project-root"
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
The live response must say `binding.status: "matched"` and `authoritative: true`. Reuse its
|
|
391
|
+
`projectIdentity.projectId` with the same root on every subsequent Ark call, starting with
|
|
392
|
+
`ark_manifest`. A missing `ark_identity` or `ark_manifest` means the process is from an older
|
|
393
|
+
ArkGate build; restart the host and use the workspace-local CLI until the new server answers. A
|
|
394
|
+
mismatch means Codex is connected to another project's process; do not use its contract,
|
|
395
|
+
placement, Layers, ArkRules, or check evidence.
|
|
396
|
+
|
|
397
|
+
Setup-time `runtimeActivation` remains intentionally conservative: the installer/doctor cannot
|
|
398
|
+
observe a later MCP conversation from files alone. The matched `ark_identity` response is the
|
|
399
|
+
runtime observation for that caller and live process; it does not mutate the setup JSON.
|
|
400
|
+
`.codex/config.toml` by itself never upgrades `runtimeObserved` or `active`.
|
|
333
401
|
|
|
334
402
|
Codex uses the best-effort local patch hook plus advisory MCP for discovery/validation and
|
|
335
403
|
`ark-check` as the hard merge backstop. Register all three as soon as the repo is adopted.
|
|
@@ -357,9 +425,11 @@ writes a scoped secondary table:
|
|
|
357
425
|
| Doctor: primary points at another permanent project | gap id `codex-home-multi-project` (warn if no secondary yet and session host is unknown/Codex; **info + `deferred`** when the session host is known and not Codex — e.g. Grok/Claude/Cursor; info if a scoped secondary is already present) |
|
|
358
426
|
| When using Codex: refresh home skills | `ark-check --install-agent-gates --skills-only --codex-home --force` |
|
|
359
427
|
|
|
360
|
-
When a valid project `.codex/config.toml` exists,
|
|
361
|
-
|
|
362
|
-
|
|
428
|
+
When a valid project `.codex/config.toml` exists, it is the expected binding, but files alone
|
|
429
|
+
cannot prove which already-running process answered. Doctor therefore keeps an unrelated home
|
|
430
|
+
primary as collision evidence until the live `ark_identity` matches; it does not label that home
|
|
431
|
+
entry as the active project. Without a project binding, doctor surfaces the legacy multi-project
|
|
432
|
+
state directly. **Deferred (fix when using Codex):**
|
|
363
433
|
non-temp Codex-home gaps (`codex-home-multi-project`, stale `$CODEX_HOME/skills`) are
|
|
364
434
|
severity **info**, marked `deferred: true`, and omitted from doctor **Primary next action** /
|
|
365
435
|
**Also** list (formerly “Top actions”) when the session host is known and not Codex —
|
|
@@ -379,6 +449,23 @@ Flat `.codex/prompts/*.md` files are **not** the invocable skill catalog. Instal
|
|
|
379
449
|
repo catalog above so AGENTS.md `/ark-*` references match what Codex can load. After install,
|
|
380
450
|
Ark verifies those references against each selected host catalog.
|
|
381
451
|
|
|
452
|
+
**Several repos on one machine:** repo catalogs are independent and follow each repository's
|
|
453
|
+
locally installed ArkGate package. A managed upgrade rewrites a repo skill only when its normalized
|
|
454
|
+
body changes; a package-version stamp alone is a no-op. The optional home catalog is shared, so
|
|
455
|
+
ArkGate 4.2.0+ installation is monotonic there: an older bundled source cannot replace a newer
|
|
456
|
+
managed home skill, even with `--force`. A pre-4.2 binary ignores the catalog/lock protocol and
|
|
457
|
+
can still overwrite those files, so upgrade every legacy repo before it runs `--codex-home`
|
|
458
|
+
(especially with `--force`). Identical content is idempotent, and preserved customization still
|
|
459
|
+
follows the explicit force contract. The shared skill only routes the workflow; project evidence remains
|
|
460
|
+
bound to the repo through `ark_identity`. Ark records the shared catalog in
|
|
461
|
+
`$CODEX_HOME/skills/.arkgate-catalog.json`, writes a durable
|
|
462
|
+
`.arkgate-catalog.pending.json` floor before mutations, and serializes concurrent installs.
|
|
463
|
+
Doctor suppresses home refresh gaps only when the maximum valid committed/pending floor is newer
|
|
464
|
+
than the repo package; an equal pending version remains actionable for recovery, and corrupt
|
|
465
|
+
metadata never counts as a floor. When a newer package retires a skill, Ark removes it only if the
|
|
466
|
+
bytes still match the prior managed identity; customized retired content is preserved and
|
|
467
|
+
released from Ark ownership.
|
|
468
|
+
|
|
382
469
|
**Parity & honesty (doctor / install):**
|
|
383
470
|
|
|
384
471
|
- Doctor distinguishes **missing / stale / legacy-prompts-only** for repo (`.agents/skills`) and
|
|
@@ -387,7 +474,7 @@ Ark verifies those references against each selected host catalog.
|
|
|
387
474
|
`--skills-only --tools codex --force` (repo) or `--codex-home --force` (home) fix.
|
|
388
475
|
- Codex **write path is advisory**: MCP + best-effort `.codex/hooks.json` is **not** a hard
|
|
389
476
|
write boundary and is **not** equivalent to Claude/Grok PreToolUse hard-write + repair.
|
|
390
|
-
The hard merge backstop is CI `--strict-merge` (or `--strict`)
|
|
477
|
+
The hard merge backstop is CI `--strict-merge` (or `--strict`) as a **required GitHub status context** (not “workflow file present”).
|
|
391
478
|
- CI workflows that run ark-check without the fail-closed profile (or with only
|
|
392
479
|
`--strict-config`) surface gap `enforcement-ci-not-fail-closed`.
|
|
393
480
|
|
|
@@ -591,13 +678,34 @@ for standalone linting where no project contract applies.
|
|
|
591
678
|
Whatever the agent side does, run the merge profile in CI:
|
|
592
679
|
|
|
593
680
|
```yaml
|
|
594
|
-
|
|
681
|
+
# EH04: first push may have all-zero github.event.before — only pass --base-ref when resolvable.
|
|
682
|
+
- name: Ark architecture check
|
|
683
|
+
env:
|
|
684
|
+
ARK_POLICY_BASE_REF: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
685
|
+
run: |
|
|
686
|
+
set -euo pipefail
|
|
687
|
+
BASE_REF="${ARK_POLICY_BASE_REF:-}"
|
|
688
|
+
if [[ "$BASE_REF" =~ ^0{40,64}$ ]]; then BASE_REF=""; fi
|
|
689
|
+
if [ -n "$BASE_REF" ] && git cat-file -e "${BASE_REF}^{commit}" 2>/dev/null; then
|
|
690
|
+
export ARK_POLICY_BASE_REF="$BASE_REF"
|
|
691
|
+
npx ark-check --root . --config ark.config.json --strict-merge \
|
|
692
|
+
--fail-on-new-smells --base-ref "$BASE_REF"
|
|
693
|
+
else
|
|
694
|
+
export ARK_POLICY_BASE_REF=""
|
|
695
|
+
npx ark-check --root . --config ark.config.json --strict-merge
|
|
696
|
+
fi
|
|
595
697
|
```
|
|
596
698
|
|
|
597
699
|
This explicit brownfield ratchet records schema `1.0` identities, touched paths, and stable
|
|
598
|
-
evidence; missing base exits `2
|
|
599
|
-
|
|
600
|
-
|
|
700
|
+
evidence; missing base with `--fail-on-new-smells` exits `2`, so the generated workflow skips the
|
|
701
|
+
delta when the SHA is all-zero or unresolvable while keeping the full merge gate. Its first
|
|
702
|
+
semantic smell is `domain-logic-in-ui`; residual, path-only moves, and unrelated work stay green.
|
|
703
|
+
Generated Claude/Grok hooks share the delta and golden-pattern repair hint. MCP exposes the result
|
|
704
|
+
but stays advisory.
|
|
705
|
+
|
|
706
|
+
**CLI vs required status:** `arkgate-check --strict-merge` / `ark-check --strict-merge` is the
|
|
707
|
+
**command**. The hard merge boundary is making that job a **required GitHub status context** —
|
|
708
|
+
not “workflow file present.”
|
|
601
709
|
|
|
602
710
|
Or use the repository's composite Action at a pinned release or commit:
|
|
603
711
|
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
<text x="24" y="152" fill="#f85149" font-weight="bold">✗ Ark architecture gate blocked this write to src/domain/order.ts (layer: DomainModel):</text>
|
|
19
19
|
<text x="40" y="174" fill="#f85149">- [FORBIDDEN_IMPORT] Forbidden import target: "../adapters/persistence/pg-order-repository".</text>
|
|
20
|
-
<text x="24" y="196" fill="#8b949e">Fix the violations and retry. The architecture contract is available
|
|
21
|
-
<text x="24" y="214" fill="#8b949e">
|
|
20
|
+
<text x="24" y="196" fill="#8b949e">Fix the violations and retry. The architecture contract is available through</text>
|
|
21
|
+
<text x="24" y="214" fill="#8b949e">the project-bound ark_manifest MCP tool.</text>
|
|
22
22
|
|
|
23
23
|
<text x="24" y="248" fill="#c9d1d9">● The domain layer can't import persistence adapters. I'll define the port in the</text>
|
|
24
24
|
<text x="24" y="266" fill="#c9d1d9">domain instead and implement it in src/adapters/persistence/.</text>
|
package/docs/develop.md
CHANGED
|
@@ -14,14 +14,18 @@ npx arkgate start --apply
|
|
|
14
14
|
npx arkgate-check --doctor
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Make the architecture check a **required** merge status (GitHub/GitLab/etc.)
|
|
17
|
+
Make the architecture check a **required** merge **status context** (GitHub/GitLab/etc.). The CLI
|
|
18
|
+
command is `arkgate-check --strict-merge` / `ark-check --strict-merge` — the hard boundary is
|
|
19
|
+
requiring that job’s status, not merely adding a workflow file:
|
|
18
20
|
|
|
19
21
|
```yaml
|
|
20
22
|
- run: npx arkgate-check --root . --config ark.config.json --strict-merge
|
|
21
23
|
# or: uses: pedroknigge/arkgate@<tag-or-SHA>
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
Generated workflows also gate `--fail-on-new-smells --base-ref` so a first push with an all-zero
|
|
27
|
+
`github.event.before` still runs the full merge gate without a broken delta (see
|
|
28
|
+
[ai-gates.md](ai-gates.md#ci-backstop)).
|
|
25
29
|
|
|
26
30
|
---
|
|
27
31
|
|
|
@@ -31,9 +35,9 @@ Local write hardness **differs by host**. CI required status is the shared hard
|
|
|
31
35
|
|
|
32
36
|
| Host | Local write | MCP | Merge |
|
|
33
37
|
|------|-------------|-----|-------|
|
|
34
|
-
| Claude · Grok · Antigravity | Hard PreToolUse when installed + trusted | Advisory | Required status |
|
|
35
|
-
| Codex · OpenCode | Best-effort / advisory | Advisory | Required status |
|
|
36
|
-
| Cursor | Advisory only | Advisory | Required status |
|
|
38
|
+
| Claude · Grok · Antigravity | Hard PreToolUse when installed + trusted | Advisory | Required status context |
|
|
39
|
+
| Codex · OpenCode | Best-effort / advisory | Advisory | Required status context |
|
|
40
|
+
| Cursor | Advisory only | Advisory | Required status context |
|
|
37
41
|
|
|
38
42
|
Full matrix and install commands: [ai-gates.md](ai-gates.md) · canonical table in [README](../README.md#host-enforcement-support).
|
|
39
43
|
|
|
@@ -46,7 +50,13 @@ npx arkgate-check --install-agent-gates --tools opencode
|
|
|
46
50
|
npx arkgate-check --install-agent-gates --skills-only --force
|
|
47
51
|
```
|
|
48
52
|
|
|
49
|
-
Doctor reports what is actually installed and observed (`writePath` / enforcement state). Installed
|
|
53
|
+
Doctor reports what is actually installed and observed (`writePath` / enforcement state). Installed
|
|
54
|
+
files alone do not imply `hard:true` without runtime evidence where the product requires it.
|
|
55
|
+
|
|
56
|
+
**Evidence split (Phase EH):** soft-write hosts keep `soft-write-host` in evidence without forcing
|
|
57
|
+
global **Not finished** when the contract is ready. With `ARK_DOCTOR_GITHUB=1`, successful CI runs
|
|
58
|
+
can show `runtimeObserved: true` even when branch-protection policy is plan-unavailable
|
|
59
|
+
(`unavailable-plan` on GitHub Free private); `hard: false` until the status is required.
|
|
50
60
|
|
|
51
61
|
---
|
|
52
62
|
|
|
@@ -42,6 +42,12 @@ npx arkgate-check --doctor
|
|
|
42
42
|
npx arkgate-check --require-gates
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
`--require-gates` implies strict config validation. It verifies content, not filenames alone:
|
|
46
|
+
`AGENTS.md` must contain the Ark contract and strict check, MCP registration must launch one Ark
|
|
47
|
+
server with an explicit project root, compact Codex must contain valid project config plus
|
|
48
|
+
SessionStart/PreToolUse Ark hooks, and CI must execute a fail-closed Ark command. Included but
|
|
49
|
+
unclassified source files therefore remain red.
|
|
50
|
+
|
|
45
51
|
Doctor JSON includes `writePath.mode` plus `enforcementLadder`: support, installation, observed
|
|
46
52
|
evidence, covered operations, bypassability, and CI honesty. MCP registration stays advisory.
|
|
47
53
|
|