arkgate 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +142 -0
- package/README.md +7 -5
- package/bin/ark-check-runtime.mjs +244 -25
- package/bin/ark-check.mjs +10 -1
- package/bin/ark-layer-match.mjs +80 -5
- package/bin/ark-shared.mjs +170 -9
- package/bin/ark.mjs +52 -5
- package/bin/lib/adapter-contract.mjs +7 -1
- package/bin/lib/agent-gates.mjs +2 -0
- package/bin/lib/analysis-engine.mjs +6 -6
- package/bin/lib/arkrules-sensors.mjs +63 -22
- package/bin/lib/ci-and-commands.mjs +148 -8
- package/bin/lib/core-ratchet.mjs +9 -4
- package/bin/lib/doctor-advisories.mjs +8 -1
- package/bin/lib/doctor-plan.mjs +277 -59
- package/bin/lib/enforcement-honesty.mjs +351 -26
- package/bin/lib/enforcement-state.mjs +1 -1
- package/bin/lib/field-install.mjs +35 -2
- package/bin/lib/graph-blind.mjs +1 -1
- package/bin/lib/html-report-advisories.mjs +8 -25
- package/bin/lib/html-report-depth.mjs +167 -3
- package/bin/lib/html-report.mjs +12 -5
- package/bin/lib/install-migrate.mjs +109 -6
- package/bin/lib/managed-upgrade.mjs +100 -1
- package/bin/lib/presets.mjs +314 -46
- package/bin/lib/project-root.mjs +268 -0
- package/bin/lib/remediation.mjs +12 -11
- package/bin/lib/rules-inventory.mjs +71 -29
- package/bin/lib/rules-under-contract.mjs +389 -5
- package/bin/lib/start-preview.mjs +48 -14
- package/bin/lib/suggestions.mjs +118 -3
- package/bin/lib/unavailable-analysis.mjs +2 -0
- package/bin/lib/upgrade-command.mjs +325 -14
- package/bin/lib/write-path-capabilities.mjs +38 -9
- package/dist/eslint/index.cjs +2 -2
- package/dist/eslint/index.d.ts +27 -2
- package/dist/eslint/index.js +2 -2
- package/dist/index.cjs +16 -14
- package/dist/index.d.ts +3 -1
- package/dist/index.js +16 -14
- package/docs/README.md +3 -2
- package/docs/ai-gates.md +15 -11
- package/docs/brownfield-adoption.md +38 -0
- package/docs/configuration.md +59 -7
- package/docs/package-surface.md +3 -2
- package/docs/product-voice.md +10 -1
- package/docs/typescript-support.md +9 -5
- package/docs/use.md +7 -5
- package/package.json +3 -1
- package/server.json +3 -3
- package/templates/architecture-playbook.json +3 -0
- package/templates/layers/shared-types.starter.json +29 -0
- package/templates/skills/ark-adopt.md +2 -0
- package/templates/skills/ark-explain.md +23 -5
- package/templates/skills/ark-explore.md +21 -1
- package/templates/skills/ark-fix.md +16 -5
- package/templates/skills/ark-upgrade.md +57 -11
package/docs/README.md
CHANGED
|
@@ -57,8 +57,9 @@ These are **not** the day-to-day product path. They stay in the repo for evidenc
|
|
|
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
|
+
Current published: [releases/4.0.1.md](releases/4.0.1.md) (`arkgate@4.0.1` on npm `latest`).
|
|
61
|
+
Next prepared: [releases/4.1.0.md](releases/4.1.0.md) (`arkgate@4.1.0` — field product phases + CI PR slim; not published until registry).
|
|
62
|
+
Previous major: [releases/4.0.0.md](releases/4.0.0.md) (`arkgate@4.0.0`).
|
|
62
63
|
Config: [configuration.md](configuration.md) · Agent skills dual-plane: [agent-guide.md](agent-guide.md).
|
|
63
64
|
|
|
64
65
|
---
|
package/docs/ai-gates.md
CHANGED
|
@@ -560,21 +560,25 @@ export default [
|
|
|
560
560
|
|
|
561
561
|
**Exact layer-edge parity envelope:** the linted production source is on disk, inside
|
|
562
562
|
`include`, outside configured/generated exclusions, parse-clean, and uses a static
|
|
563
|
-
`import`/`export` with a relative
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
not-yet-created target.
|
|
563
|
+
`import`/`export` with a **relative** or **tsconfig `paths` / `baseUrl` alias** (e.g. `@/*`)
|
|
564
|
+
literal whose target is also on disk. Inside that envelope, ESLint uses the same layer glob
|
|
565
|
+
specificity, rule decision, rule id, and evidence as the resolved CLI. It reloads
|
|
566
|
+
`ark.config.json` when its content changes and never invents a not-yet-created target.
|
|
567
567
|
|
|
568
|
-
|
|
569
|
-
`
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
568
|
+
**Path-alias residual (honest):** simple `paths` + `baseUrl` (including one level of relative
|
|
569
|
+
`extends`) are resolved. Not claimed: TypeScript project references, multi-target path arrays
|
|
570
|
+
beyond the first entry, catch-all `*` mappings, package/workspace bare imports, or symlink
|
|
571
|
+
hops. Those stay CI / preflight / write-gate truth.
|
|
572
|
+
|
|
573
|
+
Outside that envelope—packages/workspaces, symlinks, CommonJS, `import = require`, dynamic
|
|
574
|
+
imports, virtual creates/deletes, unresolved targets, or complete cross-file candidates—ESLint
|
|
575
|
+
emits no layer-parity verdict. Use `ark preflight`, `ark_prepare_change`, the complete
|
|
576
|
+
ApplyPatch hook, or final strict CI; those paths consume the canonical resolved facts.
|
|
573
577
|
|
|
574
578
|
Additional rule notes:
|
|
575
579
|
|
|
576
|
-
- Relative imports
|
|
577
|
-
-
|
|
580
|
+
- Relative and tsconfig-aliased imports resolve only to existing on-disk TS/JS targets; package bare imports are left to CI/TS.
|
|
581
|
+
- Value forbidden edges error (same pass/fail as `arkgate-check`). Type-only forbidden edges are **placement debt** (reported with `typeOnly`); merge blocking prefers value edges — align with doctor `typeEdgePolicy`.
|
|
578
582
|
- `no-forbidden-globals` applies from the file layer’s `forbiddenGlobals`; the `globals` option is only a standalone fallback when no project config applies, never an override that weakens the project contract. Layers without either surface are not inventively restricted. `process` also owns exact value imports of `process` / `node:process`; type-only forms, subpaths, and `child_process` stay excluded. If the same layer also denies the `process` capability, this rule is the single `FORBIDDEN_GLOBAL` voice.
|
|
579
583
|
- Without `ark.config.json`, `no-domain-infra-imports` emits no contract verdict.
|
|
580
584
|
|
|
@@ -20,6 +20,42 @@ every ungoverned directory** (harvested from the 11-layer profile + presets; unr
|
|
|
20
20
|
ones are flagged for you to classify, never guessed). Keep an existing config; don't
|
|
21
21
|
regenerate it unasked.
|
|
22
22
|
|
|
23
|
+
### Next.js honesty (default overlays / ui-surface / monorepo)
|
|
24
|
+
|
|
25
|
+
**App Router API routes are Application / use-case shell by default**, not Presentation/UI:
|
|
26
|
+
|
|
27
|
+
| Path | Default layer |
|
|
28
|
+
|------|----------------|
|
|
29
|
+
| `app/api/**`, `src/app/api/**` | **ApplicationOrchestration** (orchestration shell) |
|
|
30
|
+
| `pages/api/**`, `src/pages/api/**` | **ApplicationOrchestration** |
|
|
31
|
+
| UI routes (`app/(…)`, `page.tsx`, `components/**`) | **PresentationAdapters** |
|
|
32
|
+
|
|
33
|
+
Without this split, broad `**/app/**` Presentation patterns push every API handler into UI and
|
|
34
|
+
create a Presentation→Persistence tsunami. Specificity still wins: more-specific Application
|
|
35
|
+
globs beat Presentation. ArkRules stay **opt-in** (not forced on by start/adopt).
|
|
36
|
+
|
|
37
|
+
### Composition-root / factory modules (optional Application-only)
|
|
38
|
+
|
|
39
|
+
Many brownfield trees park DI composition roots and object factories next to domain code
|
|
40
|
+
(`src/factories/**`, `src/composition/**`, `src/app/container.ts`). Those modules are
|
|
41
|
+
**wiring**, not domain rules:
|
|
42
|
+
|
|
43
|
+
| Pattern | Recommended layer | Why |
|
|
44
|
+
|---------|-------------------|-----|
|
|
45
|
+
| `**/factories/**`, `**/composition/**`, `**/container.ts`, `**/bootstrap.ts` | **ApplicationOrchestration** (or a dedicated optional CompositionRoot layer if you need it) | Constructs aggregates / wires ports; may import Domain + Persistence adapters |
|
|
46
|
+
| Aggregate `static create` / private ctor factories **inside** domain entities | **DomainModel** | Always-valid factory is a domain rule (ArkRules `always-valid-factory`), not composition |
|
|
47
|
+
| NestJS modules / providers | FrameworkAdapters / Application | Framework shell, not Domain |
|
|
48
|
+
|
|
49
|
+
Do **not** map composition roots into DomainModel solely because a file constructs entities —
|
|
50
|
+
that turns honest Application→Domain edges into false Domain purity failures. Prefer:
|
|
51
|
+
|
|
52
|
+
1. Application patterns that match `**/factories/**` / `**/composition/**` (higher specificity than broad Domain globs), or
|
|
53
|
+
2. An optional **CompositionRoot** layer that may depend on Domain + Persistence and is
|
|
54
|
+
forbidden as a dependency *from* Domain (mirror Application rules).
|
|
55
|
+
|
|
56
|
+
Field note (S3.1.3): factory-bag composition roots belong in Application (or CompositionRoot),
|
|
57
|
+
not Domain — document the choice in `ark.config.json` rather than freezing factory noise.
|
|
58
|
+
|
|
23
59
|
## 2. Diagnose before you freeze
|
|
24
60
|
|
|
25
61
|
```bash
|
|
@@ -53,6 +89,8 @@ structure / invariants). Case study shape:
|
|
|
53
89
|
|
|
54
90
|
**Upgrade note (4.0):** `ark upgrade --no-install` can refresh skills/gates while leaving
|
|
55
91
|
`package.json` on an older pin—doctor exposes `packageVersionTruth` when the CLI is ahead.
|
|
92
|
+
Prefer project-local `npx arkgate upgrade …` over bare PATH `ark` — global **2.x** is mutative
|
|
93
|
+
and unsafe next to 3.8+/4.0 ([field footgun](releases/4.0.0.md#field-footgun--global-arkgate-2x-on-path)).
|
|
56
94
|
|
|
57
95
|
## 3. Make the contract real (via `/ark-contract`)
|
|
58
96
|
|
package/docs/configuration.md
CHANGED
|
@@ -107,6 +107,42 @@ Rule fields:
|
|
|
107
107
|
when both paths classify. Missing paths, empty slice folders, or unclassifiable slices
|
|
108
108
|
**fail closed** (deny — cannot prove same-slice).
|
|
109
109
|
|
|
110
|
+
### Type-only edges (placement debt)
|
|
111
|
+
|
|
112
|
+
`import type` / `export type` and pure type-only named bindings are **type placement debt**, not
|
|
113
|
+
runtime coupling. They still appear on the **violations** list with `typeOnly: true`,
|
|
114
|
+
`failsStrict: false`, and adapter diagnostic **severity: warning** so doctor/HTML keep
|
|
115
|
+
`violations.typeOnly` / `typeEdgePolicy` honest — but they **do not** fail merge/exit, library
|
|
116
|
+
`valid`, or preflight the way **value** edges do. **Exception:** `peerIsolation` slice
|
|
117
|
+
boundaries stay hard even for type-only. A value import of a pure-type barrel is still a value
|
|
118
|
+
edge (not soft-skipped). Prefer placing shared types in a **SharedTypes** (or owning) layer
|
|
119
|
+
both sides may import. Optional starter: [`templates/layers/shared-types.starter.json`](../templates/layers/shared-types.starter.json)
|
|
120
|
+
(layer globs + allow rules). Doctor always emits `violations.typeEdgePolicy`; plan groups type-only
|
|
121
|
+
steps under `plan.typeOnlyGroup` when volume is high.
|
|
122
|
+
|
|
123
|
+
### Next.js API shell (framework overlay / presets)
|
|
124
|
+
|
|
125
|
+
When Next is detected (or `ui-surface` / monorepo patterns apply), **`app/api/**` and
|
|
126
|
+
`pages/api/**` classify as Application orchestration**, not Presentation. UI routes stay
|
|
127
|
+
Presentation. More-specific Application globs win over broad `**/app/**` Presentation patterns.
|
|
128
|
+
See [brownfield adoption](brownfield-adoption.md#nextjs-honesty-default-overlays--ui-surface--monorepo).
|
|
129
|
+
|
|
130
|
+
### ArkRules dual plane (when `arkRules` is present)
|
|
131
|
+
|
|
132
|
+
| Plane | What it is | Merge teeth |
|
|
133
|
+
|-------|------------|-------------|
|
|
134
|
+
| **Layers** | Inter-layer import graph | Always on |
|
|
135
|
+
| **Structure sensors** | Intra-layer heuristics | Only `mode: "enforced"` |
|
|
136
|
+
| **Invariants** | Catalog + coverage evidence (not a business runtime) | Only enforced + proven-uncovered |
|
|
137
|
+
|
|
138
|
+
Absence of `arkRules` adds **no** extra merge teeth. **Advisory** structure sensors and advisory
|
|
139
|
+
invariants also add **no** merge teeth (FG-ARKRULES-ADVISORY-ONLY) — packing every starter
|
|
140
|
+
`arkrules/*` file does not make merge fail structure alone. Enforced structure/invariants arm
|
|
141
|
+
`mergePlanes.extraMergeTeeth` only when the layer plane is honestly classified
|
|
142
|
+
(governed ≥ 50% and ≥ 1 populated layer); empty classification never gets structure teeth
|
|
143
|
+
(P1M-EXTRATEETH-EMPTY-GRAPH). Structure and invariants **never** merge into one architecture
|
|
144
|
+
score. Doctor exposes `rulesUnderContract.mergePlanes` for which plane can fail.
|
|
145
|
+
|
|
110
146
|
Safety fields:
|
|
111
147
|
|
|
112
148
|
- `maxTsSuppressions`, `maxAnyCasts`
|
|
@@ -119,20 +155,36 @@ policy.
|
|
|
119
155
|
|
|
120
156
|
Sibling schema export: `arkgate/schema/arkrules` (`schemas/ark.arkrules.schema.json`).
|
|
121
157
|
|
|
158
|
+
**Two planes (never one score):**
|
|
159
|
+
|
|
160
|
+
| Plane | Question | Where |
|
|
161
|
+
|-------|----------|--------|
|
|
162
|
+
| **[Layer]** (inter-layer) | Who may import whom? Pure / forbidden globals / capabilities? | `layers[]` + `rules[]` |
|
|
163
|
+
| **[ArkRules]** (intra-layer, opt-in) | How is code shaped *inside* a layer, and which named business policies are catalogued with coverage evidence? | `arkRules` map + `arkrules/<ExactLayerName>.json` |
|
|
164
|
+
|
|
165
|
+
Absence of `arkRules` is valid: only the Layers plane runs; inter-layer verdict is unchanged.
|
|
166
|
+
|
|
122
167
|
Each `arkrules/<Layer>.json` may declare:
|
|
123
168
|
|
|
124
|
-
| Section | Purpose | Modes |
|
|
125
|
-
|
|
126
|
-
| `structure[]` | Closed sensor ids (e.g. `aggregate-private-state`, `always-valid-factory`, `
|
|
127
|
-
| `invariants[]` | Stable ids + description +
|
|
169
|
+
| Section | Purpose | Modes | What it really enforces |
|
|
170
|
+
|---------|---------|--------|-------------------------|
|
|
171
|
+
| `structure[]` | Closed sensor ids (e.g. `orchestration-only`, `thin-adapter`, `aggregate-private-state`, `always-valid-factory`, `domain-event-on-mutation`, `no-anemic-model`) | `advisory` (default) or `enforced` | **Heuristics of module shape** — not proof that logic was extracted to Domain. Tier-2 sensors (`no-anemic-model`) stay advisory-only (cannot promote to enforced). |
|
|
172
|
+
| `invariants[]` | Stable ids + description + `coverage` (`test` / `symbol`) + optional `appliesTo` globs | `advisory` or `enforced` | **Named policy + evidence** (symbol in source and/or test title/content). Does **not** execute business logic at check time and does **not** replace behavior/property tests. |
|
|
128
173
|
|
|
129
174
|
**Reporting:** diagnostics carry `evidence.arkruleId` + `evidence.arkruleSource`. Label residual
|
|
130
|
-
**`[Layer]`**
|
|
131
|
-
|
|
175
|
+
**`[Layer]`** vs **`[ArkRules]`** in agent output. Doctor / HTML: `rulesUnderContract` (catalog +
|
|
176
|
+
counts, **never a score**). Showcase HTML lists per-layer totals, structure sensors, uncovered
|
|
177
|
+
invariants, and a covered sample when the map is active.
|
|
132
178
|
|
|
133
179
|
**Promotion:** advisory→enforced is strengthening when coverage evidence exists; demote/delete is
|
|
134
180
|
a hash-bound policy weakening. Empty `appliesTo: []` fails closed; zero-match globs emit
|
|
135
|
-
`ARKRULE_SCOPE_EMPTY` (advisory warn / enforced fail).
|
|
181
|
+
`ARKRULE_SCOPE_EMPTY` (advisory warn / enforced fail). Enforced + proven uncovered →
|
|
182
|
+
`INVARIANT_UNCOVERED` with `failsStrict` (partial evidence stays honest, never fake-green).
|
|
183
|
+
|
|
184
|
+
**What they do not do:** prove business semantics end-to-end; replace Layers import edges;
|
|
185
|
+
make “green” mean elegant Shape. Promoting structure to enforced can force rename-to-pass
|
|
186
|
+
heuristics — prefer judgment extraction via `/ark-fix` / `/ark-loop` when the real goal is
|
|
187
|
+
Domain ownership.
|
|
136
188
|
|
|
137
189
|
```bash
|
|
138
190
|
# Brownfield candidates (not a score)
|
package/docs/package-surface.md
CHANGED
|
@@ -189,6 +189,7 @@ production deployment would need to satisfy; it is not a readiness certification
|
|
|
189
189
|
## Release notes (maintainers)
|
|
190
190
|
|
|
191
191
|
Ship notes for a version live under [releases/](https://github.com/pedroknigge/arkgate/tree/main/docs/releases)
|
|
192
|
-
(
|
|
193
|
-
|
|
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)).
|
|
194
195
|
Publish path: signed annotated tag → GitHub Release → `publish-npm.yml` (see [CONTRIBUTING.md](https://github.com/pedroknigge/arkgate/blob/main/CONTRIBUTING.md)).
|
package/docs/product-voice.md
CHANGED
|
@@ -51,8 +51,11 @@ Examples:
|
|
|
51
51
|
| **contract** | `ark.config.json` layers, rules, include — the machine-readable architecture file |
|
|
52
52
|
| **Layers plane** | Inter-layer edges: imports, placement, purity, isolation |
|
|
53
53
|
| **ArkRules** (opt-in) | Intra-layer structure sensors + domain invariant catalogs as data (`arkrules/*`) |
|
|
54
|
+
| **advisory ArkRules** | Default sensor mode — **not** merge teeth; does not fail CI/merge alone (FG-ARKRULES-ADVISORY-ONLY) |
|
|
55
|
+
| **extraMergeTeeth** | Only when enforced structure/invariant rules exist **and** classification is honest (≥50% governed, ≥1 populated layer) |
|
|
54
56
|
| **dual-plane residual** | Label findings **`[Layer]`** vs **`[ArkRules]`** — never blur them |
|
|
55
57
|
| **rulesUnderContract** | Doctor/inventory counts for ArkRules — **never a score** |
|
|
58
|
+
| **type-only placement debt** | `import type` edges on the violations list with `failsStrict:false` — prefer SharedTypes / owning layer; not runtime coupling |
|
|
56
59
|
| **gate** / **write gate** | Host boundary that blocks or advises on invalid writes |
|
|
57
60
|
| **edges** | Allowed import graph (plan **A** / remediation) |
|
|
58
61
|
| **baseline** | Frozen known debt; does not make a wrong contract honest |
|
|
@@ -83,6 +86,7 @@ Examples:
|
|
|
83
86
|
| Keep Suggest on start → doctor | New-here primary is finish `start`, not a competing recommend/architect curriculum |
|
|
84
87
|
| Qualify edge-clean under design-weak | “None on checked edges … design residual remains. Not healthy finished.” |
|
|
85
88
|
| 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`. |
|
|
86
90
|
|
|
87
91
|
## Avoid
|
|
88
92
|
|
|
@@ -95,7 +99,12 @@ Examples:
|
|
|
95
99
|
| “modes you pick” for Suggest/Adapt/Enforce | Those are **status lights**, not settings |
|
|
96
100
|
| Skill-shopping lists as the default curriculum | Progressive disclosure: one door first |
|
|
97
101
|
| “Healthy / done” while design-weak | False done |
|
|
98
|
-
| “
|
|
102
|
+
| “Honesty clear” as “architecture finished” | Honesty clear only means residual honesty sensors are quiet; graph/mode debt is separate |
|
|
103
|
+
| “ArkRules prove business correctness” | They enforce *declared* structure/coverage evidence, not arbitrary logic or full semantic proof |
|
|
104
|
+
| “Structure enforced = Domain extraction done” | Structure sensors are **heuristics**; extraction is judgment (`/ark-fix` / pilot) |
|
|
105
|
+
| “Covered invariant = E2E business tests” | Coverage = symbol/test evidence for a named policy, not a runtime test runner |
|
|
106
|
+
| “Max arkRules packs = merge fails structure” | **Advisory ArkRules ≠ merge teeth.** Only `mode: "enforced"` can add teeth, and only after honest classification (FG-ARKRULES-ADVISORY-ONLY) |
|
|
107
|
+
| “Type-only volume means the gate is broken” | High type-only count is placement debt (behavior OK); group under plan A type-only, offer SharedTypes starter |
|
|
99
108
|
| Blurring import edges with invariants | Always label **`[Layer]`** vs **`[ArkRules]`** |
|
|
100
109
|
|
|
101
110
|
---
|
|
@@ -176,11 +176,15 @@ The release compatibility workflow packs the candidate first, then tests clean c
|
|
|
176
176
|
- **npm / pnpm / Yarn**;
|
|
177
177
|
- project TypeScript **5.9.3 / 6.0.3 / 7.0.2**.
|
|
178
178
|
|
|
179
|
-
That is 36 installed-artifact cells
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
179
|
+
That is **36** installed-artifact cells on the **full matrix** path (`push` to `main`, PR labels
|
|
180
|
+
`full-matrix` / `release`, or release-prep branch names such as `feat/4.1*`). Ordinary PRs run a
|
|
181
|
+
**slim** packed smoke: **one** cell (Node 20 + npm) that still exercises TS 5/6/7 in-process.
|
|
182
|
+
See [CONTRIBUTING.md — CI profiles](../CONTRIBUTING.md#ci-profiles-pr-slim-vs-full-matrix).
|
|
183
|
+
|
|
184
|
+
Each cell verifies that the project's `tsc` stays on the requested project compiler and that
|
|
185
|
+
ArkGate resolves its fallback as exact 6.0.3 when the project API is unusable. Reports record
|
|
186
|
+
`installMode` so the Yarn TS7 linker boundary cannot disappear behind a green job. All 36 cells
|
|
187
|
+
passed on source `228dd893` in CI run `29655190747`. Locally, the repository entry point is:
|
|
184
188
|
|
|
185
189
|
```bash
|
|
186
190
|
npm run test:ts-compat
|
package/docs/use.md
CHANGED
|
@@ -40,12 +40,14 @@ ArkGate is **not** a web framework, ORM, or app runtime. It is architecture enfo
|
|
|
40
40
|
|
|
41
41
|
### Two planes (you choose)
|
|
42
42
|
|
|
43
|
-
| Plane | Plain English | Config |
|
|
44
|
-
|
|
45
|
-
| **Layers** | Who may talk to whom
|
|
46
|
-
| **ArkRules** (optional) | Habits *inside* a layer
|
|
43
|
+
| Plane | Plain English | Config | Enforces |
|
|
44
|
+
|-------|---------------|--------|----------|
|
|
45
|
+
| **Layers** | Who may talk to whom | `layers[]` + `rules[]` | Import direction, purity, forbidden globals, capabilities, peer isolation |
|
|
46
|
+
| **ArkRules** (optional) | Habits *inside* a layer + named policies | `arkRules` + `arkrules/<Layer>.json` | Structure **heuristics** (module shape); invariant **catalog + coverage evidence** (not full business proof) |
|
|
47
47
|
|
|
48
|
-
Start always gives you **layers**. ArkRules templates may ship with start/init; they begin **advisory** until you promote them. Doctor
|
|
48
|
+
Start always gives you **layers**. ArkRules templates may ship with start/init; they begin **advisory** until you promote them. Doctor / HTML show `rulesUnderContract` (catalog, **not a score**). No `arkRules` map is fine — only Layers run.
|
|
49
|
+
|
|
50
|
+
**Do not confuse:** green Layers ≠ perfect design (Shape residual can remain). Covered invariants ≠ “the business always does the right thing” — they mean the named policy is declared and has symbol/test evidence.
|
|
49
51
|
|
|
50
52
|
---
|
|
51
53
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arkgate",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.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",
|
|
@@ -136,6 +136,7 @@
|
|
|
136
136
|
"check:package-files": "node scripts/verify-package-files.mjs",
|
|
137
137
|
"check:release-artifacts": "node scripts/verify-release-artifacts.mjs",
|
|
138
138
|
"test:release-artifacts": "vitest run tests/unit/scripts/verifyReleaseArtifacts.test.ts",
|
|
139
|
+
"test:field-dogfood-smoke": "node scripts/field-dogfood/smoke.mjs",
|
|
139
140
|
"audit:beta-exit": "node scripts/beta-exit-audit.mjs",
|
|
140
141
|
"clean": "rm -rf dist",
|
|
141
142
|
"release:npm": "node scripts/release-npm.mjs",
|
|
@@ -156,6 +157,7 @@
|
|
|
156
157
|
"overrides": {
|
|
157
158
|
"qs": "6.15.3",
|
|
158
159
|
"vite": "6.4.3",
|
|
160
|
+
"postcss": "8.5.23",
|
|
159
161
|
"tsup": {
|
|
160
162
|
"esbuild": "0.28.1"
|
|
161
163
|
},
|
package/server.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.pedroknigge/arkgate",
|
|
4
|
-
"description": "ArkGate
|
|
4
|
+
"description": "ArkGate — architecture co-pilot for AI TypeScript (write gate, CI, plan/loop)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/pedroknigge/arkgate",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "4.
|
|
9
|
+
"version": "4.1.0",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "arkgate",
|
|
14
|
-
"version": "4.
|
|
14
|
+
"version": "4.1.0",
|
|
15
15
|
"runtimeHint": "npx",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
@@ -86,6 +86,9 @@
|
|
|
86
86
|
"label": "UI-focused repository; backend lives elsewhere or is thin",
|
|
87
87
|
"preset": "layered",
|
|
88
88
|
"presetAlternatives": {
|
|
89
|
+
"vite-vercel-spa": {
|
|
90
|
+
"whenSignal": "viteVercelSpaLayout"
|
|
91
|
+
},
|
|
89
92
|
"feature-sliced": {
|
|
90
93
|
"whenSignal": "featureSlicedLayout"
|
|
91
94
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Optional SharedTypes layer starter (NEW-TYPEONLY-VOLUME). Copy the layer + allow rules into ark.config.json when type-only placement debt volume is high. Both application and presentation may import SharedTypes; SharedTypes must not import adapters or orchestration.",
|
|
3
|
+
"layer": {
|
|
4
|
+
"name": "SharedTypes",
|
|
5
|
+
"patterns": [
|
|
6
|
+
"src/types/**",
|
|
7
|
+
"src/shared/types/**",
|
|
8
|
+
"packages/shared/src/types/**",
|
|
9
|
+
"lib/types/**"
|
|
10
|
+
],
|
|
11
|
+
"intentPrefixes": ["Shared.Types."]
|
|
12
|
+
},
|
|
13
|
+
"suggestedRules": [
|
|
14
|
+
{ "from": "DomainModel", "to": "SharedTypes", "allowed": true },
|
|
15
|
+
{ "from": "ApplicationOrchestration", "to": "SharedTypes", "allowed": true },
|
|
16
|
+
{ "from": "PresentationAdapters", "to": "SharedTypes", "allowed": true },
|
|
17
|
+
{ "from": "PersistenceAdapters", "to": "SharedTypes", "allowed": true },
|
|
18
|
+
{ "from": "SharedTypes", "to": "DomainModel", "allowed": false },
|
|
19
|
+
{ "from": "SharedTypes", "to": "ApplicationOrchestration", "allowed": false },
|
|
20
|
+
{ "from": "SharedTypes", "to": "PresentationAdapters", "allowed": false },
|
|
21
|
+
{ "from": "SharedTypes", "to": "PersistenceAdapters", "allowed": false }
|
|
22
|
+
],
|
|
23
|
+
"guidance": [
|
|
24
|
+
"Type-only edges (`import type`) are placement debt — failsStrict:false; value edges still block merge.",
|
|
25
|
+
"Move pure type modules both sides need into SharedTypes (or an owning Domain surface).",
|
|
26
|
+
"Do not put runtime logic or I/O in SharedTypes.",
|
|
27
|
+
"Doctor violations.typeEdgePolicy and plan.typeOnlyGroup describe the same policy."
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -99,6 +99,8 @@ Ark protects the **boundary around** a framework, not its internals. Nest/DI pub
|
|
|
99
99
|
If the tree is `src/features` + `shared`/`lib` **without** FSD `entities`/`widgets`, prefer
|
|
100
100
|
`vertical-slice` (or pack `enthusiast-vertical-slice`) — do **not** force hexagonal.
|
|
101
101
|
If `src/contexts` or `src/bounded-contexts` exists, prefer `ddd-bounded-contexts`.
|
|
102
|
+
**Next.js:** `app/api/**` / `pages/api/**` (and route-group `app/(…)/api/**`) default to
|
|
103
|
+
**ApplicationOrchestration**, not Presentation — do not reclassify API shells as UI.
|
|
102
104
|
2. **Check + diagnose** — `summary.concentrated` / dominant edge → fix contract first, don’t freeze.
|
|
103
105
|
Cross-slice / cross-context `peerIsolation` hits are judgment: extract shared or events.
|
|
104
106
|
If one edge dominates residual debt: **STOP — do not continue this skill as complete.** **STOP — concentrated edge: invoke /ark-contract with source evidence** (do not freeze a wrong contract or grind N freezes).
|
|
@@ -45,8 +45,20 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
### Explain + ArkRules
|
|
48
|
-
- HTML/plain tour: section **Layers** and section **
|
|
49
|
-
|
|
48
|
+
- HTML/plain tour: section **Layers** and section **Rules under contract (ArkRules)** —
|
|
49
|
+
when `arkRules` is active the showcase lists **per-layer counts**, **structure sensors**
|
|
50
|
+
(id / sensor / mode), **uncovered** invariants (call them out), and a **covered sample**.
|
|
51
|
+
Inactive map stays a short opt-in note. Counts are never a score.
|
|
52
|
+
- Spoken tour: name 2–4 real invariant IDs and one structure sensor from this repo’s
|
|
53
|
+
`arkrules/*` (open the files — do not invent). Residual candidates → `--rules-inventory`.
|
|
54
|
+
- **Teach the product model (required when arkRules is active):**
|
|
55
|
+
- **[Layer]** = dependency direction / purity / capabilities.
|
|
56
|
+
- **[ArkRules] structure** = module-shape **heuristics** (orchestration-only, thin-adapter, …);
|
|
57
|
+
enforced is not proof of Domain extraction.
|
|
58
|
+
- **[ArkRules] invariants** = named business policies as **data + coverage evidence**
|
|
59
|
+
(symbol/test); not a runtime engine and not a substitute for behavior tests.
|
|
60
|
+
- Green edges + covered catalog ≠ elegant Shape (design-weak residual stays honest).
|
|
61
|
+
- Never merge Layers and ArkRules into one “architecture score.”
|
|
50
62
|
|
|
51
63
|
## Subagent fan-out (optional, host-dependent)
|
|
52
64
|
|
|
@@ -117,15 +129,21 @@ the same files or weaken the gate.
|
|
|
117
129
|
(SUGGEST / ADAPT / ENFORCE), and the plan's safe-to-auto vs decision counts.
|
|
118
130
|
|
|
119
131
|
The HTML report is the visual twin of this skill: architecture map, files per layer,
|
|
120
|
-
dependency direction, matrix, violations,
|
|
121
|
-
**Senior diagnostics** block (coupling
|
|
122
|
-
forensics, baseline taxonomy) for
|
|
132
|
+
dependency direction, matrix, violations, **ArkRules under contract** (when mapped),
|
|
133
|
+
enforcement points, Ark fitness score, and a **Senior diagnostics** block (coupling
|
|
134
|
+
fan-in/out, deny density, purity surface, pattern forensics, baseline taxonomy) for
|
|
135
|
+
tech leads.
|
|
123
136
|
|
|
124
137
|
When explaining the **plan**, name the four `mechanical-safe` remediation kinds only
|
|
125
138
|
(type-only move, pure-type file relocate, `import type` of pure-type modules,
|
|
126
139
|
`import-type-of-type-exports` for named type exports from mixed modules; W6 port-proof inject is judgment when proof holds) — everything
|
|
127
140
|
else is judgment/deferred and must not be auto-applied.
|
|
128
141
|
|
|
142
|
+
**Type-edge honesty:** type-only denied edges are **placement debt** (`typeOnly` +
|
|
143
|
+
`failsStrict: false`) — prefer SharedTypes / owning layer; they do not fail merge like value
|
|
144
|
+
edges. Doctor `productHonesty` and `violations.typeEdgePolicy` must not be sold as “all done”
|
|
145
|
+
when residual signals remain.
|
|
146
|
+
|
|
129
147
|
## Spoken / written explanation
|
|
130
148
|
|
|
131
149
|
1. **Load the real contract**: `ark.config.json`, `ark://manifest` if available, `AGENTS.md`.
|
|
@@ -276,6 +276,25 @@ in parallel. When `pilotLoop.queuedBets > 0`, those bets stay **queued**, not co
|
|
|
276
276
|
lines — never silent codemod of plan B. After the pilot lands, re-run doctor; success =
|
|
277
277
|
reduced evidence on pilot paths.
|
|
278
278
|
|
|
279
|
+
### Plan B one-pilot checklist (mandatory before any B apply)
|
|
280
|
+
|
|
281
|
+
Empty plan A + design-weak is **not** architecture finished. Plan B is judgment only.
|
|
282
|
+
|
|
283
|
+
| Step | Gate | Fail closed if… |
|
|
284
|
+
|------|------|-----------------|
|
|
285
|
+
| 1. Confirm residual | `designFitness.designWeak` **or** non-empty `patternBets` / `designSmells` | You would claim healthy finished because plan A is empty |
|
|
286
|
+
| 2. Pick **one** pilot | `pilotLoop.nextPilot` (preferred) **or** one ranked B bet with a path scope | Multi-pilot batch / “fix all smells this PR” |
|
|
287
|
+
| 3. Write extraction card | Pilot · Smell · Move · Do not · Success · **Kill-switch** · Next | Missing kill-switch or success signal |
|
|
288
|
+
| 4. User OK | Explicit approval before edit (or stay map-only) | Silent auto-apply of plan B |
|
|
289
|
+
| 5. Apply **only** that pilot | Via `/ark-autopilot` (apply B) or `/ark-fix` (one cluster) | Opening a second pilot before re-doctor |
|
|
290
|
+
| 6. Re-doctor | Success = reduced evidence on pilot paths; residual outside pilot may remain | Declaring whole-tree done from one pilot |
|
|
291
|
+
|
|
292
|
+
**Hard lines (never break):**
|
|
293
|
+
- `killSwitch` / kill-switch is **required** on every B card (stop condition if pilot does not reduce confusion).
|
|
294
|
+
- `multiPilotBatchForbidden` — never multi-batch Shape extractions.
|
|
295
|
+
- `autoApplyPlanBForbidden` / `neverMechanicalSafe: true` — never invent mechanical-safe for B.
|
|
296
|
+
- `healthyFinishedForbidden` while design-weak — empty plan A is baseline, not done.
|
|
297
|
+
|
|
279
298
|
```text
|
|
280
299
|
### Extraction card
|
|
281
300
|
Pilot: <one dir or feature — or pilotLoop.nextPilot.pilotTarget>
|
|
@@ -286,8 +305,9 @@ Do not:
|
|
|
286
305
|
- weaken ark.config.json
|
|
287
306
|
- auto-apply as mechanical-safe or invent new mechanical-safe kinds
|
|
288
307
|
- big-bang the monorepo
|
|
308
|
+
- open a second pilot before re-doctor
|
|
289
309
|
Success: <observable / falsifiable — re-doctor>
|
|
290
|
-
Kill-switch: <stop condition>
|
|
310
|
+
Kill-switch: <stop condition — e.g. if pilot does not clear smell evidence in 1 PR → stop / re-map>
|
|
291
311
|
Next: /ark-autopilot (apply with user ok) | /ark-fix (one cluster) | re-doctor
|
|
292
312
|
```
|
|
293
313
|
|
|
@@ -19,16 +19,27 @@ the two files on the violation edge.
|
|
|
19
19
|
|
|
20
20
|
When the fix is really a **Shape** extraction (I/O out of routes, god module split), write an
|
|
21
21
|
**extraction card** before editing — same template as `docs/brownfield-adoption.md`
|
|
22
|
-
§6 and explore §G. Fixed fields (never mechanical-safe, never silent B apply)
|
|
22
|
+
§6 and explore §G. Fixed fields (never mechanical-safe, never silent B apply).
|
|
23
|
+
|
|
24
|
+
### Plan B one-pilot checklist (when Shape residual, not a single edge fix)
|
|
25
|
+
|
|
26
|
+
Empty plan A + `designWeak` is **not** architecture finished. One pilot only:
|
|
27
|
+
|
|
28
|
+
1. **Confirm** doctor `designFitness.designWeak` / non-empty `patternBets` (or agent-detected smell).
|
|
29
|
+
2. **One pilot** — prefer `pilotLoop.nextPilot`; never multi-batch concurrent Shape extractions.
|
|
30
|
+
3. **Extraction card** with **Kill-switch** + falsifiable Success (required).
|
|
31
|
+
4. **User OK** before apply — `autoApplyPlanBForbidden` / never mechanical-safe.
|
|
32
|
+
5. **Edit only that pilot scope** — then `ark-check` / re-doctor; residual outside pilot may remain.
|
|
33
|
+
6. **Stop** if kill-switch fires; do not open pilot #2 in the same batch.
|
|
23
34
|
|
|
24
35
|
```text
|
|
25
36
|
### Extraction card
|
|
26
|
-
Pilot: <one directory or feature path>
|
|
37
|
+
Pilot: <one directory or feature path — or pilotLoop.nextPilot.pilotTarget>
|
|
27
38
|
Smell: <doctor designSmells id if present>
|
|
28
39
|
Move: <verbatim relocate / split>
|
|
29
|
-
Do not: rewrite queries; weaken ark.config; invent mechanical-safe kinds; big-bang
|
|
30
|
-
Success: <falsifiable>
|
|
31
|
-
Kill-switch: <stop condition>
|
|
40
|
+
Do not: rewrite queries; weaken ark.config; invent mechanical-safe kinds; big-bang; multi-pilot batch
|
|
41
|
+
Success: <falsifiable — re-doctor on pilot paths>
|
|
42
|
+
Kill-switch: <stop condition — required>
|
|
32
43
|
Next: re-run ark-check; shrink baseline if applicable
|
|
33
44
|
```
|
|
34
45
|
|
|
@@ -43,7 +43,10 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
|
|
|
43
43
|
|
|
44
44
|
## Safety contract
|
|
45
45
|
|
|
46
|
-
-
|
|
46
|
+
- Always invoke the **project-local** CLI (`npx arkgate` /
|
|
47
|
+
`node node_modules/arkgate/bin/ark.mjs`). Bare PATH `ark` / `arkgate` is unsafe
|
|
48
|
+
when a global 2.x install shadows the project (mutative legacy upgrade).
|
|
49
|
+
- `ark upgrade` (managed era) is read-only. It reports the selected profile and hosts, every
|
|
47
50
|
managed asset, its content state, and the exact next command.
|
|
48
51
|
- The first `ark upgrade --apply` updates the dependency and lockfile, then runs
|
|
49
52
|
the newly installed CLI to produce another read-only preview. It does **not**
|
|
@@ -72,16 +75,54 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
|
|
|
72
75
|
|
|
73
76
|
## Procedure
|
|
74
77
|
|
|
75
|
-
1. **
|
|
78
|
+
1. **Resolve the project CLI (mandatory before any upgrade command).** Prefer the
|
|
79
|
+
**project-local** binary — never bare `ark` / `arkgate` from PATH unless you
|
|
80
|
+
prove it is this project's install.
|
|
81
|
+
|
|
82
|
+
Resolution order:
|
|
83
|
+
|
|
84
|
+
1. `node node_modules/arkgate/bin/ark.mjs` from the repository root (both `arkgate`
|
|
85
|
+
and `ark` package bins map to this file).
|
|
86
|
+
2. Package-manager exec from the project: `npx arkgate`, `pnpm exec arkgate`,
|
|
87
|
+
`yarn arkgate`, etc.
|
|
88
|
+
|
|
89
|
+
**Do not** use bare `ark` / `arkgate` from PATH unless `which ark` (or the
|
|
90
|
+
resolved realpath) is under this project's `node_modules/arkgate`, or the
|
|
91
|
+
binary reports the **same** version as `node_modules/arkgate/package.json` and
|
|
92
|
+
supports managed upgrade.
|
|
93
|
+
|
|
94
|
+
**Capability probe (abort if missing):** run
|
|
95
|
+
`node node_modules/arkgate/bin/ark.mjs upgrade --help` (or the resolved local
|
|
96
|
+
equivalent) and require a **managed upgrade** surface — help text must mention
|
|
97
|
+
`--plan-digest` (and read-only `upgrade --json` preview). If the only available
|
|
98
|
+
CLI is old (global Homebrew / npm global 2.x, or any binary whose help lacks
|
|
99
|
+
`--plan-digest`), **stop**: skill incomplete; do **not** preview or apply.
|
|
100
|
+
Global 2.x `ark upgrade` is mutative and can rewrite managed skills, forcing a
|
|
101
|
+
later `--accept-conflicts` recovery.
|
|
102
|
+
|
|
103
|
+
**Recovery (preferred → optional):**
|
|
104
|
+
|
|
105
|
+
- Preferred: package-manager runner from project / `--root`
|
|
106
|
+
(`npx arkgate upgrade …` / `pnpm exec arkgate upgrade …` / `yarn arkgate upgrade …`).
|
|
107
|
+
This works when arkgate is **hoisted** and a nested package has no shallow
|
|
108
|
+
`node_modules/arkgate`.
|
|
109
|
+
- Secondary: `node node_modules/arkgate/bin/ark.mjs upgrade …` from the
|
|
110
|
+
**workspace install root** (not a nested package lacking a local install).
|
|
111
|
+
- Optional: refresh a global install with `npm i -g arkgate@latest` only if the
|
|
112
|
+
user wants a global binary; still prefer project-local for this procedure.
|
|
113
|
+
|
|
114
|
+
Record the resolved CLI path/version, read
|
|
76
115
|
`node_modules/arkgate/package.json`, query `npm view arkgate version`, identify
|
|
77
116
|
the repository package manager, and open the intervening entries in the
|
|
78
117
|
shipped `CHANGELOG.md` (fall back to registry or release notes and name that
|
|
79
118
|
source). Do not infer “latest” from `node_modules` alone.
|
|
80
119
|
|
|
81
|
-
2. **Preview managed content.**
|
|
120
|
+
2. **Preview managed content.** Using the **project-local** CLI from step 1
|
|
121
|
+
(never a bare PATH `ark` that failed the probe), run:
|
|
82
122
|
|
|
83
123
|
```bash
|
|
84
|
-
|
|
124
|
+
npx arkgate upgrade --json
|
|
125
|
+
# or: node node_modules/arkgate/bin/ark.mjs upgrade --json
|
|
85
126
|
```
|
|
86
127
|
|
|
87
128
|
Pass `--root <path>` and `--tools <active-host>` when selection would otherwise
|
|
@@ -89,10 +130,10 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
|
|
|
89
130
|
that customized files remain non-applying and that any deletion/conflict is
|
|
90
131
|
blocked.
|
|
91
132
|
|
|
92
|
-
3. **Update and re-preview.** If the registry is newer, run:
|
|
133
|
+
3. **Update and re-preview.** If the registry is newer, run (project-local CLI):
|
|
93
134
|
|
|
94
135
|
```bash
|
|
95
|
-
|
|
136
|
+
npx arkgate upgrade --apply
|
|
96
137
|
```
|
|
97
138
|
|
|
98
139
|
This updates through the detected package manager and hands control to the new
|
|
@@ -105,20 +146,25 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
|
|
|
105
146
|
off, and prove `pnpm install --frozen-lockfile` succeeds.
|
|
106
147
|
|
|
107
148
|
4. **Apply only the reviewed candidate.** When there are no blocked assets, run
|
|
108
|
-
the preview's exact `nextCommand
|
|
149
|
+
the preview's **exact** `nextCommand` as emitted (JSON field / human “Apply the
|
|
150
|
+
exact preview with: …”). That command is already **project-local**
|
|
151
|
+
(`npx arkgate` / `pnpm exec arkgate` / `yarn arkgate` — never bare PATH `ark`).
|
|
152
|
+
Do **not** rewrite it to bare `ark upgrade`; pasting through a global 2.x PATH
|
|
153
|
+
reintroduces the mutative footgun. Shape:
|
|
109
154
|
|
|
110
155
|
```bash
|
|
111
|
-
|
|
156
|
+
npx arkgate upgrade --apply --no-install --plan-digest <preview-digest>
|
|
112
157
|
```
|
|
113
158
|
|
|
114
159
|
If recorded deletion/conflict recovery is desired, ask first and then add
|
|
115
160
|
`--accept-conflicts`. Never add it merely to make the run green. Run a second
|
|
116
161
|
preview and require `summary.changed: 0`.
|
|
117
162
|
|
|
118
|
-
5. **Verify enforcement and architecture.** Run
|
|
163
|
+
5. **Verify enforcement and architecture.** Run
|
|
164
|
+
`npx arkgate-check --doctor --json` (or the project-local `ark-check`) and
|
|
119
165
|
the same fail-closed architecture command used by managed apply (normally
|
|
120
|
-
`
|
|
121
|
-
`completeness: "complete"` and `ok: true`. Treat provider-unavailable CI
|
|
166
|
+
`npx arkgate-check --root . --config ark.config.json --strict-merge --json`).
|
|
167
|
+
Require `completeness: "complete"` and `ok: true`. Treat provider-unavailable CI
|
|
122
168
|
required-check evidence as `unverified`, never as proof that merges are
|
|
123
169
|
blocked. If new violations appear, hand off to `/ark-fix` for a small set or
|
|
124
170
|
`/ark-loop` / `/ark-autopilot` for residual debt; do not regenerate a baseline
|