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.
Files changed (63) hide show
  1. package/CHANGELOG.md +124 -2
  2. package/README.md +24 -14
  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/ark-gitignore.mjs +88 -0
  7. package/bin/lib/ci-and-commands.mjs +33 -8
  8. package/bin/lib/codex-home.mjs +90 -8
  9. package/bin/lib/design-smells.mjs +71 -9
  10. package/bin/lib/doctor-plan.mjs +47 -39
  11. package/bin/lib/effective-contract-load.mjs +73 -9
  12. package/bin/lib/enforcement-honesty.mjs +78 -22
  13. package/bin/lib/enforcement-state.mjs +1 -1
  14. package/bin/lib/gate-files.mjs +441 -9
  15. package/bin/lib/github-enforcement.mjs +168 -7
  16. package/bin/lib/hook-templates.mjs +12 -11
  17. package/bin/lib/host-support-matrix.mjs +91 -17
  18. package/bin/lib/html-report-depth.mjs +13 -2
  19. package/bin/lib/html-report-evolution.mjs +114 -0
  20. package/bin/lib/html-report.mjs +18 -97
  21. package/bin/lib/import-resolve.mjs +33 -11
  22. package/bin/lib/install-activation.mjs +87 -0
  23. package/bin/lib/install-migrate.mjs +66 -50
  24. package/bin/lib/managed-upgrade.mjs +10 -41
  25. package/bin/lib/mcp-adoption.mjs +15 -5
  26. package/bin/lib/pilot-loop.mjs +25 -8
  27. package/bin/lib/project-identity.mjs +103 -0
  28. package/bin/lib/report-snapshot-context.mjs +28 -0
  29. package/bin/lib/resident-hook.mjs +33 -9
  30. package/bin/lib/rules-inventory.mjs +100 -8
  31. package/bin/lib/skill-install.mjs +272 -22
  32. package/bin/lib/skill-write.mjs +899 -0
  33. package/bin/lib/start-preview.mjs +84 -1
  34. package/bin/lib/upgrade-command.mjs +2 -5
  35. package/bin/lib/write-path-detect.mjs +2 -2
  36. package/dist/index.cjs +13 -13
  37. package/dist/index.d.ts +194 -2
  38. package/dist/index.js +13 -13
  39. package/docs/README.md +6 -4
  40. package/docs/agent-guide.md +115 -17
  41. package/docs/ai-gates.md +133 -25
  42. package/docs/assets/ark-write-gate.svg +2 -2
  43. package/docs/develop.md +16 -6
  44. package/docs/enthusiast/how-to-agent-gates.md +6 -0
  45. package/docs/package-surface.md +16 -9
  46. package/docs/product-voice.md +22 -4
  47. package/docs/use.md +3 -1
  48. package/package.json +3 -1
  49. package/schemas/ark.project-identity.schema.json +116 -0
  50. package/server.json +2 -2
  51. package/templates/skills/ark-adopt.md +9 -0
  52. package/templates/skills/ark-architect.md +12 -2
  53. package/templates/skills/ark-autopilot.md +9 -0
  54. package/templates/skills/ark-contract.md +11 -1
  55. package/templates/skills/ark-coverage.md +9 -0
  56. package/templates/skills/ark-explain.md +13 -1
  57. package/templates/skills/ark-explore.md +9 -0
  58. package/templates/skills/ark-fix.md +10 -1
  59. package/templates/skills/ark-loop.md +11 -2
  60. package/templates/skills/ark-place.md +17 -6
  61. package/templates/skills/ark-runtime.md +8 -0
  62. package/templates/skills/ark-think.md +14 -2
  63. package/templates/skills/ark-upgrade.md +9 -0
@@ -16,9 +16,9 @@ hardening guide remains repository-hosted rather than duplicated in the gate tar
16
16
 
17
17
  | Surface | How you use it | Stability notes |
18
18
  |---------|----------------|-----------------|
19
- | **CLI** | `arkgate` / `arkgate-check` (aliases `ark` / `ark-check`) | Flags and human text may improve; **JSON output shapes** for `--json` (check, doctor, plan, coverage, recommend) are stable within a major. Additive fields OK; removals/renames are major. |
19
+ | **CLI** | `arkgate` / `arkgate-check` (aliases `ark` / `ark-check`) | Flags and human text may improve; **JSON output shapes** for `--json` (check, doctor, plan, coverage, recommend) are stable within a major. Additive fields OK; removals/renames are major. In 4.2, `--require-gates` implies strict config and verifies semantic Ark AGENTS, project-rooted MCP/compact Codex registration, and fail-closed CI rather than file presence alone. |
20
20
  | **Programmatic gate API** | `import { analyzeProject, loadContract, createAICodeGate, ... } from 'arkgate'` | The root export is the static gate/config/analysis contract listed below. It intentionally contains no runtime-kernel implementation. |
21
- | **Doctor design fitness (P02+)** | `ark-check --doctor --json` → `doctor.designFitness`, `doctor.designSmells[]` | Additive. Stable smell `id`s: `io-under-application`, `handler-in-persistence`, `god-module`, `domain-logic-in-ui`, `facade-sql-in-routes`, `mixed-pattern-cluster`, `soft-contract`. Y02 extends `handler-in-persistence` to static ES imports/re-exports of framework HTTP surfaces (`next/server`), `defineRoute` calls, and existing handler bodies inside Persistence-role layers or specific persistence paths; `require()` and dynamic `import()` are outside this narrow advisory, and a generic `Infrastructure` role alone is not Persistence. Persistence candidates are filtered and sorted before the bounded content scan so large application prefixes cannot hide the advisory. The detector inspects the first 800 sorted Persistence candidates; later candidates are uninspected, so **absence of a smell is not full-tree proof** above that envelope (incomplete/`partial` analysis also never proves “no smells”). Each smell has `evidence[]`, `fix`, technical `message`, and plain-language **`outcome`** (Q02). Does **not** fail the gate by itself. |
21
+ | **Doctor design fitness (P02+)** | `ark-check --doctor --json` → `doctor.designFitness`, `doctor.designSmells[]` | Additive. Stable smell `id`s: `io-under-application`, `handler-in-persistence`, `god-module`, `domain-logic-in-ui`, `facade-sql-in-routes`, `mixed-pattern-cluster`, `soft-contract`. Y02 extends `handler-in-persistence` to static ES imports/re-exports of framework HTTP surfaces (`next/server`), `defineRoute` calls, and existing handler bodies inside Persistence-role layers or specific persistence paths; `require()` and dynamic `import()` are outside this narrow advisory, and a generic `Infrastructure` role alone is not Persistence. Persistence candidates are filtered and sorted before the bounded content scan so large application prefixes cannot hide the advisory. The detector inspects the first 800 sorted Persistence candidates; later candidates are uninspected, so **absence of a smell is not full-tree proof** above that envelope (incomplete/`partial` analysis also never proves “no smells”). **4.2 feedback hardening:** mode labels preserve the observed SUGGEST/ADAPT/ENFORCE state; a local permission/UI-state `canEdit` name alone is not a domain smell; real UI business rules route Domain → Application → UI; seed/fixture/demo/migration/generated files are not god-module pilots. Each smell has `evidence[]`, `fix`, technical `message`, and plain-language **`outcome`** (Q02). Does **not** fail the gate by itself. |
22
22
  | **Post-green path (Q01)** | `doctor.postGreenPath`, `doctor.primaryNextAction`, `doctor.healthyFinishedForbidden` | Additive when `designFitness.designWeak`. Single Shape door (`id: clarify-for-ai`): explore shape-focus → dual-plan B → autopilot only with OK. Never empty plan A = healthy finished. |
23
23
  | **Golden pattern (Q03)** | Optional `.ark/golden-pattern.json`; doctor JSON `doctor.goldenPattern`; MCP `ark_place` / `ark_prepare_write` → `goldenPattern` | Additive, **advisory for NEW code only**. Required fields: `name`, `norm`; optional `newCodeHome`, `examplePath`, `schemaVersion`. **Absent is normal** (no claim). Never ENFORCE; never clears design-weak. Malformed → `invalid: true`, not silent guidance. |
24
24
  | **Plan pattern B (P03+)** | `ark-check --plan --json` → `plan.patternBets[]`, `plan.goal.designWeak` | Additive. Each bet: `id`, `smellId`, `pilot`, `evidence`, `successSignal`, `killSwitch`, **`neverMechanicalSafe: true`**, `class: "judgment"`. **Never** auto-applied by loop/autoPatch; not a `remediationKind` mechanical-safe. `goal.met` remains edge honesty only. |
@@ -32,11 +32,14 @@ hardening guide remains repository-hosted rather than duplicated in the gate tar
32
32
  | **Capability walls, every adapter (U04+U06)** | CLI scan, pure IR engine, atomic preflight, `ark-mcp --hook` / MCP gate (`capabilityWalls`), ESLint `ark/no-denied-capabilities` | The same opt-in deny set enforces across every surface: hook/MCP and CLI cover ambient + import evidence (symbol-aware); the pure engine, preflight, and ESLint cover the import dimension (documented envelope). Dual depth everywhere: plain port hint (`FIX_HINTS`/`suggestion`) + stable JSON (`ruleId`, `capability`, `fixClass: inject-port`, deterministic `nextAction`). |
33
33
  | **Hook-path budgets (U06)** | Repository-only evidence: `npm run bench:hook-path`; `eval/performance/hook-budgets.v1.json`; CI job "Hook-path end-to-end budgets" | Measures the COMPLETE pre-tool paths as fresh child processes (hook cold/warm, doctor cold) at 1k/10k. D5 method locked: ceilings are Linux-baseline p95 + fixed headroom, set once per cycle, never ratcheted; scenarios without a recorded baseline stay in RECORDING mode and cannot fail CI. |
34
34
  | **Governance weight (W02)** | `ark-check --doctor --json` → `doctor.contractHealth.governanceWeight` | Additive, **advisory only** — raw facts (`declaredLayers`, `populatedLayers`, `governedFiles`, `rules`, `deniedEdges`, `allowedEdges`, `filesPerLayer`, `rulesPerLayer`) plus a fixed comparative band `weight: heavy | typical | light | unknown` and its fixed `note`. Fixed deterministic thresholds: **heavy** = fewer than 25 governed files per declared layer AND (6+ layers OR 4+ well-formed rules per layer); **light** = at most 2 layers over 150+ governed files; **unknown** = no layers or no governed files; everything else is **typical** (banding uses raw ratios; the reported ratios are rounded for display). `notAScore: true` is explicit: never a composite score, ranking, or gate input; the heavy note asks to justify NEW layers/rules and never suggests deleting working ones. Human doctor prints a line only for `heavy`/`light`. |
35
- | **Report parity (X01)** | `ark-check --report` → advisory sections (`data-advisory="contractHealth\|ambientState\|parseHealth"`, nested `governanceWeight`) + layer wall badges | The report is a rendering of doctor truth. **Standing rule:** every doctor advisory ships with its report section — enforced by the `reportParity` guard, which enumerates the doctor's advisory keys and fails on any missing section. |
36
- | **MCP tools** | `arkgate-mcp` / `ark://…` resources | Tool names and primary argument shapes are stable within a major. |
35
+ | **Report parity and snapshot evidence (X01/4.2)** | `ark-check --report` → advisory sections (`data-advisory="contractHealth\|ambientState\|parseHealth"`, nested `governanceWeight`) + layer wall badges; `.ark/reports/*.json` | The report is a rendering of doctor truth. **Standing rule:** every doctor advisory ships with its report section — enforced by the `reportParity` guard, which enumerates the doctor's advisory keys and fails on any missing section. Snapshots add best-effort Git `HEAD`/branch/dirty provenance without a shell; unavailable Git is explicit. Evolution renders the Ark score delta only when both snapshots name the same ArkGate version, while retaining raw facts across versions. |
36
+ | **MCP project identity (4.2)** | `ark_identity`; `arkgate/schema/project-identity` or `arkgate/schema/ark.project-identity.schema.json`; root API constants/helpers/types | Schema `1.0`. `projectId` hashes canonical root + config path and stays stable across contract edits/restarts; runtime id/start time are separate. Every project-bound tool result and error carries `projectIdentity`, `binding` (`matched` / `unverified` / `mismatch`), and `authoritative`. Canonical out-of-root config/file evidence fails before project data. |
37
+ | **MCP tools and compatibility resource** | `arkgate-mcp`; `ark_manifest`; `ark://manifest` | Tool names and primary argument shapes are stable within a major. Every tool accepts additive `project.expectedRoot` / optional `expectedProjectId`. The initial handshake requires the exact project root; a contained descendant is authoritative only together with the matching project id. Legacy tool calls remain callable but `unverified` and non-authoritative. `ark_manifest` is the authoritative contract surface after binding. Standard `resources/read` cannot portably carry the expectation, so `ark://manifest` remains compatibility-only and always unverified/non-authoritative. The server never retargets from input. |
37
38
  | **`ark.config.json`** | Layer globs, rules, include/exclude, forbiddenGlobals, intent prefixes, `peerIsolation`, `dynamicImportAllowlist`, `safety` thresholds; optional **`arkRules`** map (schema `1.1+`) | Versioned by `schemaVersion`; unknown fields fail closed and migrations preserve the previous supported major. Absence of `arkRules` is byte-for-byte silent on inter-layer verdicts. |
38
- | **ArkRules inventory / under-contract (4.0)** | `ark-check --rules-inventory [--json]`; doctor `rulesUnderContract`; MCP `ark_rules_inventory` | Additive. Honest counts (inventoried / under-contract / frozen) — **never a score**. Structure/invariant diagnostics use adapter `1.4` provenance. |
39
+ | **ArkRules inventory / under-contract (4.0; layer context 4.2)** | `ark-check --rules-inventory [--json]`; doctor `rulesUnderContract`; MCP `ark_rules_inventory` | Additive. Honest counts (inventoried / under-contract / frozen) — **never a score**. When configured layer evidence exists it overrides filename role guesses: a Domain file named `handler` is not a controller candidate. Test/fixture/seed/migration/exclusion surfaces plus narrow development-identity, PostgreSQL OID, and technical I/O constants are silent. Without layer evidence, backward-compatible path/content heuristics remain. Structure/invariant diagnostics use adapter `1.4` provenance. |
40
+ | **`arkgate/schema/project-identity`** or **`arkgate/schema/ark.project-identity.schema.json`** | MCP canonical project, contract, runtime, expectation, and binding envelope | Schema `1.0`. Initial `expectedRoot` must be the exact project root. A contained descendant can match only when `expectedProjectId` is also present and correct; id-only matching stays non-authoritative. Mismatch codes are `PROJECT_ROOT_MISMATCH`, `PROJECT_ID_MISMATCH`, and `INVALID_PROJECT_EXPECTATION`. |
39
41
  | **Package pin dual-truth (4.0)** | doctor JSON `packageVersionTruth`; upgrade JSON/human note when pin behind CLI | Additive, advisory. Surfaces after `upgrade --no-install` when managed CLI is ahead of package.json. |
42
+ | **Product honesty readiness split (4.1.1 EH)** | doctor JSON `productHonesty` | Additive. `unfinished` / `headline` / `primaryNextAction` / `reasonIds` remain; EH adds `contractReadiness` (`ready`\|`partial`\|`not-ready`), `localWriteBoundary` (`advisory`\|`hard`\|`unverified`\|`unknown`), `architectureReasonIds`, `environmentResidualIds` / `environmentResiduals`. Soft-write hosts stay in evidence without alone forcing global **Not finished**. `notAScore: true` always. |
40
43
  | **Policy transition analysis (T01, 3.1.0)** | `analyzePolicyDelta(...)`; MCP `ark_policy_delta`; CLI `--policy-base` / `--policy-base-ref` / `--policy-ack`; check JSON `policyDelta` | Additive schema `1.0`. Classifications and finding ids are deterministic. Weakening/judgment requires an acknowledgement bound to both policy hashes and the exact blocking finding set. |
41
44
  | **Atomic change preflight (T02, 3.1.0)** | `preflightChange(...)`; CLI `ark preflight --changes <file> --json`; MCP `ark_prepare_change` | Additive schema `1.0`. One complete governed production-source `{path,content}` / `{path,delete:true}` batch; read-only; returns operation, content/tree/policy/compiler fingerprints and stable graph findings. MCP availability alone is advisory. |
42
45
  | **Architecture change map (T03, 3.1.0)** | `arkgate/schema/change-map` or `arkgate/schema/ark.change-map.schema.json`; CLI `ark preflight --change-map <file>`; MCP `ark_prepare_change.changeMap` | Optional strict schema `1.0`. Canonical planned paths + operations + resolved Ark layers + dependencies between planned files. Preflight returns `changeMapHash`; absence is normal and adds no project file. Structural intent only, never behavioral completion. |
@@ -48,7 +51,7 @@ hardening guide remains repository-hosted rather than duplicated in the gate tar
48
51
  | **`arkgate/schema/arkrules`** or **`arkgate/schema/ark.arkrules.schema.json`** | Per-layer structure sensors + invariant catalog (ADR 0012) | Schema `1.0`. Opt-in via root `arkRules` map (`ark.config` schema `1.1`). |
49
52
  | **`arkgate/schema/resolved-candidate-facts`** or **`arkgate/schema/ark.resolved-candidate-facts.schema.json`** | Versioned parity-capable input for `analyzeResolvedProject` / `preflightResolvedChange` | Schema `1.0` is serializable and deterministic. Tooling owns filesystem/compiler resolution; Domain/Kernel validate and evaluate supplied facts without importing those effects. Facts name resolver/compiler inputs, governed files, dependency evidence, completeness reasons, and candidate tree/facts hashes. |
50
53
  | **Config JSON Schema** | `arkgate/schema` or `arkgate/schema/ark.config.schema.json` | Stable package resource subpaths for editor completion and contract tooling. |
51
- | **Agent skills** | `/ark-*` templates; install via `--install-agent-gates` (often `--skills-only` on top of compact) | **Day zero** is the compact router from `ark start` / `start --apply` + doctor control plane — not the full skill pack. Skill *names* and the guided expert path (`/ark-autopilot` after pack install) are stable; internal skill prose may evolve. **4.0:** all skills except experimental `/ark-runtime` integrate **layers + ArkRules** and must label residual `[Layer]` vs `[ArkRules]`. |
54
+ | **Agent skills** | `/ark-*` templates; install via `--install-agent-gates` (often `--skills-only` on top of compact) | **Day zero** is the compact router from `ark start` / `start --apply` + doctor control plane — not the full skill pack. Skill *names* and the guided expert path (`/ark-autopilot` after pack install) are stable; internal skill prose may evolve. **4.0:** all skills except experimental `/ark-runtime` integrate **layers + ArkRules** and must label residual `[Layer]` vs `[ArkRules]`. **4.2:** repo catalogs are content-idempotent; the optional shared Codex home catalog is monotonic across 4.2.0+ installers. Pre-4.2 writers are outside that protocol and must be upgraded first. A durable pending-catalog journal preserves the floor across an interrupted install and is cleared only by its owning same/newer recovery. |
52
55
  | **ESLint subpath** | `arkgate/eslint` | Config-driven layer/import rules; loads consumer `ark.config.json`. |
53
56
  | **GitHub Action** | `pedroknigge/arkgate` (see `action.yml`) | The `uses:` tag/SHA selects the checker source; `version` remains an optional exact npm compatibility override. |
54
57
  | **Package metadata** | `arkgate/package.json` | Stable resource subpath for tooling that needs the installed manifest. |
@@ -85,6 +88,7 @@ are grouped below.
85
88
  | Group | Exported runtime values |
86
89
  |-------|-------------------------|
87
90
  | Metadata and adapter diagnostics | `version`, `ARK_ANALYSIS_RESULT_SCHEMA_VERSION`, `ARK_ANALYSIS_RESULT_SCHEMA`, `createAdapterResult`, `toAdapterDiagnostic` |
91
+ | MCP project identity | `ARK_PROJECT_IDENTITY_SCHEMA_VERSION`, `ARK_PROJECT_IDENTITY_SCHEMA_URL`, `ARK_PROJECT_IDENTITY_SCHEMA`, `PROJECT_EXPECTATION_SCHEMA`, `PROJECT_BINDING_SCHEMA`, `createProjectId`, `createProjectIdentity` |
88
92
  | AI snippet gate | `createAICodeGate` |
89
93
  | Profiles and config factories | `createArchitectureProfile`, `createArchitectureProfileFromArkConfig`, `createElevenLayerArkConfig`, `elevenLayerProfile` |
90
94
  | Analysis and preflight | `loadContract`, `analyzeResolvedProject`, `preflightResolvedChange`, lexical-compatibility `analyzeProject` / `analyzeChange` / `preflightChange`, `analyzePolicyDelta`, `analyzeArchitectureConvergence`, `explainViolation`, `evaluateArchitectureGraph`, `collectAnalysisConfigWarnings`, `detectArchitectureCycles`, `collectForbiddenCapabilityUses`, `extractSemanticDependencies` |
@@ -97,6 +101,7 @@ The type-only root exports are also semver-supported:
97
101
 
98
102
  - Adapter diagnostics: `AdapterDiagnostic`, `AdapterResult`, `AdapterSeverity`,
99
103
  `AdapterViolationInput`, `AdapterCompletenessReason`, `AnalysisCompleteness`, `AnalysisMode`.
104
+ - MCP project identity: `ProjectIdentity`, `ProjectExpectation`, `ProjectBinding`.
100
105
  - Resolved facts: `ResolvedCandidateFacts`, `ResolvedCandidateFactsInput`, and their
101
106
  dependency/file/evidence component types.
102
107
  - AI snippet gate: `AICodeGate`, `AICodeGateResult`, `AICodeGateViolation`,
@@ -189,7 +194,9 @@ production deployment would need to satisfy; it is not a readiness certification
189
194
  ## Release notes (maintainers)
190
195
 
191
196
  Ship notes for a version live under [releases/](https://github.com/pedroknigge/arkgate/tree/main/docs/releases)
192
- (current published: [4.0.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.0.1.md);
193
- next prepared: [4.1.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.1.0.md);
194
- previous: [4.0.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.0.0.md)).
197
+ (prepared: [4.2.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.2.0.md);
198
+ current published: [4.1.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.1.1.md);
199
+ previous: [4.1.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.1.0.md),
200
+ [4.0.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.0.1.md),
201
+ [4.0.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.0.0.md)).
195
202
  Publish path: signed annotated tag → GitHub Release → `publish-npm.yml` (see [CONTRIBUTING.md](https://github.com/pedroknigge/arkgate/blob/main/CONTRIBUTING.md)).
@@ -22,7 +22,8 @@ because the design space is small and honest.
22
22
  - **Co-pilot side:** where code belongs, who talks to whom, how; dual plan **A** (edges) +
23
23
  **B** (shape); one pilot at a time; never silent judgment codemod; never weaken the contract.
24
24
  - **False done is forbidden:** Enforce ≠ elegant design. `design-weak` / residual must not
25
- read as “healthy finished.” Empty ArkRules inventory is not a score.
25
+ read as “healthy finished.” Empty ArkRules inventory is not a score. MCP configuration on
26
+ disk is not proof that the current process belongs to this project.
26
27
 
27
28
  ---
28
29
 
@@ -73,7 +74,15 @@ Examples:
73
74
  | **compact router** | Default onboarding agent instructions (not the full skill pack) |
74
75
  | **hard write** | Non-bypassable PreToolUse block for listed ops (Claude/Grok when installed + trusted) |
75
76
  | **advisory write** | MCP/rules coach only (Cursor/Codex at write time) — not a hard block |
76
- | **required CI** | Merge hard boundary when the repository makes `arkgate-check` a required status |
77
+ | **project identity** | Stable canonical root + config identity returned by `ark_identity`; separate from contract and process identity |
78
+ | **matched binding** | Live MCP answered for the exact project root, or for a contained descendant together with the matching project id; only this binding is authoritative |
79
+ | **authoritative manifest** | Contract returned by `ark_manifest` after a matched identity handshake |
80
+ | **compatibility manifest resource** | `ark://manifest` through standard `resources/read`; always unverified/non-authoritative because the request cannot portably carry a project expectation |
81
+ | **configured on disk** | Host files name an Ark MCP command; says nothing about which process is currently running |
82
+ | **runtime observed** | A live `ark_identity` response matched this workspace; never infer it from `.codex/config.toml` or hook files |
83
+ | **required CI / status context** | Merge hard boundary when the repository makes the Ark job a **required GitHub status context** (CLI: `arkgate-check --strict-merge` / `ark-check --strict-merge`) |
84
+ | **contract ready** | Project/layers/ArkRules honesty residual clear — not the same as “hard local write” |
85
+ | **environment residual** | Permanent host/provider posture (e.g. soft-write Codex) kept in evidence without forcing global **Not finished** |
77
86
 
78
87
  ## Do (product copy)
79
88
 
@@ -82,11 +91,15 @@ Examples:
82
91
  | Name the status light + plain fact + term + next action | “Enforce · design-weak. Checked edges are honest; design smells remain. Next: one Shape door — explore → dual-plan B → autopilot with OK.” |
83
92
  | Rank one primary door under residual | Doctor **Primary next action** #1; **Also** only for secondary |
84
93
  | Label expert skills as escapes | “Install skill pack only when doctor or a STOP handoff names a skill.” |
85
- | State host write honesty | “Cursor/Codex: advisory write. Required CI is the hard merge boundary.” |
94
+ | State host write honesty | “Cursor/Codex: advisory write. Required GitHub status context is the hard merge boundary.” |
95
+ | Soft-write ≠ unfinished project | “Architecture contract ready; Codex local writes are advisory.” Keep `soft-write-host` in evidence; reserve **Not finished** for contract/project debt. |
86
96
  | Keep Suggest on start → doctor | New-here primary is finish `start`, not a competing recommend/architect curriculum |
87
97
  | Qualify edge-clean under design-weak | “None on checked edges … design residual remains. Not healthy finished.” |
88
98
  | Prefer fail-closed over fake hard | Incomplete analysis, unobserved hooks, and soft MCP never paint as hard green |
89
- | Honesty clear architecture healthy | `productHonesty.finished` means residual honesty sensors are clear not a green graph score. Open blocking violations, ADAPT/SUGGEST with debt, dual-truth pin, or design residual keep `unfinished: true`. |
99
+ | State project binding before verdict | “Ark MCP matched this workspace; `ark_manifest` evidence is authoritative.” Otherwise: “Ark MCP is configured, but runtime identity is unverified. Restart and call `ark_identity` with the exact project root.” |
100
+ | Keep inventory claims evidence-bound | “Possible rule candidate in the configured Application layer.” A filename or technical constant alone is not Domain evidence. |
101
+ | Honesty clear ≠ architecture healthy | `productHonesty.finished` means residual **architecture** honesty sensors are clear — not a green graph score. Open blocking violations, ADAPT/SUGGEST with debt, dual-truth pin, or design residual keep `unfinished: true`. Permanent soft-write alone does **not**. |
102
+ | Separate CI runtime from provider policy | Successful CI run ≠ required status; GitHub Free plan 403 → `unavailable-plan`, not “CI never ran.” |
90
103
 
91
104
  ## Avoid
92
105
 
@@ -100,6 +113,11 @@ Examples:
100
113
  | Skill-shopping lists as the default curriculum | Progressive disclosure: one door first |
101
114
  | “Healthy / done” while design-weak | False done |
102
115
  | “Honesty clear” as “architecture finished” | Honesty clear only means residual honesty sensors are quiet; graph/mode debt is separate |
116
+ | “Not finished” solely because host is Codex/Cursor | Soft-write is environment residual; do not paint a green whole-tree project as unfinished architecture |
117
+ | “MCP installed / active” because a config file exists | Say **configured on disk · runtime unverified** until `ark_identity` matches the expected root |
118
+ | Treating an unverified legacy MCP call as authoritative | Compatibility is not proof; require `binding.status: "matched"` and `authoritative: true` |
119
+ | “Handler means controller” / “every constant is a business rule” | ArkRules inventory uses configured layer context and suppresses narrow technical/test evidence; candidates remain prompts for judgment |
120
+ | Conflating CLI name with required status | `ark-check` is the command; the hard boundary is the GitHub required **status context** |
103
121
  | “ArkRules prove business correctness” | They enforce *declared* structure/coverage evidence, not arbitrary logic or full semantic proof |
104
122
  | “Structure enforced = Domain extraction done” | Structure sensors are **heuristics**; extraction is judgment (`/ark-fix` / pilot) |
105
123
  | “Covered invariant = E2E business tests” | Coverage = symbol/test evidence for a named policy, not a runtime test runner |
package/docs/use.md CHANGED
@@ -33,9 +33,11 @@ Full skill pack is **optional** (expert depth). Day-to-day: compact router + doc
33
33
  | When | What happens |
34
34
  |------|----------------|
35
35
  | While the AI writes | Host write gate or advisory MCP (depends on host) |
36
- | Before merge | `arkgate-check` make it a **required** CI status |
36
+ | Before merge | Make the Ark job a **required GitHub status context** running `arkgate-check --strict-merge` (alias `ark-check`) |
37
37
  | Anytime | Doctor: Suggest / Adapt / Enforce (+ design-weak if residual) |
38
38
 
39
+ **Codex / Cursor / OpenCode:** local write stays advisory forever — that is not unfinished architecture. Doctor may say **contract ready** while still reminding you that local writes are advisory; **Not finished** is reserved for real project/contract debt.
40
+
39
41
  ArkGate is **not** a web framework, ORM, or app runtime. It is architecture enforcement + co-pilot for AI TypeScript.
40
42
 
41
43
  ### Two planes (you choose)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkgate",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "ArkGate — architecture co-pilot for AI TypeScript (write gate, CI gate, plan/loop; optional ArkRules)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -21,6 +21,8 @@
21
21
  "./schema/ark.config.schema.json": "./schemas/ark.config.schema.json",
22
22
  "./schema/analysis-result": "./schemas/ark.analysis-result.schema.json",
23
23
  "./schema/ark.analysis-result.schema.json": "./schemas/ark.analysis-result.schema.json",
24
+ "./schema/project-identity": "./schemas/ark.project-identity.schema.json",
25
+ "./schema/ark.project-identity.schema.json": "./schemas/ark.project-identity.schema.json",
24
26
  "./schema/change-map": "./schemas/ark.change-map.schema.json",
25
27
  "./schema/ark.change-map.schema.json": "./schemas/ark.change-map.schema.json",
26
28
  "./schema/resolved-candidate-facts": "./schemas/ark.resolved-candidate-facts.schema.json",
@@ -0,0 +1,116 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://unpkg.com/arkgate@4/schemas/ark.project-identity.schema.json",
4
+ "title": "ArkGate MCP project identity",
5
+ "description": "Stable project binding plus separate runtime and architecture-contract evidence.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "schemaVersion",
10
+ "projectId",
11
+ "resolvedRoot",
12
+ "resolvedConfigPath",
13
+ "arkgateVersion",
14
+ "contractHash",
15
+ "contractSource",
16
+ "runtimeId",
17
+ "processStartedAt"
18
+ ],
19
+ "properties": {
20
+ "schemaVersion": {
21
+ "const": "1.0"
22
+ },
23
+ "projectId": {
24
+ "type": "string",
25
+ "pattern": "^sha256:[a-f0-9]{64}$"
26
+ },
27
+ "resolvedRoot": {
28
+ "type": "string",
29
+ "minLength": 1
30
+ },
31
+ "resolvedConfigPath": {
32
+ "type": "string",
33
+ "minLength": 1
34
+ },
35
+ "arkgateVersion": {
36
+ "type": "string",
37
+ "minLength": 1
38
+ },
39
+ "contractHash": {
40
+ "type": "string",
41
+ "pattern": "^sha256:[a-f0-9]{64}$"
42
+ },
43
+ "contractSource": {
44
+ "enum": [
45
+ "project",
46
+ "default-profile",
47
+ "manifest"
48
+ ]
49
+ },
50
+ "runtimeId": {
51
+ "type": "string",
52
+ "minLength": 1
53
+ },
54
+ "processStartedAt": {
55
+ "type": "string",
56
+ "format": "date-time"
57
+ }
58
+ },
59
+ "$defs": {
60
+ "expectation": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "properties": {
64
+ "expectedRoot": {
65
+ "type": "string",
66
+ "minLength": 1,
67
+ "description": "Absolute expected workspace/project directory. The initial authoritative handshake requires the exact project root; descendant calls also require expectedProjectId."
68
+ },
69
+ "expectedProjectId": {
70
+ "type": "string",
71
+ "pattern": "^sha256:[a-f0-9]{64}$",
72
+ "description": "Project id previously returned by ark_identity or ark_manifest."
73
+ }
74
+ }
75
+ },
76
+ "binding": {
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "required": [
80
+ "status",
81
+ "authoritative"
82
+ ],
83
+ "properties": {
84
+ "status": {
85
+ "enum": [
86
+ "matched",
87
+ "unverified",
88
+ "mismatch"
89
+ ]
90
+ },
91
+ "authoritative": {
92
+ "type": "boolean"
93
+ },
94
+ "expectedRoot": {
95
+ "type": "string",
96
+ "minLength": 1
97
+ },
98
+ "expectedProjectId": {
99
+ "type": "string",
100
+ "pattern": "^sha256:[a-f0-9]{64}$"
101
+ },
102
+ "code": {
103
+ "enum": [
104
+ "PROJECT_ROOT_MISMATCH",
105
+ "PROJECT_ID_MISMATCH",
106
+ "INVALID_PROJECT_EXPECTATION"
107
+ ]
108
+ },
109
+ "message": {
110
+ "type": "string",
111
+ "minLength": 1
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/pedroknigge/arkgate",
7
7
  "source": "github"
8
8
  },
9
- "version": "4.1.0",
9
+ "version": "4.2.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "arkgate",
14
- "version": "4.1.0",
14
+ "version": "4.2.0",
15
15
  "runtimeHint": "npx",
16
16
  "transport": {
17
17
  "type": "stdio"
@@ -30,6 +30,15 @@ when design smells remain after the contract is honest.
30
30
 
31
31
 
32
32
 
33
+ ## MCP workspace binding (mandatory)
34
+
35
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
36
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
37
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
38
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
39
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
40
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
41
+
33
42
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
34
43
 
35
44
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -31,6 +31,15 @@ The CLI is a **sensor**, never the whole job. Claiming done without the explorat
31
31
 
32
32
 
33
33
 
34
+ ## MCP workspace binding (mandatory)
35
+
36
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
37
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
38
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
39
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
40
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
41
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
42
+
34
43
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
35
44
 
36
45
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -71,8 +80,9 @@ the same files or weaken the gate.
71
80
 
72
81
  ## Steps
73
82
 
74
- 1. **Detect the shape** — call MCP tool **`ark_recommend`** (or run
75
- `ark-check --recommend --json`). Read `archetype`, `preset`, `confidence`,
83
+ 1. **Bind and detect the shape** — complete the mandatory `ark_identity` preflight first, then
84
+ call MCP tool **`ark_recommend`** with the bound `project` envelope (or run the workspace-local
85
+ `ark-check --recommend --json`). Never use an unverified recommendation. Read `archetype`, `preset`, `confidence`,
76
86
  `adoptInOrder.phase1`, `analogy`, `why`, `evidence`, and `requiresConfirmation`.
77
87
  Ask at most **two** questions only if `requiresConfirmation` is true (or for compatibility
78
88
  with older ArkGate output, `confidence < 0.5`):
@@ -65,6 +65,15 @@ decision-grade explore pass **and** without opening violating files.
65
65
 
66
66
 
67
67
 
68
+ ## MCP workspace binding (mandatory)
69
+
70
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
71
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
72
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
73
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
74
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
75
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
76
+
68
77
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
69
78
 
70
79
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -13,7 +13,8 @@ description: Safely edit ark.config.json layers/rules and arkrules/* (structure
13
13
  | Concentrated-edge / false-green STOP from other skills | Full map without config edit → `/ark-explore` |
14
14
 
15
15
  The **one sanctioned way** to change layers/rules/`intentPrefixes`/includes.
16
- Also used to **land mined business rules** into the executable manifest (`ark.config.json` + intent naming that `ark://manifest` exposes).
16
+ Also used to **land mined business rules** into the executable manifest (`ark.config.json` +
17
+ intent naming that the project-bound `ark_manifest` tool exposes authoritatively).
17
18
 
18
19
 
19
20
  ## Dual engine (mandatory)
@@ -27,6 +28,15 @@ The CLI is a **sensor**, never the whole job. Claiming done without the explorat
27
28
 
28
29
 
29
30
 
31
+ ## MCP workspace binding (mandatory)
32
+
33
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
34
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
35
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
36
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
37
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
38
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
39
+
30
40
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
31
41
 
32
42
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -43,6 +43,15 @@ If you did not open source files, the skill is **not complete**.
43
43
  Full recon + pattern planning: `/ark-explore`.
44
44
 
45
45
 
46
+ ## MCP workspace binding (mandatory)
47
+
48
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
49
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
50
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
51
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
52
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
53
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
54
+
46
55
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
47
56
 
48
57
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -27,6 +27,15 @@ The CLI is a **sensor**, never the whole job. Claiming done without the explorat
27
27
 
28
28
 
29
29
 
30
+ ## MCP workspace binding (mandatory)
31
+
32
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
33
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
34
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
35
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
36
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
37
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
38
+
30
39
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
31
40
 
32
41
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -146,7 +155,10 @@ when residual signals remain.
146
155
 
147
156
  ## Spoken / written explanation
148
157
 
149
- 1. **Load the real contract**: `ark.config.json`, `ark://manifest` if available, `AGENTS.md`.
158
+ 1. **Load the real contract**: `ark.config.json`, `AGENTS.md`, and—when MCP is available
159
+ `ark_identity` with the exact project root followed by `ark_manifest` with the same root plus
160
+ returned project id. `ark://manifest` is compatibility-only and always
161
+ unverified/non-authoritative.
150
162
  2. **If asked generally** ("explain the architecture"), produce a guided tour:
151
163
  - Operating mode + governed% (honest: low coverage means green checks almost nothing).
152
164
  - Each major layer: name, purpose, one real file from this repo, file count if known.
@@ -68,6 +68,15 @@ that still matters (dogfood gaps, soft starters, identity drift, **semantic fals
68
68
  say so in one line and hand off `stop`.
69
69
 
70
70
 
71
+ ## MCP workspace binding (mandatory)
72
+
73
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
74
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
75
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
76
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
77
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
78
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
79
+
71
80
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
72
81
 
73
82
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -52,6 +52,15 @@ Next: re-run ark-check; shrink baseline if applicable
52
52
 
53
53
 
54
54
 
55
+ ## MCP workspace binding (mandatory)
56
+
57
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
58
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
59
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
60
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
61
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
62
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
63
+
55
64
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
56
65
 
57
66
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -129,7 +138,7 @@ feature dirs, plan clusters), you **may** dispatch **subagents**:
129
138
  If the “fix” is really a missing business intent or Domain home for a rule:
130
139
 
131
140
  - Propose intent name + layer placement.
132
- - Register / place code so `ark://manifest` / config can enforce it.
141
+ - Register / place code so `ark_manifest` / config can enforce it.
133
142
  - Do not only delete the import.
134
143
 
135
144
  ## Rules
@@ -42,6 +42,15 @@ Pattern bets always have `neverMechanicalSafe: true` — extraction cards only
42
42
 
43
43
 
44
44
 
45
+ ## MCP workspace binding (mandatory)
46
+
47
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
48
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
49
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
50
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
51
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
52
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
53
+
45
54
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
46
55
 
47
56
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -120,8 +129,8 @@ you may run **that one pilot** — never more:
120
129
  card: respect the explicit record and do not reconstruct it from raw facts. Read a live card's
121
130
  `pilotTarget`, `decisionTarget`, `moveSample`/`movesTotal`, `successSignal`, `killSwitch`, `doNot[]`.
122
131
  2. Moves are **proposed only** — enumerate the full move set for the pilot anchor, express it as
123
- an architecture change map, and validate through the atomic preflight (`ark_prepare_change` /
124
- the write gate) **before** any file moves. A move the preflight rejects is a finding, not a
132
+ an architecture change map, and validate through the atomic preflight (`ark_prepare_change`
133
+ with the matched `project` envelope / the write gate) **before** any file moves. A move the preflight rejects is a finding, not a
125
134
  thing to force.
126
135
  3. Never move anything under `app/` or `pages/` (fixed by framework convention). Never merge
127
136
  files here — merges are judgment cards for `/ark-architect` / `/ark-fix`.
@@ -36,6 +36,15 @@ The CLI is a **sensor**, never the whole job. Claiming done without the explorat
36
36
 
37
37
 
38
38
 
39
+ ## MCP workspace binding (mandatory)
40
+
41
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
42
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
43
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
44
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
45
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
46
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
47
+
39
48
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
40
49
 
41
50
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -66,16 +75,18 @@ the same files or weaken the gate.
66
75
 
67
76
  ## Steps
68
77
 
69
- 1. **Read the contract, not your intuition.** If the `ark` MCP server is available,
70
- call the **`ark_place`** tool with the target file path — it returns the layer,
78
+ 1. **Read the contract, not your intuition.** If the `ark` MCP server is available, complete
79
+ the mandatory `ark_identity` preflight first, then call **`ark_place`** with the target file
80
+ path and bound `project` envelope — it returns the layer,
71
81
  its forbidden globals, and exactly which layers the file may / must not import,
72
82
  straight from the contract (no guessing). When present, also honor optional
73
83
  **`goldenPattern`** (from `.ark/golden-pattern.json`) for **NEW code only** —
74
84
  advisory layout norm; never overrides the gate and never clears design-weak.
75
- Absent golden is normal. Otherwise load `ark.config.json` and the
76
- `ark://manifest` MCP resource (it includes `suggestedLayers` with conventional
77
- directories for layers not yet adopted). The project's `AGENTS.md` placement table,
78
- if present, is authoritative too.
85
+ Absent golden is normal. Otherwise load `ark.config.json`; after the matched preflight,
86
+ `ark_manifest` with the same bound envelope includes `suggestedLayers` with conventional
87
+ directories for layers not yet adopted. The `ark://manifest` resource is compatibility-only and always
88
+ unverified/non-authoritative. The project's `AGENTS.md` placement table, if present, is
89
+ authoritative too.
79
90
  2. **Classify the artifact** by what it does, not what it's called:
80
91
  - Pure business rules/entities/value objects → domain-model layer.
81
92
  - When Domain ArkRules require private state / factories (`aggregate-private-state`,
@@ -24,6 +24,14 @@ one feature at a time.
24
24
 
25
25
  The CLI is a **sensor**, never the whole job. Claiming done without the exploratory bar for this skill is **incomplete**.
26
26
 
27
+ ## MCP workspace binding (mandatory)
28
+
29
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
30
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
31
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
32
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
33
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
34
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
27
35
 
28
36
  ## Out of scope for ArkRules
29
37
 
@@ -31,6 +31,15 @@ If you lack a product map and the tree is messy: run a **compressed** explore pa
31
31
  Never reason only from abstract hexagons. Open real modules before recommending a shape.
32
32
 
33
33
 
34
+ ## MCP workspace binding (mandatory)
35
+
36
+ Before any `ark_*` MCP tool, call `ark_identity` with `project.expectedRoot` set to the exact
37
+ workspace root. Continue only when `binding.status === "matched"` and `authoritative === true`;
38
+ retain `projectIdentity.projectId`, then pass both `expectedRoot` and `expectedProjectId` under
39
+ `project` on every later MCP call. If identity is missing, mismatched, unverified, or the root is
40
+ uncertain, do not consume MCP analysis: use the workspace-local CLI and report that MCP
41
+ restart/retargeting is required. `ark://manifest` never satisfies this preflight.
42
+
34
43
  ## Dual plane — layers + ArkRules (mandatory, except /ark-runtime)
35
44
 
36
45
  ArkGate has **two opt-in planes**. The user chooses which to use; you **always label** findings so they never blur.
@@ -71,8 +80,11 @@ feature dirs, plan clusters), you **may** dispatch **subagents**:
71
80
 
72
81
  ## Steps
73
82
 
74
- 1. **Load the contract** — `ark.config.json`, MCP `ark://manifest` if available, and
75
- `ark-check --coverage --json` / `--doctor` for honesty about governed% and false-green.
83
+ 1. **Load the contract** — `ark.config.json`; when MCP is available, call `ark_identity` with
84
+ the exact project root followed by `ark_manifest` with the same root plus returned project
85
+ id. The `ark://manifest` resource is compatibility-only and always
86
+ unverified/non-authoritative. Use `ark-check --coverage --json` / `--doctor` for honesty
87
+ about governed% and false-green.
76
88
  2. **Touch the decision surface** — README skim + **≥5 source files** on the feature/package/boundary
77
89
  under discussion. Name paths in the answer.
78
90
  3. **Name the active shape** — which preset/archetype fits (hexagonal, vertical-slice,