arkgate 4.8.25 → 4.8.27

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 (64) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +2 -2
  3. package/bin/ark-layer-match.mjs +23 -0
  4. package/bin/ark-mcp-runtime.mjs +45 -4
  5. package/bin/ark-mcp.mjs +9 -3
  6. package/bin/ark.mjs +27 -1
  7. package/bin/lib/analysis-engine.mjs +10 -10
  8. package/bin/lib/arkrules-sensors.mjs +9 -4
  9. package/bin/lib/class-source-scan.mjs +1 -1
  10. package/bin/lib/config-contract.mjs +5 -0
  11. package/bin/lib/policy-delta-io.mjs +5 -4
  12. package/bin/lib/prepare-change.mjs +10 -6
  13. package/bin/lib/prepare-write.mjs +7 -0
  14. package/bin/lib/project-root.mjs +12 -23
  15. package/bin/lib/remediation.mjs +84 -0
  16. package/bin/lib/resolved-candidate-facts.mjs +19 -2
  17. package/bin/lib/snippet-analysis.mjs +82 -1
  18. package/dist/chunk-A5EIY3HI.cjs +3 -3
  19. package/dist/chunk-H5I3GARV.js +16 -0
  20. package/dist/chunk-QQ4SJEJ7.cjs +16 -0
  21. package/dist/chunk-SVSQVGFJ.js +3 -3
  22. package/dist/{configTypes-GPvvdleM.d.cts → configTypes-D1oxws6x.d.cts} +6 -0
  23. package/dist/{configTypes-GPvvdleM.d.ts → configTypes-D1oxws6x.d.ts} +6 -0
  24. package/dist/eslint/index.cjs +11 -12
  25. package/dist/eslint/index.d.cts +7 -1
  26. package/dist/eslint/index.d.ts +7 -1
  27. package/dist/eslint/index.js +11 -11
  28. package/dist/index.cjs +32 -32
  29. package/dist/index.d.cts +13 -2
  30. package/dist/index.d.ts +13 -2
  31. package/dist/index.js +32 -32
  32. package/dist/inspectorListen-6DQVJ4DC.js +2 -1
  33. package/dist/inspectorListen-KGMIQ2TF.cjs +2 -1
  34. package/dist/nestjs/index.cjs +1 -1
  35. package/dist/nestjs/index.d.cts +1 -1
  36. package/dist/nestjs/index.d.ts +1 -1
  37. package/dist/nestjs/index.js +1 -1
  38. package/dist/order/index.cjs +1 -1
  39. package/dist/order/index.js +1 -1
  40. package/dist/runtime/index.cjs +10 -10
  41. package/dist/runtime/index.d.cts +4 -3
  42. package/dist/runtime/index.d.ts +4 -3
  43. package/dist/runtime/index.js +10 -10
  44. package/dist/{types-CnauMQQL.d.cts → types-DBiqlOWZ.d.cts} +6 -0
  45. package/dist/{types-CnauMQQL.d.ts → types-DBiqlOWZ.d.ts} +6 -0
  46. package/docs/README.md +3 -1
  47. package/docs/agent-guide.md +9 -6
  48. package/docs/ai-gates.md +1 -1
  49. package/docs/configuration.md +11 -0
  50. package/docs/diagnostics.md +1 -1
  51. package/docs/package-surface.md +2 -1
  52. package/docs/product-voice.md +1 -1
  53. package/package.json +1 -1
  54. package/schemas/ark.config.schema.json +10 -0
  55. package/server.json +2 -2
  56. package/templates/agent-skills/README.md +1 -1
  57. package/templates/agent-skills/ark-adopt/SKILL.md +6 -0
  58. package/templates/agent-skills/ark-autopilot/SKILL.md +1 -1
  59. package/templates/agent-skills/ark-place/SKILL.md +4 -0
  60. package/templates/skills/ark-adopt.md +6 -0
  61. package/templates/skills/ark-autopilot.md +1 -1
  62. package/templates/skills/ark-place.md +4 -0
  63. package/dist/chunk-AHACEKSV.js +0 -16
  64. package/dist/chunk-UN5EH4QV.cjs +0 -16
@@ -78,6 +78,12 @@ type ArkConfigLayer = {
78
78
  name: string;
79
79
  patterns: string[];
80
80
  exclude?: string[];
81
+ /**
82
+ * Optional public surface globs for this layer. When non-empty, cross-layer
83
+ * imports into this layer must target a file matching one of these globs;
84
+ * deep imports into internal layer files are denied.
85
+ */
86
+ entrypoints?: string[];
81
87
  intentPrefixes?: string[];
82
88
  /**
83
89
  * App-context caption for this layer.
@@ -78,6 +78,12 @@ type ArkConfigLayer = {
78
78
  name: string;
79
79
  patterns: string[];
80
80
  exclude?: string[];
81
+ /**
82
+ * Optional public surface globs for this layer. When non-empty, cross-layer
83
+ * imports into this layer must target a file matching one of these globs;
84
+ * deep imports into internal layer files are denied.
85
+ */
86
+ entrypoints?: string[];
81
87
  intentPrefixes?: string[];
82
88
  /**
83
89
  * App-context caption for this layer.
package/docs/README.md CHANGED
@@ -73,7 +73,9 @@ These are **not** the day-to-day product path. They stay in the repo for evidenc
73
73
  | Field adoption kit (scaffolding, not closed) | [field/](field/) |
74
74
  | Runtime hardening (experimental) | [production-hardening.md](production-hardening.md) |
75
75
 
76
- Current release: [CHANGELOG](../CHANGELOG.md) (`arkgate@4.8.25`; confirm npm with `npm view arkgate@4.8.25 version`; does not close `K01`).
76
+ Current release: [CHANGELOG](../CHANGELOG.md) (`arkgate@4.8.27`; confirm npm with `npm view arkgate@4.8.27 version`; does not close `K01`).
77
+ Prior published: [CHANGELOG](../CHANGELOG.md) (`arkgate@4.8.26`).
78
+ Prior published: [CHANGELOG](../CHANGELOG.md) (`arkgate@4.8.25`).
77
79
  Prior published: [CHANGELOG](../CHANGELOG.md) (`arkgate@4.8.24`).
78
80
  Prior published: [CHANGELOG](../CHANGELOG.md) (`arkgate@4.8.23`).
79
81
  Prior published: [CHANGELOG](../CHANGELOG.md) (`arkgate@4.8.22`).
@@ -315,6 +315,7 @@ MCP `ark_recommend` and the `/ark-adopt` skill (leftover name `/ark-architect` i
315
315
  npx ark start --yes # preferred read-only preview: shape → contract → host → CI
316
316
  npx ark start --yes --apply # apply exactly the previewed compact setup
317
317
  npx ark init --archetype crud-product --yes # non-interactive: shape → preset → origin → gates
318
+ npx ark init --baseline --yes # brownfield: freeze existing debt into .ark-baseline.json + wire --baseline in CI
318
319
  npx ark init # TTY wizard: pick application shape (1–8), not a framework
319
320
  npx ark-check --doctor # includes "New here?" when coverage is low or config is fresh
320
321
  npx ark-check --report beginner.html --beginner # simplified HTML for enthusiasts
@@ -559,10 +560,12 @@ When `include` matches **zero** TS/JS files, plan/doctor treat that as **not don
559
560
  The **verdict path refuses** in that state rather than passing: a plain or `--strict`
560
561
  `ark-check` over zero governed files exits 1 with `ANALYSIS_COVERS_NO_FILES`, because
561
562
  every rule is vacuously satisfied on an empty set. It fires when source exists under the
562
- analyzed root and the contract governs none of it, or when the analyzed root is not the
563
- root you asked for (a contract found outside `--root` makes ArkGate adopt the contract's
564
- directory). A genuinely greenfield repo — no governable source anywhere under the root
565
- you asked for — still passes, so `ark init` can land a contract before the code.
563
+ analyzed root and the contract governs none of it. An explicit `--config` path is a file
564
+ and patterns resolve against `--root`. `--strict` exits 2 when that file is outside Git.
565
+ Basename walk-up can still adopt a parent
566
+ `ark.config.json` when `--root` has none. A genuinely greenfield repo — no governable
567
+ source anywhere under the root you asked for — still passes, so `ark init` can land a
568
+ contract before the code.
566
569
 
567
570
  "Source exists" is answered by a probe the contract cannot steer: it ignores `exclude`
568
571
  (otherwise `exclude: ["**"]` would buy a green), skips dot-directories, never follows a
@@ -1555,8 +1558,8 @@ The server exposes these thirteen tools. Every tool accepts the additive
1555
1558
  | `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. |
1556
1559
  | `ark_policy_delta` | `{ baseConfig, candidateConfig?, baseArkRuleFiles?, candidateArkRuleFiles?, acknowledgement? }`: classify a complete contract transition, ArkRules included; never edits the contract. `baseArkRuleFiles` (`{ "<path from baseConfig.arkRules>": <file JSON> }`) is required when `baseConfig` maps `arkRules`. Include each `childSlices.arkRulesFile` path in that map when the wall discovers one. Weakening / new layer / new allow edge needs `adrPath` on the acknowledgement. |
1557
1560
  | `ark_coverage` | No args: report per-layer counts, every unclassified file, unmatched layers, and missing rule edges. |
1558
- | `ark_place` | `{ filePath, description? }`: resolve the governed home for `filePath` (fail-closed without it; never invents a path) and return its import/global constraints. |
1559
- | `ark_prepare_write` | `{ source, filePath, description?, layer? }`: compose placement and snippet validation, with hashes and a mechanical-safe patch when available. `filePath` is required (fail-closed). Partial like `validate_code`: read `lexicalValid`. |
1561
+ | `ark_place` | `{ filePath, description? }`: resolve the governed home for `filePath` (fail-closed without it; never invents a path) and return its import/global constraints, plus `entrypoints` and `targetEntrypoints` when layers declare public entrypoints. |
1562
+ | `ark_prepare_write` | `{ source, filePath, description?, layer? }`: compose placement (`entrypoints`, `targetEntrypoints`) and snippet validation (including immediate 2-hop cycle checks under `cyclePolicy: "strict"`), with hashes, a mechanical-safe patch when available, and `judgmentBrief.blueprint` (ready-to-paste TypeScript port/entrypoint/valve/kernel code on rejection). `filePath` is required (fail-closed). Partial like `validate_code`: read `lexicalValid`. |
1560
1563
  | `ark_prepare_change` | `{ changes, changeMap? }`: preflight one complete create/update/delete batch in memory against the same Effective Contract as `ark-check` (ArkRules included: same `policyHash`, structure/invariant findings; a missing referenced ArkRules file fails closed); ArkRules-plane findings the base tree already has are returned as `preExisting: true` warnings and do not block, so baselined brownfield debt does not reject an unrelated batch; never writes files. |
1561
1564
  | `ark_recommend` | No args: return the deterministic application-shape plan used by `ark-check --recommend --json`. |
1562
1565
  | `ark_suggest_include` | No args: propose TypeScript/JavaScript include roots from workspaces and nested packages. |
package/docs/ai-gates.md CHANGED
@@ -961,7 +961,7 @@ checker from the ref you pin, so an older ref runs an older checker, and that ch
961
961
  config keys (for example `schemaVersion` 1.3, `childSlices`, `sliceIdentity`) with exit 2:
962
962
 
963
963
  ```yaml
964
- - uses: pedroknigge/arkgate@v4.8.25 # same version as the arkgate devDependency
964
+ - uses: pedroknigge/arkgate@v4.8.27 # same version as the arkgate devDependency
965
965
  with:
966
966
  root: .
967
967
  config: ark.config.json
@@ -263,6 +263,17 @@ That sentence is product copy. Not “Rich domain model, business rules, and dom
263
263
  ]
264
264
  ```
265
265
 
266
+ - **`layers[].entrypoints`** (optional) — public entrypoints for the layer (for
267
+ example `["src/infrastructure/index.ts"]`). When present and non-empty, external
268
+ layers that are permitted to import this layer may only import files matching
269
+ `entrypoints`; importing an internal file outside `entrypoints` is rejected as
270
+ `LAYER_IMPORT_VIOLATION` across `ark-check`, `arkgate/eslint`, `AICodeGate`, and
271
+ `ark-mcp`. Same-layer imports remain allowed. Enabling or narrowing `entrypoints`
272
+ is a `strengthening` policy delta; removing or widening `entrypoints` is a
273
+ `weakening` policy delta. Invalid or zero-match globs emit
274
+ `CONFIG_INVALID_LAYER_PATTERN` / `CONFIG_LAYER_PATTERN_NO_MATCHES`. `ark_place`
275
+ and `ark_prepare_write` project `entrypoints` and `targetEntrypoints` so agents
276
+ know which public surface to import before writing.
266
277
  - `intentPrefixes`, `forbiddenGlobals`, `mayImportInfrastructure`, `optional`
267
278
  — `intentPrefixes` is how the ArkRun kernel maps an intent name to a layer at runtime.
268
279
  A layer with a canonical 11-layer name (`DomainModel`, `ApplicationOrchestration`,
@@ -734,7 +734,7 @@ Haken slaving: few slow keys (ξ) determine derived fast state. Field ingest nev
734
734
 
735
735
  **Analysis covered no files**
736
736
 
737
- - **Why:** No file matched the contract `include` and layer patterns under the analyzed root, so the run had nothing to check. Every rule is vacuously satisfied on an empty set: a green here would read exactly like a green over a governed tree while certifying nothing. Usual causes are a `--root` that is not the tree the contract describes (including a contract found outside the requested root, whose directory is then adopted as the project root), `include` / `exclude` patterns that match nothing, layer patterns written for a different layout, or an `include` that matched files none of which belong to a layer.
737
+ - **Why:** No file matched the contract `include` and layer patterns under the analyzed root, so the run had nothing to check. Every rule is vacuously satisfied on an empty set: a green here would read exactly like a green over a governed tree while certifying nothing. Usual causes are a `--root` the contract misses, basename walk-up adopting a parent that governs nothing, or `include` / `exclude` / layer patterns that match nothing. An explicit `--config` path stays a file: the check runs on `--root`.
738
738
  - **Fix:** Point `--root` at the tree the contract describes, or keep the contract inside that tree, or fix the `include` / `exclude` / layer patterns so they match real files — then re-run `npx arkgate-check --root . --config ark.config.json`. `--plan` and `--coverage` report the empty scope without refusing, and `--adopt-contract --write` proposes an `include` that matches the tree. This is a refusal about ArkGate's own inputs, not a finding about your code; no baseline or policy acknowledgement can suppress it, and `exclude` cannot silence it — the "is there source here" probe deliberately ignores the contract's own `exclude`, skips dot-directories, never follows a symlink, and skips `*.config.*` tooling files so a polyglot repo is not mistaken for a mismatch.
739
739
 
740
740
  <a id="ANALYSIS_HOST_UNAVAILABLE"></a>
@@ -69,10 +69,11 @@ hardening guide remains repository-hosted rather than duplicated in the gate tar
69
69
  | **Report parity and snapshot evidence (4.2)** | `ark-check --report` → advisory sections (`data-advisory="contractHealth\|ambientState\|parseHealth\|arkRun"`, 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. Thin `arkRun` on `latest.json` is `notAScore` residual honesty for `ark status`. |
70
70
  | **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. |
71
71
  | **MCP tools and compatibility resource** | `arkgate-mcp`; `ark_manifest`; `ark_status`; `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. **`ark_status`** returns the status manifest envelope (parity with `ark status --json`). 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. Every published `outputSchema` has top-level `type: "object"` and the returned `structuredContent` validates against it (MCP SDK clients check both). A contract edit after startup makes project tools return `CONTRACT_STALE` until restart. `arkgate-mcp --help` / `--version` print and exit. |
72
- | **`ark.config.json`** | Layer globs, optional `layers[].description`, optional `layers[].trustBoundary`, optional `layers[].owners`, optional `requireLayerOwners`, rules, include/exclude, forbiddenGlobals, intent prefixes, `peerIsolation`, `dynamicImportAllowlist`, `safety` thresholds; optional **`coverage`** controls (`testGlobs`, `maxFiles`); optional **`arkRules`** map of one path or a list of paths (schema `1.1+`), plus optional `childSlices.arkRulesFile` and `sliceAliases.pinned`; optional **`arkRun`** extra (schema `1.2+`); optional **`arkOrder`** extra (schema `1.3+`) | Versioned by `schemaVersion`; unknown fields fail closed and migrations preserve the previous supported major. Absence of `coverage`, `arkRules`, `arkRun`, or `arkOrder` is byte-for-byte silent on Layers / ArkRules verdicts. Enforced extra teeth share the CLI / MCP / hook / preflight / CI verdict and arm only when the layer plane is classified (same ArkRules floor). |
72
+ | **`ark.config.json`** | Layer globs, optional `layers[].description`, optional `layers[].trustBoundary`, optional `layers[].owners`, optional `layers[].entrypoints`, optional `requireLayerOwners`, rules, include/exclude, forbiddenGlobals, intent prefixes, `peerIsolation`, `dynamicImportAllowlist`, `safety` thresholds; optional **`coverage`** controls (`testGlobs`, `maxFiles`); optional **`arkRules`** map of one path or a list of paths (schema `1.1+`), plus optional `childSlices.arkRulesFile` and `sliceAliases.pinned`; optional **`arkRun`** extra (schema `1.2+`); optional **`arkOrder`** extra (schema `1.3+`) | Versioned by `schemaVersion`; unknown fields fail closed and migrations preserve the previous supported major. Absence of `coverage`, `arkRules`, `arkRun`, or `arkOrder` is byte-for-byte silent on Layers / ArkRules verdicts. Enforced extra teeth share the CLI / MCP / hook / preflight / CI verdict and arm only when the layer plane is classified (same ArkRules floor). |
73
73
  | **Layer caption (`layers[].description`, 4.8.7)** | Optional string on each layer. Projected onto `ark_place` / prepare-write / MCP place JSON, doctor JSON + human, coverage JSON, and the HTML Purpose column when present. `/ark-adopt` writes it from the product map or glossary; `/ark-place` prints it next to layer name + globs. | Existing optional field — **no `schemaVersion` bump**, no new key, no 14th skill. Copy is **app context** (a product sentence such as `Purchase requests — from asked to received.`), not architecture jargon. Stripped from `policyHash` like `stewards`; caption-only edits are neutral. Absence is silent: never a residual, never a score, never `--strict-config` fail, never flips `valid`. Compact starters may omit. |
74
74
  | **Layer trust (`layers[].trustBoundary`)** | Optional closed tag on each layer: `public` \| `auth` \| `admin` \| `internal`. Projected onto `ark_place` / prepare-write / MCP place JSON, doctor JSON + human, coverage JSON, and the HTML report when present. `/ark-adopt` writes it when the product map names that door; `/ark-place` prints `trust: public`. | Additive optional field — **no `schemaVersion` bump**, no new skill. Stripped from `policyHash` like `stewards` and `layers[].description`; tag-only edits are neutral. Absence is silent: never a residual, never a score, never `--strict-config` fail, never flips `valid`. Invalid values fail the schema. Compact starters may omit. Not host/CI TLS. Not an import-rule matrix. |
75
75
  | **Layer owners (`layers[].owners` + `requireLayerOwners`)** | Optional GitHub handles or emails on each layer. Projected onto place / prepare-write / MCP / doctor / coverage / HTML when present. `requireLayerOwners: true` asks for owners on every live (non-reserved) layer: doctor names the first missing house, `--strict-config` refuses, and the write gate denies a write into that house. | Additive optional fields — **no `schemaVersion` bump**, no new skill. Owners are stripped from `policyHash` like captions; owner-only edits are neutral. The require flag stays in the hash. Absence of owners is silent unless the require flag is on. Invalid identity (display name) fails the schema. Compact starters may omit. Not import-rule teeth. No `/ark-owners`. |
76
+ | **Layer entrypoints (`layers[].entrypoints`, 4.8.27)** | Optional non-empty glob array on each layer declaring its public entrypoints. Projected onto `ark_place` / `ark_prepare_write` (`entrypoints`, `targetEntrypoints`). External layers allowed to import the target layer must import via `entrypoints`; internal files outside `entrypoints` fail with `LAYER_IMPORT_VIOLATION` across CLI, ESLint, `AICodeGate`, and MCP, with a deterministic `blueprint` snippet on rejection. | Additive optional field — **no `schemaVersion` bump**, no new skill. Enforced at the single `findDeniedEdgeDecision` waist. Policy-delta classifies enabling/narrowing as `strengthening` and removing/widening as `weakening`. Absence changes no verdict. |
76
77
  | **ArkRules inventory / under-contract (4.0; layer context 4.2)** | `ark-check --rules-inventory [--json]`; doctor `rulesUnderContract` + `rulesMigration`; MCP `ark_rules_inventory` | Additive. Honest counts (inventoried / under-contract / frozen) — **never a score**. Structure candidates count as under contract by declared (layer, sensor); frozen counts `ARKRULE_*` / `INVARIANT_*` baseline keys. CLI and MCP payloads share one builder (same keys, incl. `coverageEvidence`). 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. |
77
78
  | **`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`. |
78
79
  | **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. |
@@ -80,7 +80,7 @@ On the seven lane openings — `docs/use.md`, `docs/develop.md`, `docs/README.md
80
80
  `README.md` is the first-contact module. Its first screen is four beats: what
81
81
  (**Contener · Guiar · Ordenar**), why (design the boundary before you implement;
82
82
  a green check is **needs a refactor** when leftover mess remains), one command
83
- (`npx arkgate@4.8.25 start`), and one honest red result (fail-open named; required
83
+ (`npx arkgate@4.8.27 start`), and one honest red result (fail-open named; required
84
84
  CI is the hard line). The four paragraphs, the not-that line, the host matrix,
85
85
  and the release index sit below `## Appendix`. The not-that line does not lead
86
86
  the README.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkgate",
3
- "version": "4.8.25",
3
+ "version": "4.8.27",
4
4
  "description": "When the agent writes a bad import, the write doesn’t land. The same check fails the pull request.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -699,6 +699,16 @@
699
699
  },
700
700
  "uniqueItems": true
701
701
  },
702
+ "entrypoints": {
703
+ "type": "array",
704
+ "items": {
705
+ "type": "string",
706
+ "minLength": 1
707
+ },
708
+ "uniqueItems": true,
709
+ "minItems": 1,
710
+ "description": "Optional public surface globs for this layer. When non-empty, cross-layer imports into this layer must target a file matching one of these globs; deep imports into internal layer files are denied."
711
+ },
702
712
  "intentPrefixes": {
703
713
  "type": "array",
704
714
  "items": {
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/pedroknigge/arkgate",
7
7
  "source": "github"
8
8
  },
9
- "version": "4.8.25",
9
+ "version": "4.8.27",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "arkgate",
14
- "version": "4.8.25",
14
+ "version": "4.8.27",
15
15
  "runtimeHint": "npx",
16
16
  "transport": {
17
17
  "type": "stdio"
@@ -9,7 +9,7 @@ closed `/ark-*` catalog shipped as flat templates for Ark install.
9
9
  **Closed catalog** (`ARK_SKILL_NAMES`) — first-class doors plus one-release
10
10
  redirect stubs. Add a name only with a live ROADMAP item.
11
11
 
12
- Package version when last generated context: **arkgate@4.8.25**
12
+ Package version when last generated context: **arkgate@4.8.27**
13
13
  Schema: agent-skills package contract `1.0`
14
14
 
15
15
  ## Skills (closed catalog)
@@ -35,6 +35,12 @@ has honest houses. Skills never enforce — CLI / hooks / CI do.
35
35
  (GitHub handle or email). Compact starter may omit. Do not invent people.
36
36
  Absence is silent unless the user asked for required owners — then write
37
37
  `requireLayerOwners: true` after the live houses have names. No `/ark-owners`.
38
+ - When a layer exposes a deliberate public barrel or facade (e.g. `src/domain/index.ts`),
39
+ optional `layers[].entrypoints` restricts cross-layer imports into that layer to matching
40
+ globs. Intra-layer imports stay unrestricted. Absence is silent. No `/ark-entrypoints`.
41
+ - On brownfield trees with genuine pre-existing debt, `ark init --baseline` (or
42
+ `arkgate-check --write-baseline`) freezes `.ark-baseline.json` so `--strict-merge`
43
+ blocks only new regressions.
38
44
  - When the user wants required gates (`--require-gates` / `--strict-merge` /
39
45
  required GitHub check) and there is no `docs/adr/` (or `docs/decisions/`),
40
46
  leave a short decision note there — only if they loosen a rule or add a real
@@ -258,7 +258,7 @@ Status lights from doctor — not settings you choose. Rank residual honestly:
258
258
  **STOP — do not continue this skill as complete.** **STOP — concentrated edge:** rewrite `ark.config.json` **in this turn** with source evidence (do not freeze a wrong config or grind N freezes).
259
259
  6. **Worktree preferred** — discardable git worktree when possible.
260
260
  7. **Mechanical-safe (A only)** — kinds from `/ark-loop` table; one step, validate, rollback.
261
- 8. **Judgment (A)** — implement with full “así te lo re-soluciono”; validate; rollback on fail.
261
+ 8. **Judgment (A)** — implement with full “así te lo re-soluciono” (use the deterministic `blueprint` / `judgmentBrief.blueprint` TypeScript skeleton when present for `FORBIDDEN_GLOBAL`, `CAPABILITY_VIOLATION`, `LAYER_IMPORT_VIOLATION`, `ARKORDER_*`, or `ARKRUN_DIRECT_NEW`); validate; rollback on fail.
262
262
  9. **Pattern bets (B)** — apply **one** extraction-card pilot this turn; leave the rest queued. Never weaken the gate to clear B.
263
263
  10. **Manifiesto** — loose business rules → Domain placement + `intentPrefixes` / intents; write config here if the path is still dishonest.
264
264
  11. **Final report** — re-`--report`; evolution vs origin; A applied vs open; B proposed/deferred; gates on.
@@ -49,6 +49,10 @@ right house. Skills never enforce — CLI / hooks / CI do.
49
49
  to the layer name and globs. Omit when absent — do not invent a person or `/ark-owners`.
50
50
  When `requireLayerOwners` is on and the house has no owners, send that gap to
51
51
  `/ark-adopt` before writing.
52
+ - When `ark_place` / `ark_prepare_write` returns `entrypoints` or `targetEntrypoints`,
53
+ import allowed layers through their listed public entrypoints (barrels/facades) rather
54
+ than deep internal paths. When `ark_prepare_write` returns `judgmentBrief.blueprint`,
55
+ use that TypeScript Port/valve/entrypoint skeleton to satisfy the boundary before writing.
52
56
  - When `arkRun` is on: scaffold through the kernel (no `new` of managed types; declare
53
57
  `uses` / `reactsTo` / `raises` / `sends`; factory only in `arkRun.kernelRoots`,
54
58
  `compositionRoots` alias). Extra off → do not introduce the kernel. Enable it
@@ -35,6 +35,12 @@ has honest houses. Skills never enforce — CLI / hooks / CI do.
35
35
  (GitHub handle or email). Compact starter may omit. Do not invent people.
36
36
  Absence is silent unless the user asked for required owners — then write
37
37
  `requireLayerOwners: true` after the live houses have names. No `/ark-owners`.
38
+ - When a layer exposes a deliberate public barrel or facade (e.g. `src/domain/index.ts`),
39
+ optional `layers[].entrypoints` restricts cross-layer imports into that layer to matching
40
+ globs. Intra-layer imports stay unrestricted. Absence is silent. No `/ark-entrypoints`.
41
+ - On brownfield trees with genuine pre-existing debt, `ark init --baseline` (or
42
+ `arkgate-check --write-baseline`) freezes `.ark-baseline.json` so `--strict-merge`
43
+ blocks only new regressions.
38
44
  - When the user wants required gates (`--require-gates` / `--strict-merge` /
39
45
  required GitHub check) and there is no `docs/adr/` (or `docs/decisions/`),
40
46
  leave a short decision note there — only if they loosen a rule or add a real
@@ -258,7 +258,7 @@ Status lights from doctor — not settings you choose. Rank residual honestly:
258
258
  **STOP — do not continue this skill as complete.** **STOP — concentrated edge:** rewrite `ark.config.json` **in this turn** with source evidence (do not freeze a wrong config or grind N freezes).
259
259
  6. **Worktree preferred** — discardable git worktree when possible.
260
260
  7. **Mechanical-safe (A only)** — kinds from `/ark-loop` table; one step, validate, rollback.
261
- 8. **Judgment (A)** — implement with full “así te lo re-soluciono”; validate; rollback on fail.
261
+ 8. **Judgment (A)** — implement with full “así te lo re-soluciono” (use the deterministic `blueprint` / `judgmentBrief.blueprint` TypeScript skeleton when present for `FORBIDDEN_GLOBAL`, `CAPABILITY_VIOLATION`, `LAYER_IMPORT_VIOLATION`, `ARKORDER_*`, or `ARKRUN_DIRECT_NEW`); validate; rollback on fail.
262
262
  9. **Pattern bets (B)** — apply **one** extraction-card pilot this turn; leave the rest queued. Never weaken the gate to clear B.
263
263
  10. **Manifiesto** — loose business rules → Domain placement + `intentPrefixes` / intents; write config here if the path is still dishonest.
264
264
  11. **Final report** — re-`--report`; evolution vs origin; A applied vs open; B proposed/deferred; gates on.
@@ -49,6 +49,10 @@ right house. Skills never enforce — CLI / hooks / CI do.
49
49
  to the layer name and globs. Omit when absent — do not invent a person or `/ark-owners`.
50
50
  When `requireLayerOwners` is on and the house has no owners, send that gap to
51
51
  `/ark-adopt` before writing.
52
+ - When `ark_place` / `ark_prepare_write` returns `entrypoints` or `targetEntrypoints`,
53
+ import allowed layers through their listed public entrypoints (barrels/facades) rather
54
+ than deep internal paths. When `ark_prepare_write` returns `judgmentBrief.blueprint`,
55
+ use that TypeScript Port/valve/entrypoint skeleton to satisfy the boundary before writing.
52
56
  - When `arkRun` is on: scaffold through the kernel (no `new` of managed types; declare
53
57
  `uses` / `reactsTo` / `raises` / `sends`; factory only in `arkRun.kernelRoots`,
54
58
  `compositionRoots` alias). Extra off → do not introduce the kernel. Enable it