arkgate 3.0.0 → 3.0.1

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.
@@ -25,6 +25,12 @@ import {
25
25
  violationEdge,
26
26
  } from './violations.mjs';
27
27
  import { buildUnclassifiedSuggestions } from './suggestions.mjs';
28
+ import {
29
+ detectDesignSmells,
30
+ buildPatternBetsFromSmells,
31
+ summarizeDesignFitness,
32
+ isDesignWeak,
33
+ } from './design-smells.mjs';
28
34
 
29
35
  const color = {
30
36
  green: (s) => `\x1b[32m${s}\x1b[0m`,
@@ -142,7 +148,25 @@ export function runCoverage(root, config, files, rules, asJson) {
142
148
  // Co-pilot Phase F — turn active violations into a classified, ordered remediation PLAN with an
143
149
  // embedded GOAL. This is the `plan` primitive the future apply-loop (Phase H, `loop`) consumes
144
150
  // and the autopilot (Phase I) drives toward the `goal`. Read-only: it changes no files.
145
- export function buildRemediationPlan(root, activeViolations, governedPercent = null, totalFiles = null) {
151
+ /**
152
+ * @param {string} root
153
+ * @param {object[]} activeViolations
154
+ * @param {number|null} [governedPercent]
155
+ * @param {number|null} [totalFiles]
156
+ * @param {object} [options]
157
+ * @param {object[]} [options.designSmells]
158
+ * @param {object[]} [options.patternBets]
159
+ * @param {object} [options.config]
160
+ * @param {string[]} [options.files]
161
+ * @param {object} [options.coverage]
162
+ */
163
+ export function buildRemediationPlan(
164
+ root,
165
+ activeViolations,
166
+ governedPercent = null,
167
+ totalFiles = null,
168
+ options = {}
169
+ ) {
146
170
  // A plan with 0 violations but ~0% governed (or ZERO files in scope) is a FALSE green:
147
171
  // nothing is actually being checked. Treat as "not done — classify / fix include first."
148
172
  const governedLow = governedPercent != null && governedPercent < 50;
@@ -177,20 +201,54 @@ export function buildRemediationPlan(root, activeViolations, governedPercent = n
177
201
  judgment: countOf('judgment'),
178
202
  deferred: countOf('deferred'),
179
203
  };
204
+
205
+ // Plan B (pattern bets) — never mechanical-safe; additive within major (P03).
206
+ let designSmells = options.designSmells;
207
+ if (!designSmells && options.config && options.files) {
208
+ designSmells = detectDesignSmells(
209
+ root,
210
+ options.config,
211
+ options.files,
212
+ options.coverage ?? null
213
+ );
214
+ }
215
+ designSmells = designSmells ?? [];
216
+ const patternBets =
217
+ options.patternBets ?? buildPatternBetsFromSmells(designSmells);
218
+ const edgesMet = activeViolations.length === 0 && !notHonestlyEnforced;
219
+ const designWeak = isDesignWeak(designSmells, {
220
+ activeViolations: activeViolations.length,
221
+ governedPercent,
222
+ totalFiles,
223
+ });
224
+
225
+ let statement =
226
+ activeViolations.length > 0
227
+ ? `Resolve ${activeViolations.length} architecture violation(s) without weakening the contract.`
228
+ : emptyScope
229
+ ? 'No source files matched the contract include paths — this "clean" result checks nothing. Fix include/layers (monorepo → apps/packages, or /ark-adopt) so Ark has real code to govern.'
230
+ : governedLow
231
+ ? `No violations — but Ark governs only ${governedPercent}% of your code, so this "clean" result checks almost nothing. Classify the rest (ark-check --coverage, then /ark-adopt) so it's actually enforced.`
232
+ : 'No active violations — the architecture already meets its contract.';
233
+ if (designWeak) {
234
+ statement =
235
+ 'No active edge violations — contract edges are clean, but design smells remain (ENFORCE · design-weak). Shape residual is plan B only; not healthy finished.';
236
+ }
237
+
180
238
  return {
181
239
  version: '1',
182
240
  goal: {
183
- statement:
184
- activeViolations.length > 0
185
- ? `Resolve ${activeViolations.length} architecture violation(s) without weakening the contract.`
186
- : emptyScope
187
- ? 'No source files matched the contract include paths — this "clean" result checks nothing. Fix include/layers (monorepo → apps/packages, or /ark-adopt) so Ark has real code to govern.'
188
- : governedLow
189
- ? `No violations — but Ark governs only ${governedPercent}% of your code, so this "clean" result checks almost nothing. Classify the rest (ark-check --coverage, then /ark-adopt) so it's actually enforced.`
190
- : 'No active violations — the architecture already meets its contract.',
191
- // The loop's termination signal (Phase H): nothing left to remediate AND the contract
192
- // actually governs real code. Empty scope or low coverage is not "met".
193
- met: activeViolations.length === 0 && !notHonestlyEnforced,
241
+ statement,
242
+ // Edge remediation termination (Phase H). Design-weak does NOT flip met false
243
+ // (would break loop semantics) it is reported separately for honesty.
244
+ met: edgesMet,
245
+ designWeak,
246
+ ...(designWeak
247
+ ? {
248
+ designWeakLabel:
249
+ 'ENFORCE · design-weak use patternBets / dual-plan B; never auto-apply as mechanical-safe',
250
+ }
251
+ : {}),
194
252
  ...(governedPercent != null ? { governedPercent } : {}),
195
253
  ...(totalFiles != null ? { totalFiles } : {}),
196
254
  ...(emptyScope ? { emptyScope: true } : {}),
@@ -198,17 +256,38 @@ export function buildRemediationPlan(root, activeViolations, governedPercent = n
198
256
  autoApplicable: counts.mechanicalSafe,
199
257
  needsDecision: counts.judgment,
200
258
  deferred: counts.deferred,
259
+ patternBetCount: patternBets.length,
201
260
  },
202
261
  counts,
203
262
  steps,
263
+ // Additive: pattern evolution bets derived from design smells (never auto).
264
+ patternBets,
265
+ designSmells,
204
266
  };
205
267
  }
206
268
 
207
269
  // `--plan`: print the classified remediation plan. Dual-focus output — a one-line headline
208
270
  // anyone can read, then the per-step detail a developer acts on. Read-only.
209
- export function runPlan(root, activeViolations, asJson, governedPercent = null, totalFiles = null) {
210
- const plan = buildRemediationPlan(root, activeViolations, governedPercent, totalFiles);
271
+ /**
272
+ * @param {object} [options] optional { config, files, coverage, designSmells, patternBets }
273
+ */
274
+ export function runPlan(
275
+ root,
276
+ activeViolations,
277
+ asJson,
278
+ governedPercent = null,
279
+ totalFiles = null,
280
+ options = {}
281
+ ) {
282
+ const plan = buildRemediationPlan(
283
+ root,
284
+ activeViolations,
285
+ governedPercent,
286
+ totalFiles,
287
+ options
288
+ );
211
289
  // Honesty: a zero-violation plan with almost nothing governed is NOT "ok".
290
+ // design-weak still ok:true for edge goal.met, but JSON carries designWeak + patternBets.
212
291
  const planOk = plan.goal.met === true;
213
292
  if (asJson) {
214
293
  console.log(JSON.stringify({ ok: planOk, plan }, null, 2));
@@ -217,6 +296,13 @@ export function runPlan(root, activeViolations, asJson, governedPercent = null,
217
296
  console.log(color.bold(`Ark plan — ${path.basename(path.resolve(root)) || '.'}`));
218
297
  console.log('');
219
298
  console.log(plan.goal.statement);
299
+ if (plan.goal.designWeak) {
300
+ console.log(
301
+ color.yellow(
302
+ ` ENFORCE · design-weak — ${plan.patternBets?.length ?? 0} pattern bet(s) (never auto-apply)`
303
+ )
304
+ );
305
+ }
220
306
  if (governedPercent != null) {
221
307
  const pctLabel =
222
308
  governedPercent < 50
@@ -224,6 +310,14 @@ export function runPlan(root, activeViolations, asJson, governedPercent = null,
224
310
  : color.dim(`Governed: ${governedPercent}% of in-scope files`);
225
311
  console.log(pctLabel);
226
312
  }
313
+ if (plan.patternBets?.length && activeViolations.length === 0) {
314
+ console.log('');
315
+ console.log(color.bold('Pattern bets (B) — judgment only'));
316
+ for (const bet of plan.patternBets.slice(0, 5)) {
317
+ console.log(` [decide] ${bet.smellId} ${color.dim(bet.pilot)}`);
318
+ console.log(color.dim(` success: ${bet.successSignal}`));
319
+ }
320
+ }
227
321
  if (activeViolations.length === 0) return plan;
228
322
  console.log('');
229
323
  console.log(
@@ -245,7 +339,7 @@ export function runPlan(root, activeViolations, asJson, governedPercent = null,
245
339
  console.log('');
246
340
  console.log(
247
341
  color.dim(
248
- 'Plan only — no files changed. "auto" = an agent can safely apply it; "decide" = your call.'
342
+ 'Plan only — no files changed. "auto" = an agent can safely apply it; "decide" = your call. patternBets are never auto.'
249
343
  )
250
344
  );
251
345
  return plan;
@@ -283,6 +377,12 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
283
377
  const activeCount = violations.length - suppressed;
284
378
  const missingSkills = skillGaps.reduce((sum, gap) => sum + gap.missing, 0);
285
379
  const staleSkills = skillGaps.reduce((sum, gap) => sum + gap.stale, 0);
380
+ const designSmells = detectDesignSmells(root, config, files, cov);
381
+ const designFitness = summarizeDesignFitness(designSmells, {
382
+ activeViolations: activeCount,
383
+ governedPercent: cov.governed.percent,
384
+ totalFiles: cov.governed.totalFiles,
385
+ });
286
386
 
287
387
  if (asJson) {
288
388
  console.log(
@@ -304,6 +404,9 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
304
404
  return p ? p.files / total : null;
305
405
  })(),
306
406
  }),
407
+ // Path-correct ENFORCE can still be design-weak (P02).
408
+ designFitness,
409
+ designSmells,
307
410
  governed: cov.governed,
308
411
  emptyLayers: cov.emptyLayers,
309
412
  layersWithoutRules: cov.layersWithoutRules,
@@ -412,7 +515,18 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
412
515
  enforce:
413
516
  'Guard — contract coverage is honest and checked edges are clean. You do not pick this mode; you arrived here. Next: keep the host-appropriate write path and CI check on; only NEW violations should fail.',
414
517
  };
415
- line(modeMark, `${mode.toUpperCase()} — ${modeHelp[mode]}`);
518
+ const modeTitle =
519
+ mode === 'enforce' && designFitness.designWeak
520
+ ? 'ENFORCE · design-weak'
521
+ : mode.toUpperCase();
522
+ line(
523
+ modeMark,
524
+ `${modeTitle} — ${
525
+ designFitness.designWeak
526
+ ? 'Guard on edges is honest, but design smells remain (Shape residual). You do not pick this mode. Next: /ark-explore dual-plan B or /ark-autopilot for pattern bets — never treat empty plan A as healthy finished.'
527
+ : modeHelp[mode]
528
+ }`
529
+ );
416
530
  if (emptyScope) {
417
531
  line(
418
532
  bad,
@@ -420,6 +534,25 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
420
534
  );
421
535
  }
422
536
 
537
+ console.log('');
538
+ console.log(color.bold('Design fitness'));
539
+ if (designSmells.length === 0) {
540
+ line(ok, designFitness.label);
541
+ } else {
542
+ line(designFitness.designWeak ? warn : warn, designFitness.label);
543
+ for (const smell of designSmells.slice(0, 5)) {
544
+ line(' ', color.dim(`[${smell.id}] ${smell.message}`));
545
+ if (smell.evidence?.length) {
546
+ line(' ', color.dim(`evidence: ${smell.evidence.slice(0, 4).join(', ')}`));
547
+ }
548
+ }
549
+ if (designFitness.designWeak) {
550
+ actions.push(
551
+ 'shape residual: /ark-explore (shape-focus) or /ark-autopilot dual-plan B — pattern bets are never mechanical-safe'
552
+ );
553
+ }
554
+ }
555
+
423
556
  console.log('');
424
557
  console.log(color.bold('Coverage'));
425
558
  const govMark =
package/dist/index.cjs CHANGED
@@ -50,7 +50,7 @@ __export(gate_exports, {
50
50
  module.exports = __toCommonJS(gate_exports);
51
51
 
52
52
  // src/version.ts
53
- var version = "3.0.0";
53
+ var version = "3.0.1";
54
54
 
55
55
  // src/domain/adapterContract.ts
56
56
  var ARK_ANALYSIS_RESULT_SCHEMA_VERSION = "1.0";
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@ import { a as ArkConfigRule, b as ArkConfigLayer, A as ArkConfig, c as ArkConfig
2
2
  export { d as ARK_CONFIG_SCHEMA, e as ARK_CONFIG_SCHEMA_VERSION, l as loadArkConfigContract, p as parseArkConfigJson } from './configContract-BxSIwVRo.cjs';
3
3
 
4
4
  /** ArkGate library version — single source of truth. */
5
- declare const version = "3.0.0";
5
+ declare const version = "3.0.1";
6
6
 
7
7
  /** Versioned public result contract shared by every ArkGate enforcement adapter. */
8
8
  declare const ARK_ANALYSIS_RESULT_SCHEMA_VERSION: "1.0";
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { a as ArkConfigRule, b as ArkConfigLayer, A as ArkConfig, c as ArkConfig
2
2
  export { d as ARK_CONFIG_SCHEMA, e as ARK_CONFIG_SCHEMA_VERSION, l as loadArkConfigContract, p as parseArkConfigJson } from './configContract-BxSIwVRo.js';
3
3
 
4
4
  /** ArkGate library version — single source of truth. */
5
- declare const version = "3.0.0";
5
+ declare const version = "3.0.1";
6
6
 
7
7
  /** Versioned public result contract shared by every ArkGate enforcement adapter. */
8
8
  declare const ARK_ANALYSIS_RESULT_SCHEMA_VERSION: "1.0";
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var version = "3.0.0";
2
+ var version = "3.0.1";
3
3
 
4
4
  // src/domain/adapterContract.ts
5
5
  var ARK_ANALYSIS_RESULT_SCHEMA_VERSION = "1.0";
@@ -75,6 +75,12 @@ To remove a compact host integration, preview `ark start --remove-host <host>` a
75
75
  only after review. Ark removes only its exact compact artifacts, leaves customized files untouched
76
76
  as unresolved decisions, and restores the integration with `ark start --tools <host> --apply`.
77
77
 
78
+ **Skill roles (avoid overlap):** `/ark-explore` = map + dual-plan **seed** + Shape residual
79
+ (no apply). `/ark-coverage` = Ark **fitness** only (governed/gates). `/ark-think` = one decision
80
+ (2–3 options). `/ark-adopt` = brownfield Align/Stabilize + seed Shape B. `/ark-autopilot` =
81
+ explore then apply A + propose/apply-with-ok B. `/ark-loop` = plan A only. Empty plan A is not
82
+ “architecture healthy” if design-weak residual remains.
83
+
78
84
  **Full-skill agent co-pilot:** after explicitly installing the `/ark-*` pack, use
79
85
  `/ark-autopilot` (explore-first, dual plan A remediation + B pattern bets). Recon without
80
86
  applying: `/ark-explore`. The default compact router uses MCP/CLI directly. Never treat empty
@@ -86,10 +86,61 @@ violations — the ratchet only moves toward zero.
86
86
  `/ark-fix` resolves each cluster at the root cause; fixing a frozen violation shrinks the
87
87
  baseline permanently. Re-freeze lower with `--update-baseline` as you go.
88
88
 
89
+ ## 6. Shape residual — extraction cards (judgment assist, P05)
90
+
91
+ When edges are green (`ark-check --plan` has empty `steps[]`) but doctor reports
92
+ **ENFORCE · design-weak** (`designSmells` / `patternBets`), you are in **Shape** work. Plan A
93
+ is done; plan **B** is not auto-applicable.
94
+
95
+ Use one **extraction card** per pilot (I/O relocate, god-module split, domain-out-of-UI).
96
+ Agents and humans fill the same fields — never invent a codemod engine or silent apply:
97
+
98
+ ```text
99
+ ### Extraction card
100
+ Pilot: <one directory or feature path>
101
+ Smell: <doctor designSmells[].id or agent-detected id>
102
+ Move: <what moves, e.g. query bytes verbatim → OrderRepository adapter>
103
+ Do not:
104
+ - rewrite queries / touch schema / migrations
105
+ - weaken ark.config.json to silence the smell
106
+ - auto-apply as mechanical-safe or invent new mechanical-safe kinds
107
+ - big-bang the whole monorepo
108
+ Success: <falsifiable signal, e.g. 0 routes import @prisma/client>
109
+ Kill-switch: <when to stop, e.g. if 2 PRs still confuse ownership → stop layer add>
110
+ Next: /ark-fix (one cluster) | /ark-autopilot (user ok on B) | /ark-explore shape-focus
111
+ ```
112
+
113
+ CLI sensors:
114
+
115
+ ```bash
116
+ ark-check --doctor --json # designFitness.designWeak + designSmells[].evidence
117
+ ark-check --plan --json # patternBets[] with neverMechanicalSafe: true
118
+ ```
119
+
120
+ Fixture for CI honesty: `tests/fixtures/design-weak-enforce/` (empty plan A + non-empty B).
121
+
122
+ ### Optional: durable Shape plan (multi-PR)
123
+
124
+ CLI `patternBets` and extraction cards are enough for a single session. If residual spans
125
+ **multiple PRs or agents**, optionally persist one human-readable plan under the repo
126
+ (e.g. `docs/plans/shape-<pilot>/README.md` or any team path) with:
127
+
128
+ | Field | Source |
129
+ |-------|--------|
130
+ | Phase | Align / Stabilize / **Shape** |
131
+ | Golden vs legacy patterns | explore concurrent-patterns table |
132
+ | Smell ids / patternBets | `ark-check --doctor --json` / `--plan --json` |
133
+ | Extraction cards | §6 template above |
134
+ | Status of pilot | e.g. dual path (legacy + new) → real (only golden) when smells clear |
135
+
136
+ This is **optional narrative**, not a gate. Ark does not require a docs skill or a fixed
137
+ folder layout. Prefer one authority plan; promote or archive it when the pilot is real.
138
+
89
139
  ## What Ark does NOT do here
90
140
 
91
141
  Ark reorganizes and governs code — it never touches your data model. Migrating raw SQL to a
92
142
  repository moves the same query to another file; the schema, migrations, and the database are
93
143
  untouched. And the burn-down itself is the team's work (or a codemod, or an agent loop) — Ark
94
144
  diagnoses, orders it, and gives you the pattern; it doesn't auto-run hundreds of edits against
95
- your restricted data layer.
145
+ your restricted data layer. **Extraction cards are judgment assists only** — no general codemod
146
+ and no silent auto-apply of plan B.
@@ -15,6 +15,8 @@ This document is the consumer contract for **what is stable** vs **what is exper
15
15
  | Surface | How you use it | Stability notes |
16
16
  |---------|----------------|-----------------|
17
17
  | **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. |
18
+ | **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`. Each smell has `evidence[]` paths and `fix`. Does **not** fail the gate by itself. |
19
+ | **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. |
18
20
  | **MCP tools** | `arkgate-mcp` / `ark://…` resources | Tool names and primary argument shapes are stable within a major. |
19
21
  | **`ark.config.json`** | Layer globs, rules, include/exclude, forbiddenGlobals, intent prefixes, `peerIsolation`, `dynamicImportAllowlist`, `safety` thresholds | Versioned by `schemaVersion`; unknown fields fail closed and migrations preserve the previous supported major. |
20
22
  | **`arkgate/schema/analysis-result`** | Public CLI/MCP/hook diagnostic envelope (`schemaVersion`, `valid`, `diagnostics`) | Versioned JSON Schema; committed v1 compatibility fixture protects rule, severity, location, and evidence fields. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkgate",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "ArkGate — architecture co-pilot for AI TypeScript (write gate, CI gate, plan/loop)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/pedroknigge/arkgate",
7
7
  "source": "github"
8
8
  },
9
- "version": "3.0.0",
9
+ "version": "3.0.1",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "arkgate",
14
- "version": "3.0.0",
14
+ "version": "3.0.1",
15
15
  "runtimeHint": "npx",
16
16
  "transport": {
17
17
  "type": "stdio"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ark-adopt
3
- description: Brownfield onboarding — exploratory match of contract to real product code, classify ungoverned dirs, mine business rules into the manifest, freeze only real debt. Deep source analysis required.
3
+ description: Brownfield onboarding — match contract to real product code, classify ungoverned dirs, mine business rules, freeze only real debt, seed Shape dual-plan B for spaghetti residual. Deep source analysis required.
4
4
  ---
5
5
 
6
6
  # /ark-adopt — Bring Ark into an existing codebase
@@ -8,6 +8,18 @@ description: Brownfield onboarding — exploratory match of contract to real pro
8
8
  Goal: contract reflects **product reality**, most code governed, only genuine debt frozen
9
9
  with a burn-down. A green check over a wrong contract is a **false green**.
10
10
 
11
+ **Adopt is Align + Stabilize, then seed Shape.** Freezing debt without a pattern plan leaves
12
+ spaghetti “ENFORCE · design-weak”. Always end with dual-plan **B** seeds (or handoff explore)
13
+ when design smells remain after the contract is honest.
14
+
15
+ ## When / not when
16
+
17
+ | Use `/ark-adopt` when… | Do **not** use it when… |
18
+ |------------------------|-------------------------|
19
+ | Existing messy repo; contract ≠ folders | Empty greenfield shape → `/ark-architect` |
20
+ | False-green / concentrated edge needs contract truth | Map-only without writing config/baseline → `/ark-explore` |
21
+ | Mine loose business rules into Domain / intents | Single violation fix → `/ark-fix` |
22
+ | Freeze **real** debt after contract is honest | Grind plan A only → `/ark-loop`; full apply loop → `/ark-autopilot` |
11
23
 
12
24
  ## Dual engine (mandatory)
13
25
 
@@ -78,22 +90,33 @@ Ark protects the **boundary around** a framework, not its internals. Nest/DI pub
78
90
  - Deliver section **“Así te lo re-soluciono en el manifiesto”** with before/after contract snippets.
79
91
  5. **Freeze only real debt** — `--update-baseline` (zero debt → **no empty baseline file** left behind).
80
92
  6. **Gates + skills** — `--install-agent-gates` (CI monorepo-aware when `frontend/package.json` exists).
81
- 7. **Ratchet + opportunity plan** ranked residual edges + **explore-style bets** (what to improve next week).
93
+ 7. **Ratchet + Shape seed (mandatory exploratory close)** after freeze/gates:
94
+ - Name phase: **Align** (contract honesty) → **Stabilize** (baseline real) → **Shape** (golden pattern).
95
+ - If plan A is empty but the tree still shows concurrent patterns, god modules, facade SQL,
96
+ domain logic in UI, or semantic false-green: emit **dual-plan B** (3–5 bets) with pilot,
97
+ success signal, kill-switch, and extraction cards for I/O moves — same bar as `/ark-explore` §G.
98
+ - Do **not** claim “adopt complete / healthy” solely because the check is green.
99
+ - Prefer handoff `/ark-autopilot` for B execution with user ok, or `/ark-explore` shape-focus
100
+ if the user only wanted a plan.
82
101
 
83
102
  ## Operating modes
84
103
 
85
104
  Explain modes as **detected stages** (Setup / Align / Guard), not user settings.
105
+ **Guard on the contract ≠ Shape done.** Say `ENFORCE · design-weak` when B residual remains.
86
106
 
87
107
  ## Verify
88
108
 
89
109
  `ark-check --root . --config ark.config.json --strict-config` (+ baseline only if non-empty file retained).
90
- Report: governed% before/after, files written, frozen count, false positives avoided, manifest/intent proposals applied or deferred, **top opportunities still open**.
110
+ Report: governed% before/after, files written, frozen count, false positives avoided, manifest/intent
111
+ proposals applied or deferred, **phase**, **top Shape / design-weak opportunities still open**
112
+ (with success signals).
91
113
 
92
114
  ## Never
93
115
 
94
116
  - Freeze false positives to get green.
95
117
  - Force runtime kernel over existing Nest/DI.
96
118
  - Claim Enforce while governed% is low, cores empty with I/O in Application, or core bags ungoverned.
119
+ - End adopt with only “baseline written” when design-weak residual is visible in files you opened.
97
120
 
98
121
  ## Completion contract (skill incomplete if missing)
99
122
 
@@ -5,6 +5,13 @@ description: Choose the application shape, adopt phase-1 layers, scaffold direct
5
5
 
6
6
  # /ark-architect — Choose your application shape and adopt Ark
7
7
 
8
+ ## When / not when
9
+
10
+ | Use `/ark-architect` when… | Do **not** use it when… |
11
+ |----------------------------|-------------------------|
12
+ | Greenfield / thin tree; pick shape + phase-1 layers | Existing spaghetti brownfield → `/ark-adopt` (+ `/ark-explore` first if map missing) |
13
+ | Enthusiast before heavy codegen | Enforcement residual on mature tree → `/ark-autopilot` |
14
+
8
15
  The user is building something new or early in Ark adoption. They may not know
9
16
  layered architecture jargon. Your job: translate **what they want to build**
10
17
  (application shape, not framework name) into an Ark preset, a phase-1 layer plan,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ark-autopilot
3
- description: End-to-end architecture co-pilot — decision-grade explore first, dual plan (remediation + pattern improvements), mechanical-safe fixes, judgment design. CLI is a sensor; you read and remediate files.
3
+ description: End-to-end co-pilot — explore first, dual plan A remediation + B pattern/Shape bets, mechanical-safe fixes, judgment design. Empty plan A is not healthy if design-weak. CLI is a sensor; you read and remediate files.
4
4
  ---
5
5
 
6
6
  # /ark-autopilot — Get to a sound architecture, end to end
@@ -11,15 +11,23 @@ execute **judgment** fixes you design from reading source (still validate with a
11
11
  never weaken the gate).
12
12
 
13
13
  **Not a plan grinder.** Empty `--plan` does **not** mean “architecture is healthy” without
14
- the explore pass and dual-plan section B (pattern bets).
14
+ the explore pass and dual-plan section B (pattern / Shape bets).
15
15
 
16
+ ## When / not when
17
+
18
+ | Use `/ark-autopilot` when… | Do **not** use it when… |
19
+ |----------------------------|-------------------------|
20
+ | “Make architecture sound” end-to-end | Map only, no apply → `/ark-explore` |
21
+ | Brownfield or greenfield with apply | Only fitness numbers → `/ark-coverage` |
22
+ | User wants A + B planned and A executed | Single edge fix → `/ark-fix`; plan A only → `/ark-loop` |
23
+ | Spaghetti under ENFORCE: Shape work with user ok on B | Contract false-green first → `/ark-adopt` / `/ark-contract` STOP paths |
16
24
 
17
25
  ## Related onboarding
18
26
 
19
27
  - **Greenfield:** `/ark-architect` or `ark-check --recommend` / `ark start`.
20
28
  - **Brownfield:** `/ark-adopt` — match contract to reality; do not force a starter preset.
21
- - **Deep map only:** `/ark-explore` — full recon report without applying fixes.
22
- - **Adoption metrics only:** `/ark-coverage` — governed% + capability gaps (feeds dual plan B).
29
+ - **Deep map only:** `/ark-explore` — full recon / dual-plan seed without applying.
30
+ - **Adoption fitness only:** `/ark-coverage` — governed% + capability gaps (not pattern dual-plan).
23
31
  - **Default path:** `ark start` → `/ark-autopilot` → `ark-check --doctor`.
24
32
 
25
33
  ## Dual engine (mandatory)
@@ -64,30 +72,38 @@ Useful first wave: **core product tree** | **field path** (examples/starters) |
64
72
 
65
73
  Do this **before** grinding plan A — plan lists *violations*, not *product reality*.
66
74
  Use the **`/ark-explore` decision-grade bar** (compressed into the autopilot report, not optional fluff).
67
-
68
- 1. **Headline** — product one-liner + honesty (mode, governed%, false-green / false-promise risk).
69
- 2. **Map** — entry points, lived layout vs globs (one screen).
70
- 3. **Field path** — if `examples/` / gallery / starter docs exist: open ≥2, **run** their check when cheap; flag soft-green or broken demos. Else `Field path: n/a`.
71
- 4. **Agent/gate reality** — installed hooks vs install templates (e.g. `--hook` vs `--hook-repair`); MCP; CI gate present.
72
- 5. **Coupling** — fan-in / exports / importers for hotspots (LOC alone is a hint).
73
- 6. **False-green soft block** — doctor/coverage: empty Domain/Persistence while Application owns I/O (`airtable`, `supabase`, `prisma`, `drizzle`, `repositories`, …). Doctor gap id: `contract-false-green-io-under-application`. If so:
75
+ Include explore **§G** when spaghetti / design-weak signals fire.
76
+
77
+ 1. **Headline** — product one-liner + honesty (mode, governed%, false-green / false-promise /
78
+ **ENFORCE·design-weak** risk).
79
+ 2. **Map** — entry points, lived layout vs globs (one screen). **Concurrent patterns** table when ≥2 styles.
80
+ 3. **Phase ladder** — name **Align | Stabilize | Shape** (explore §G).
81
+ 4. **Field path** — if `examples/` / gallery / starter docs exist: open ≥2, **run** their check when cheap; flag soft-green or broken demos. Else `Field path: n/a` + internal norm.
82
+ 5. **Agent/gate reality** — installed hooks vs install templates (e.g. `--hook` vs `--hook-repair`); MCP; CI gate present.
83
+ 6. **Coupling** — fan-in / exports / importers for hotspots (LOC alone is a hint).
84
+ 7. **False-green soft block** — doctor/coverage: empty Domain/Persistence while Application owns I/O (`airtable`, `supabase`, `prisma`, `drizzle`, `repositories`, …). Doctor gap id: `contract-false-green-io-under-application`. If so:
74
85
  **STOP — do not continue this skill as complete.** **STOP — false-green: invoke /ark-adopt or /ark-contract before claiming ENFORCE.** Do not claim goal.met / ENFORCE from type-only cleanup while doctor reports `contract-false-green-io-under-application`.
75
- 7. **Seed dual plan B** — 2–5 pattern / evolution bets ranked (impact × effort × enforceability).
86
+ 8. **Seed dual plan B** — 2–5 pattern / Shape bets ranked (impact × effort × enforceability). Each B row needs pilot + success signal; I/O bets need an **extraction card** (explore §G).
76
87
 
77
88
  Min bar: **≥12 source files** across **≥4 meaningful directories** (not only files in `steps[]`).
78
- Standalone long report: `/ark-explore`. Adoption numbers deep-dive: `/ark-coverage`.
89
+ Standalone long report: `/ark-explore`. Adoption fitness only: `/ark-coverage`.
79
90
 
80
91
  ## Dual plan (always emit)
81
92
 
82
93
  | Section | Source | Question | Auto-apply? |
83
94
  |---------|--------|----------|-------------|
84
- | **A. Remediation** | `--plan --json` + opened step files | What must change so the gate is honest? | Only `mechanical-safe` by default |
85
- | **B. Pattern / evolution** | Explore + coverage/doctor | What existing patterns should improve even if A is empty? | **Never** as mechanical-safe |
95
+ | **A. Remediation** | `--plan --json` + opened step files | What must change so the **gate** is honest? | Only `mechanical-safe` by default |
96
+ | **B. Pattern / Shape** | Explore §B/§G (not coverage alone) | What **design** must improve even if A is empty? | **Never** as mechanical-safe |
86
97
 
87
98
  **Section A** — group by edge; treat `peerIsolation` / cross-slice as **judgment**.
88
- **Section B** examples: peerIsolation, move rules out of UI, strengthen starter/preset rules, write-path repair, split god orchestration modules, Domain placement / intents, import surface (`/runtime` vs root). Cap **3–5** B rows. Each row: evidence path + **así te lo re-soluciono** + next skill/command + success signal.
99
+ **Section B** examples: choose golden pattern + pilot migrate-on-touch, peerIsolation, move rules out of UI, write-path repair, split god modules, Domain placement / intents, facade SQL → port/adapter (extraction card). Cap **3–5** B rows. Each row: evidence path + **así te lo re-soluciono** + next skill/command + **success signal** + **pilot** (+ kill-switch if new layer).
89
100
 
90
- B does **not** count as “architecture healthy finished.” Report B as `proposed | deferred | applied-with-user-ok`.
101
+ B does **not** count as “architecture healthy finished.” Report B as `proposed | deferred | applied-with-user-ok`.
102
+ When A is empty and B is non-empty: status is **`goal.met on edges · Shape residual open`** — never “done” without listing B.
103
+ Prefer CLI `patternBets[]` / `designSmells[]` when present; apply B only with explicit user ok using
104
+ **extraction cards** (`docs/brownfield-adoption.md` §6) — never mechanical-safe, never silent.
105
+ If B will take multiple PRs, offer (do not require) persisting a short Shape plan under the
106
+ repo so the next agent session continues the same pilot — still never auto-apply B.
91
107
 
92
108
  ## Origin snapshot (day-zero picture)
93
109
 
@@ -136,12 +152,13 @@ B does **not** count as “architecture healthy finished.” Report B as `propos
136
152
 
137
153
  ## Done criteria
138
154
 
139
- - Explore pass completed (decision-grade map + paths + field path or n/a + B seeds).
140
- - Dual plan emitted (A and/or B; if both empty, one-line justification).
155
+ - Explore pass completed (decision-grade map + paths + field path or n/a + phase + B seeds).
156
+ - Dual plan emitted (A and/or B; if both empty, one-line justification with evidence no design-weak smells).
141
157
  - Origin present under `.ark/reports/origin.*` (frozen this run or earlier).
142
158
  - Every applied A step validated by real `ark-check`.
143
159
  - Final plan `goal.met` true **or** remaining A steps listed with file-level proposals.
144
- - Open **B opportunities** listed; report HTML paths cited.
160
+ - Open **B / Shape opportunities** listed with success signals; report HTML paths cited when used.
161
+ - If A empty and design-weak present: B listed — **Incomplete?** must not claim full healthy stop.
145
162
 
146
163
  ## Completion contract (skill incomplete if missing)
147
164
 
@@ -5,6 +5,13 @@ description: Safely edit ark.config.json (layers, rules, forbiddenGlobals, inten
5
5
 
6
6
  # /ark-contract — Change the architecture contract (safely)
7
7
 
8
+ ## When / not when
9
+
10
+ | Use `/ark-contract` when… | Do **not** use it when… |
11
+ |---------------------------|-------------------------|
12
+ | Edit layers/rules/includes/intents with source evidence | Move product code without config change → `/ark-fix` / `/ark-loop` |
13
+ | Concentrated-edge / false-green STOP from other skills | Full map without config edit → `/ark-explore` |
14
+
8
15
  The **one sanctioned way** to change layers/rules/`intentPrefixes`/includes.
9
16
  Also used to **land mined business rules** into the executable manifest (`ark.config.json` + intent naming that `ark://manifest` exposes).
10
17