arkgate 4.6.0 → 4.6.2

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 (78) hide show
  1. package/CHANGELOG.md +54 -1
  2. package/README.md +11 -5
  3. package/bin/ark-check-runtime.mjs +115 -128
  4. package/bin/ark-mcp-runtime.mjs +86 -48
  5. package/bin/ark.mjs +21 -78
  6. package/bin/lib/agent-projection.mjs +1 -1
  7. package/bin/lib/analysis-engine.mjs +3 -3
  8. package/bin/lib/ci-and-commands.mjs +11 -11
  9. package/bin/lib/config-contract.mjs +2 -0
  10. package/bin/lib/contract-smells.mjs +5 -5
  11. package/bin/lib/design-smells.mjs +1 -1
  12. package/bin/lib/doctor-advisories.mjs +9 -0
  13. package/bin/lib/doctor-next-actions.mjs +92 -0
  14. package/bin/lib/doctor-plan.mjs +61 -71
  15. package/bin/lib/field-install.mjs +1 -1
  16. package/bin/lib/first-run-help.mjs +221 -0
  17. package/bin/lib/html-report-advisories.mjs +20 -0
  18. package/bin/lib/improvement-compass-map.mjs +20 -20
  19. package/bin/lib/pilot-loop.mjs +1 -1
  20. package/bin/lib/post-green-path.mjs +2 -2
  21. package/bin/lib/prepare-change.mjs +9 -0
  22. package/bin/lib/product-copy.mjs +1 -1
  23. package/bin/lib/start-preview.mjs +17 -10
  24. package/bin/lib/status-command.mjs +19 -0
  25. package/bin/lib/status-manifest.mjs +23 -0
  26. package/bin/lib/team-parliament-io.mjs +338 -0
  27. package/bin/lib/team-parliament.mjs +383 -0
  28. package/bin/lib/upgrade-whats-new.mjs +16 -0
  29. package/bin/lib/violations.mjs +8 -4
  30. package/dist/{configTypes-CC0FEXoF.d.ts → configTypes-B8uIcLaG.d.ts} +5 -0
  31. package/dist/eslint/index.cjs +2 -2
  32. package/dist/eslint/index.d.ts +1 -1
  33. package/dist/eslint/index.js +2 -2
  34. package/dist/index.cjs +8 -8
  35. package/dist/index.d.ts +66 -2
  36. package/dist/index.js +8 -8
  37. package/docs/README.md +5 -5
  38. package/docs/agent-guide.md +21 -17
  39. package/docs/configuration.md +36 -2
  40. package/docs/develop.md +13 -1
  41. package/docs/enthusiast/README.md +1 -1
  42. package/docs/enthusiast/how-to-agent-gates.md +3 -3
  43. package/docs/enthusiast/how-to-pick-shape.md +2 -2
  44. package/docs/enthusiast/tutorial-first-project.md +4 -3
  45. package/docs/package-surface.md +5 -3
  46. package/docs/product-voice.md +48 -10
  47. package/docs/use.md +10 -5
  48. package/package.json +2 -2
  49. package/schemas/ark.config.schema.json +9 -0
  50. package/schemas/ark.status-manifest.schema.json +51 -0
  51. package/server.json +3 -3
  52. package/templates/agent-skills/README.md +1 -1
  53. package/templates/agent-skills/ark-adopt/SKILL.md +59 -23
  54. package/templates/agent-skills/ark-architect/SKILL.md +24 -145
  55. package/templates/agent-skills/ark-autopilot/SKILL.md +49 -32
  56. package/templates/agent-skills/ark-contract/SKILL.md +21 -105
  57. package/templates/agent-skills/ark-coverage/SKILL.md +7 -3
  58. package/templates/agent-skills/ark-explain/SKILL.md +8 -4
  59. package/templates/agent-skills/ark-explore/SKILL.md +38 -21
  60. package/templates/agent-skills/ark-fix/SKILL.md +34 -157
  61. package/templates/agent-skills/ark-loop/SKILL.md +31 -153
  62. package/templates/agent-skills/ark-place/SKILL.md +35 -14
  63. package/templates/agent-skills/ark-runtime/SKILL.md +3 -3
  64. package/templates/agent-skills/ark-think/SKILL.md +6 -2
  65. package/templates/agent-skills/ark-upgrade/SKILL.md +21 -10
  66. package/templates/skills/ark-adopt.md +59 -23
  67. package/templates/skills/ark-architect.md +24 -145
  68. package/templates/skills/ark-autopilot.md +49 -32
  69. package/templates/skills/ark-contract.md +21 -105
  70. package/templates/skills/ark-coverage.md +7 -3
  71. package/templates/skills/ark-explain.md +8 -4
  72. package/templates/skills/ark-explore.md +38 -21
  73. package/templates/skills/ark-fix.md +34 -157
  74. package/templates/skills/ark-loop.md +31 -153
  75. package/templates/skills/ark-place.md +35 -14
  76. package/templates/skills/ark-runtime.md +3 -3
  77. package/templates/skills/ark-think.md +6 -2
  78. package/templates/skills/ark-upgrade.md +21 -10
package/CHANGELOG.md CHANGED
@@ -5,6 +5,59 @@ in the immutable pre-2.0 archive linked below.
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## 4.6.2 — 2026-08-16
9
+
10
+ **Patch** over **4.6.1**. First-contact copy: a newcomer (human or coding agent) sees what
11
+ to do in a few lines — `arkgate` / `arkgate-check --help`, start wrap-up, doctor light +
12
+ #1, write-gate deny, SessionStart, MCP tool order, and the five doors. Same 13 skill names.
13
+ **No required config migration.**
14
+
15
+ **Status: prepared** (not yet on npm `latest`; see `docs/releases/4.6.2.md`).
16
+
17
+ ### Changed
18
+
19
+ - **First-run help:** `arkgate --help` and `arkgate-check --help` are short; encyclopedia
20
+ text is `--help --all`. `arkgate upgrade --help` is preview vs apply.
21
+ - **Start wrap-up:** doctor → `/ark-adopt` session 0 (not `/ark-autopilot` as step 1).
22
+ - **Doctor:** operating-mode light + primary next action #1 print first.
23
+ - **Write-gate deny:** `blocked {file} — {reason}` then `Next:` (move the import / `/ark-place`).
24
+ Rule id on a following line. No “call ark_manifest”.
25
+ - **Agents:** SessionStart points at `/ark-adopt` or `arkgate-check --doctor`. `ark_identity`
26
+ is first. `ark_check` is a scan (pass/fail/incomplete), not a yes/no architecture score.
27
+ `server.json` first sentence is the layers definition.
28
+ - **Skills:** five doors open with when + steps. Shortcuts are not the first-run menu.
29
+ - **Status:** `nextAction` is `map-leftover-design` when leftover design work remains
30
+ (never `stay-enforced`).
31
+ - **npm `description`:** `One architecture config. One check. One coach.` (not “co-pilot”).
32
+ - **`docs/use.md`:** Cursor hard-blocks Write/StrReplace when hooks are trusted;
33
+ Codex/OpenCode stay advisory.
34
+
35
+ ## 4.6.1 — 2026-08-14
36
+
37
+ **Patch** over **4.6.0**. Five-door autonomy (skills write or map in-turn; CLI is sensor +
38
+ gate) plus team parliament (law vs feature: stewards, mixed-PR deny, ratchet vs the merge
39
+ base, cheap `--changed` check). Same 13 skill names. Steward identity is a GitHub handle or
40
+ email, not git `user.name`. **No required config migration.**
41
+
42
+ **Status: published** (on npm `latest`; see `docs/releases/4.6.1.md`).
43
+
44
+ ### Added
45
+
46
+ - **Five-door autonomy (SK01–SK05):** `/ark-adopt`, `/ark-place`, `/ark-autopilot`,
47
+ `/ark-explore`, `/ark-upgrade` write or map in the same turn. The other eight names stay
48
+ installed as shortcuts. Invoking a door is the approval; the CLI does not apply the change.
49
+ - **Team parliament (TW01–TW08):** mixed law+product deny; optional `stewards` (GitHub handle
50
+ or email); `--contract-session` / `--contract-diff` / `--changed --base` / `--against` /
51
+ `--persona` / `--author`; `ark status --vs`; doctor `stewardNudge` (ask or show list drift).
52
+ `stewards` is excluded from the policy hash.
53
+
54
+ ### Changed
55
+
56
+ - Doctor, compact router, and public lanes prefer the five doors. Historical changelogs stay
57
+ as shipped.
58
+ - Published 4.6.1 tarball `README.md` still banners 4.6.0 (packed at `1eadc96` before the
59
+ pointer flip). Tree README on `main` is current. No 4.6.2 for that banner.
60
+
8
61
  ## 4.6.0 — 2026-08-12
9
62
 
10
63
  **Minor** over **4.5.7**. Understandable Ark: doctor, HTML, skills, and public docs use common
@@ -13,7 +66,7 @@ software words (import rules, leftover design work, pre-write block) while **Ark
13
66
  “always latest” floor Codex already had. **No required config migration.** JSON field names
14
67
  and `ruleId`s stay stable. No new skill names, sensors, or scores.
15
68
 
16
- **Status: prepared** (not yet on npm `latest`; see `docs/releases/4.6.0.md`).
69
+ **Status: published** (on npm `latest`; see `docs/releases/4.6.0.md`).
17
70
 
18
71
  ### Added
19
72
 
package/README.md CHANGED
@@ -16,8 +16,9 @@ and makes sure a “green” check means something real.
16
16
 
17
17
  </div>
18
18
 
19
- > **ArkGate 4.6.0** is preparedclearer language + shared agent home skills.
20
- > [4.6.0 notes](docs/releases/4.6.0.md) · [4.5.7](docs/releases/4.5.7.md) (npm `latest`) · [4.5.6](docs/releases/4.5.6.md) · [Docs hub](docs/README.md) · [Product voice](docs/product-voice.md)
19
+ > **ArkGate 4.6.1** is on npm `latest` five doors + a lock on the constitution.
20
+ > **4.6.2** is prepared on this tree (first-contact copy; not yet `latest`).
21
+ > [4.6.2 notes](docs/releases/4.6.2.md) · [4.6.1](docs/releases/4.6.1.md) · [4.6.0](docs/releases/4.6.0.md) · [Docs hub](docs/README.md) · [Product voice](docs/product-voice.md)
21
22
 
22
23
  ---
23
24
 
@@ -48,10 +49,13 @@ dependency inversion — **not a score**). Leftover lenses mean design work may
48
49
  imports are green. Details: [use.md — Improvement compass](docs/use.md#improvement-compass-not-a-score).
49
50
 
50
51
  ```text
51
- start → doctor (+ compass) → day-to-day (place + gate)
52
- optional /ark-autopilot after skill pack
52
+ start → doctor (+ compass) → /ark-adopt (session 0) → day-to-day /ark-place
53
+ /ark-explore then /ark-autopilot when leftover design remains
53
54
  ```
54
55
 
56
+ Teams: keep the constitution out of product PRs. Local gate
57
+ `ark-check --changed --base origin/dev`. Steward law PRs use `--contract-session`.
58
+
55
59
  Aliases `ark` / `ark-check` / `ark-mcp` still work. npm / pnpm / yarn. No install lifecycle scripts.
56
60
 
57
61
  ![Write gate: agent blocked, then self-corrects](docs/assets/ark-write-gate.svg)
@@ -210,7 +214,9 @@ for real systems. Details: [docs/production-hardening.md](docs/production-harden
210
214
  | Config · package surface · TS | [configuration](docs/configuration.md) · [package-surface](docs/package-surface.md) · [typescript-support](docs/typescript-support.md) |
211
215
  | Brownfield | [docs/brownfield-adoption.md](docs/brownfield-adoption.md) |
212
216
  | Security | [SECURITY.md](SECURITY.md) |
213
- | Current release (4.5.7 on npm `latest`) | [docs/releases/4.5.7.md](docs/releases/4.5.7.md) · [CHANGELOG](CHANGELOG.md) |
217
+ | Current release (4.6.1 on npm `latest`) | [docs/releases/4.6.1.md](docs/releases/4.6.1.md) · [CHANGELOG](CHANGELOG.md) |
218
+ | Prepared (4.6.2 — not yet `latest`) | [docs/releases/4.6.2.md](docs/releases/4.6.2.md) |
219
+ | Prior (4.5.7) | [docs/releases/4.5.7.md](docs/releases/4.5.7.md) |
214
220
  | Prior (4.5.0) | [docs/releases/4.5.0.md](docs/releases/4.5.0.md) |
215
221
  | Prior (4.4.0) | [docs/releases/4.4.0.md](docs/releases/4.4.0.md) |
216
222
  | Prior (4.3.0) | [docs/releases/4.3.0.md](docs/releases/4.3.0.md) |
@@ -95,6 +95,7 @@ import {
95
95
  writeArkRulesTemplates,
96
96
  } from './lib/presets.mjs';
97
97
  import { loadArkConfigContract, parseArkConfigJson } from './lib/config-contract.mjs';
98
+ import { checkUsage, checkUsageAll } from './lib/first-run-help.mjs';
98
99
  import { createAdapterResult } from './lib/adapter-contract.mjs';
99
100
  import { collectGovernedFiles, normalize, walk } from './lib/scan-files.mjs';
100
101
  import { configWarning } from './lib/config-warnings.mjs';
@@ -103,6 +104,13 @@ import { ANALYSIS_COMPLETENESS, analysisIncompleteStatement } from './lib/analys
103
104
  import { reportUnavailableAnalysis } from './lib/unavailable-analysis.mjs';
104
105
  import { validateHardWriteRequest } from './lib/enforcement-profiles.mjs';
105
106
  import { analyzePolicyTransition } from './lib/policy-delta-io.mjs';
107
+ import {
108
+ applyAgainstRatchet,
109
+ bindTeamBaseRefs,
110
+ filterChangedGovernedFiles,
111
+ runTeamPreflight,
112
+ ungovernedDumpMessage,
113
+ } from './lib/team-parliament-io.mjs';
106
114
  import { tryResidentDoctor } from './lib/resident-doctor-client.mjs';
107
115
  import { createDesignDeltaCheck } from './lib/design-delta.mjs';
108
116
  import {
@@ -134,6 +142,14 @@ function parseArgs(argv) {
134
142
  policyBase: undefined,
135
143
  policyBaseRef: undefined,
136
144
  policyAck: undefined, failOnNewSmells: false, baseRef: undefined,
145
+ contractSession: false,
146
+ contractDiff: false,
147
+ changed: false,
148
+ against: undefined,
149
+ base: undefined,
150
+ persona: undefined,
151
+ author: undefined,
152
+ failUngoverned: false,
137
153
  updateBaseline: false,
138
154
  noCache: false,
139
155
  resident: false,
@@ -151,12 +167,13 @@ function parseArgs(argv) {
151
167
  noOpenReport: false,
152
168
  version: false,
153
169
  help: false,
170
+ all: false,
154
171
  followConfigRoot: false,
155
172
  };
156
173
  const requireValue = (flag, index) => {
157
174
  const value = argv[index + 1];
158
175
  if (value === undefined || value.startsWith('-')) {
159
- throw new Error(`Missing value for ${flag}. Run ark-check --help for usage.`);
176
+ throw new Error(`Missing value for ${flag}. Run arkgate-check --help for usage.`);
160
177
  }
161
178
  return value;
162
179
  };
@@ -241,14 +258,22 @@ function parseArgs(argv) {
241
258
  else if (arg === '--policy-base') args.policyBase = requireValue(arg, i++);
242
259
  else if (arg === '--policy-base-ref') args.policyBaseRef = requireValue(arg, i++);
243
260
  else if (arg === '--policy-ack') args.policyAck = requireValue(arg, i++); else if (arg === '--fail-on-new-smells') args.failOnNewSmells = true; else if (arg === '--base-ref') args.baseRef = requireValue(arg, i++);
261
+ else if (arg === '--contract-session') args.contractSession = true;
262
+ else if (arg === '--contract-diff') args.contractDiff = true;
263
+ else if (arg === '--changed') args.changed = true;
264
+ else if (arg === '--against') args.against = requireValue(arg, i++);
265
+ else if (arg === '--base') args.base = requireValue(arg, i++);
266
+ else if (arg === '--persona') args.persona = requireValue(arg, i++);
267
+ else if (arg === '--author') args.author = requireValue(arg, i++);
244
268
  else if (arg === '--root') args.root = path.resolve(requireValue(arg, i++));
245
269
  else if (arg === '--config') args.config = requireValue(arg, i++);
246
270
  else if (arg === '--manifest') args.manifest = requireValue(arg, i++);
247
271
  else if (arg === '--print-config') args.printConfig = requireValue(arg, i++);
248
272
  else if (arg === '--tsconfig') args.tsconfig = requireValue(arg, i++);
249
273
  else if (arg === '--help' || arg === '-h') args.help = true;
274
+ else if (arg === '--all') args.all = true;
250
275
  else if (arg === '--version' || arg === '-V') args.version = true;
251
- else throw new Error(`Unknown argument: ${arg}. Run ark-check --help for usage.`);
276
+ else throw new Error(`Unknown argument: ${arg}. Run arkgate-check --help for usage.`);
252
277
  }
253
278
  return args;
254
279
  }
@@ -261,111 +286,6 @@ function displayPathFromRoot(root, absPath) {
261
286
  }
262
287
  return rel.split(path.sep).join('/');
263
288
  }
264
- function usage() {
265
- return [
266
- 'Usage: arkgate-check | ark-check (identical bins; product name ArkGate)',
267
- ' ark-check --version',
268
- ' ark-check --root <project> --config <ark.config.json> [--manifest <ark.manifest.json>] [--tsconfig <tsconfig.json>] [--strict-merge | --strict | --strict-config] [--policy-base <file> | --policy-base-ref <git-ref>] [--policy-ack <file>] [--fail-on-new-smells --base-ref <git-ref>] [--require-gates] [--require-write-hook <host>] [--json] [--baseline [file]] [--report [file.html]] [--no-cache]',
269
- ' ark-check --doctor [--json] [--resident] [--fail-on-new-smells --base-ref <git-ref>] read-only diagnosis; resident JSON falls back cold',
270
- ' ark-check --coverage [--json] per-layer file counts + full unclassified list (report only, exit 0)',
271
- ' ark-check --plan [--json] classified remediation plan (mechanical-safe / judgment / deferred) + goal; report only',
272
- ' ark-check --rules-inventory [--json] brownfield rules inventory (AR13; deterministic candidates, not a score)',
273
- ' ark-check --recommend [--json] [--write-plan] application-shape plan; --write-plan emits ark-adoption-plan.json',
274
- ' ark-check --list-policy-packs enthusiast packs (hexagonal, layered, feature-sliced, monorepo, ui-surface, vertical-slice, ddd-bounded-contexts)',
275
- ' ark-check --apply-policy-pack <id> [--force] write ark.config.json from templates/policy-packs/ (uses preset factory)',
276
- ' ark-check --suggest-include [--json] propose include roots (TS packages / workspaces)',
277
- ' ark-check --adopt-contract [--write] expand include + layer patterns from ungoverned dirs (never bare lib→Presentation)',
278
- ' ark-check --migrate-contract [--write] additive P0-A retrofit: inject app/api/** → Application when missing',
279
- ' ark-check --ratchet-cores when raw graph is green (0 violations; baseline ignored), set optional:false on populated cores only (writes ark.config.json)',
280
- ' ark-check --watch re-run the check when governed files change (debounced)',
281
- ' ark-check --report [file.html] [--beginner] [--reset-origin] [--no-archive] [--open|--no-open]',
282
- ' HTML report + snapshots under .ark/reports/ (origin once, latest each run, history JSON)',
283
- ' Best-effort open in browser (local TTY). No-op if open fails. --no-open / ARK_NO_OPEN_REPORT=1 to skip; --open forces open.',
284
- ' ark-check --init [--preset hexagonal|layered|feature-sliced|monorepo|ui-surface|vertical-slice|ddd-bounded-contexts|vite-vercel-spa|clean-architecture|onion-architecture] [--force] [--follow-config-root]',
285
- ' --follow-config-root On writes (init/install-agent-gates/migrate --write/…), adopt walked-up monorepo config root (default: keep explicit --root)',
286
- ' ark-check --install-agent-gates [--tools claude,cursor,codex,grok] [--require-write-hook <host>] [--skills-only] [--codex-home] [--claude-home] [--grok-home] [--agent-homes] [--force]',
287
- ' ark-check --update-baseline [file] freeze current violations (default .ark-baseline.json)',
288
- ' ark-check --print-config eleven-layer',
289
- '',
290
- 'Adopting Ark in an existing codebase? Run --update-baseline once to freeze existing',
291
- 'violations, commit the baseline file, and gate CI with --baseline: only NEW violations',
292
- 'fail the check, so the ratchet only moves toward zero.',
293
- '',
294
- '--init scans the project for the built-in layer directory conventions (src/domain,',
295
- 'src/application, src/adapters/persistence, ...) and writes an ark.config.json covering',
296
- 'only the layers that actually exist, with the default rules filtered to those layers.',
297
- 'Undetected profile layers are printed as suggestions with their conventional',
298
- 'directories. When nothing is detected, the full 11-layer starter profile is written',
299
- 'instead (all layers optional, anchored at src/), so the strict check passes today and',
300
- 'each layer starts being enforced as soon as its directory gains source files.',
301
- '',
302
- 'Resolves relative, tsconfig path-alias, and package imports via the TypeScript',
303
- 'module resolver, then checks each resolved cross-layer import against the rules.',
304
- 'Path aliases resolve against the NEAREST tsconfig.json above each source file, so',
305
- 'monorepo packages with per-package configs work under a single --root. Pass',
306
- '--tsconfig to force one config for every file. If no tsconfig is found, path',
307
- 'aliases are unavailable but relative/package imports still resolve.',
308
- '',
309
- 'The correctness path resolves and parses one complete candidate on every invocation.',
310
- 'Legacy node_modules/.cache/ark-check.json files are ignored. --no-cache remains an',
311
- 'accepted compatibility no-op; the identity-keyed warm snapshot is introduced in Z07.',
312
- '',
313
- 'Config shape:',
314
- '{',
315
- ' "include": ["src"],',
316
- ' // optional: "exclude": ["**/vendor/**"], "excludeGenerated": false (default skips *.gen.ts / *.generated.ts)',
317
- ' "layers": [',
318
- ' { "name": "DomainModel", "patterns": ["src/domain/**"], "intentPrefixes": ["Domain."],',
319
- ' "forbiddenGlobals": ["fetch", "process", "Date.now", "Math.random"] }',
320
- ' ],',
321
- ' "rules": [{ "from": "DomainModel", "to": "PersistenceAdapters", "allowed": false }]',
322
- '}',
323
- '',
324
- 'Config warnings are advisory by default and are included in JSON output.',
325
- 'Use --strict-config to make config warnings fail the check.',
326
- 'Use --strict-merge for the fail-closed CI profile: --strict-config + --require-gates',
327
- 'plus the security diagnostics surfaced by doctor. --strict is a compatibility alias.',
328
- 'This merge profile never depends on an editor/agent hook.',
329
- 'When a Git merge base is available, --strict-merge classifies the ark.config.json',
330
- 'transition. Weakening or judgment-required findings fail unless --policy-ack names',
331
- 'every finding and is bound to both policy hashes. Use --policy-base/--policy-base-ref',
332
- 'for an explicit comparison; ARK_POLICY_BASE_REF is the CI environment equivalent.',
333
- 'Add --require-write-hook claude|grok|antigravity|cursor to validate a hard local write',
334
- 'boundary for that specific host. Codex and OpenCode expose advisory MCP (plus best-effort',
335
- 'hooks where applicable) and the shared CI check; merge blocking requires repository policy',
336
- 'to make that status required.',
337
- '',
338
- '--require-gates implies --strict-config and fails when the Ark contract in AGENTS.md,',
339
- 'the project-rooted Ark server in .mcp.json, or fail-closed CI is missing/invalid.',
340
- 'Included but unclassified source files therefore stay red instead of false-green.',
341
- '',
342
- '--install-agent-gates writes AGENTS.md, .mcp.json, and the CI workflow for every',
343
- 'project, plus tool-specific templates. Known tools: claude, cursor, codex, grok',
344
- '(Claude/Grok/Antigravity/Cursor hard-write hooks when covered; Codex advisory MCP;',
345
- 'shared CI check for all) and',
346
- 'windsurf, cline, copilot, kiro, roo, continue, gemini',
347
- '(instruction-tier rule files derived from the same contract).',
348
- 'It also installs the /ark-* skills shipped in templates/skills/ into each',
349
- 'detected tool\'s command location (.claude/skills/, .cursor/commands/,',
350
- '.agents/skills/ (Codex REPO catalog), .grok/skills/, .windsurf/workflows/,',
351
- '.clinerules/workflows/, .github/prompts/).',
352
- 'Kiro, Roo, Continue, and Gemini have no command mechanism and receive only their',
353
- 'rule file. Existing files are never overwritten without --force, so re-running',
354
- 'after an update only adds what is missing. --skills-only restricts the write to',
355
- 'just the /ark-* skills (safe to --force-refresh — it leaves a customized AGENTS.md,',
356
- 'settings, and CI workflow untouched).',
357
- 'Pass --tools to pick which tool configs to write; otherwise they are auto-detected',
358
- 'from their config directories (.claude/, .cursor/, .codex/, .grok/, .windsurf/,',
359
- '.clinerules/, .kiro/, .roo/, .continue/, .gemini/; copilot is explicit-only).',
360
- 'claude+cursor+codex+grok are written when nothing is detected.',
361
- '',
362
- 'Generate a starter 11-layer config:',
363
- ' ark-check --print-config eleven-layer > ark.config.json',
364
- '',
365
- 'Install agent + CI enforcement templates:',
366
- ' ark-check --install-agent-gates',
367
- ].join('\n');
368
- }
369
289
 
370
290
  function readConfig(root, configPath) {
371
291
  const fullPath = path.isAbsolute(configPath)
@@ -546,7 +466,7 @@ function runApplyPolicyPack(args) {
546
466
 
547
467
  if (fs.existsSync(configPath) && !args.force) {
548
468
  console.error(
549
- `${configPath} already exists. Re-run with --force to overwrite, or use /ark-contract to evolve it.`
469
+ `${configPath} already exists. Re-run with --force to overwrite, or use /ark-adopt to evolve it.`
550
470
  );
551
471
  process.exitCode = 2;
552
472
  return;
@@ -1030,7 +950,7 @@ function runInit(args) {
1030
950
  console.log('A green check ignores this code; it is not "clean", it is unchecked.');
1031
951
  if (recognized.length > 0) {
1032
952
  console.log('');
1033
- console.log('Proposed layer for each (from the 11-layer profile + presets — apply via /ark-contract):');
953
+ console.log('Proposed layer for each (from the 11-layer profile + presets — apply via /ark-adopt):');
1034
954
  for (const p of recognized) {
1035
955
  const alt = p.alternatives?.length ? ` (or ${p.alternatives.join(' / ')} — confirm)` : '';
1036
956
  console.log(` ${p.dir}/ → ${p.layer}${alt}`);
@@ -1121,7 +1041,7 @@ async function main() {
1121
1041
  process.exit(0);
1122
1042
  }
1123
1043
  if (args.help) {
1124
- console.log(usage());
1044
+ console.log(args.all ? checkUsageAll() : checkUsage());
1125
1045
  return;
1126
1046
  }
1127
1047
  if (args.init) {
@@ -1281,19 +1201,71 @@ async function main() {
1281
1201
  }
1282
1202
 
1283
1203
  const root = args.root;
1204
+ const bound = bindTeamBaseRefs(args, root);
1205
+ Object.assign(args, bound.args);
1284
1206
  const config = readConfig(root, args.config);
1285
1207
  const policyDelta = analyzePolicyTransition({
1286
1208
  root,
1287
1209
  configPath: args.config,
1288
1210
  candidateConfig: config,
1289
- strictMerge: args.strictMerge,
1211
+ strictMerge: args.strictMerge || args.contractDiff,
1290
1212
  basePath: args.policyBase,
1291
1213
  baseRef: args.policyBaseRef,
1292
1214
  acknowledgementPath: args.policyAck,
1293
1215
  });
1216
+ const preflight = runTeamPreflight({
1217
+ root,
1218
+ args,
1219
+ config,
1220
+ policyDelta,
1221
+ teamBase: bound.teamBase,
1222
+ });
1223
+ const teamParliament = preflight.teamParliament;
1224
+ const changedPaths = preflight.changedPaths;
1225
+ if (preflight.halt) {
1226
+ if (args.json) {
1227
+ console.log(
1228
+ JSON.stringify(
1229
+ {
1230
+ ok: preflight.halt.exitCode === 0,
1231
+ ...(preflight.halt.cheap ? { cheap: true } : {}),
1232
+ teamParliament: preflight.halt.teamParliament,
1233
+ ...(policyDelta ? { policyDelta } : {}),
1234
+ },
1235
+ null,
1236
+ 2
1237
+ )
1238
+ );
1239
+ } else if (preflight.halt.exitCode === 0) {
1240
+ console.log('✔ Ark check passed (no governed source or constitution files in the diff).');
1241
+ } else {
1242
+ console.error(preflight.halt.message);
1243
+ }
1244
+ process.exitCode = preflight.halt.exitCode;
1245
+ return;
1246
+ }
1294
1247
  const manifest = readManifest(root, args.manifest);
1295
1248
  const rules = manifest?.architecture?.rules ?? config.rules;
1296
- const files = collectGovernedFiles(root, config);
1249
+ const allGovernedFiles = collectGovernedFiles(root, config);
1250
+ if (args.failUngoverned && teamParliament?.changeSet?.productPaths?.length) {
1251
+ const governedRel = new Set(
1252
+ allGovernedFiles.map((abs) => normalize(path.relative(root, abs)))
1253
+ );
1254
+ const dumped = teamParliament.changeSet.productPaths.filter((rel) => !governedRel.has(rel));
1255
+ if (dumped.length > 0) {
1256
+ const message = ungovernedDumpMessage(dumped);
1257
+ if (args.json) {
1258
+ console.log(JSON.stringify({ ok: false, teamParliament: { ...teamParliament, ungoverned: dumped }, message }, null, 2));
1259
+ } else {
1260
+ console.error(message);
1261
+ }
1262
+ process.exitCode = 1;
1263
+ return;
1264
+ }
1265
+ }
1266
+ const files = args.changed
1267
+ ? filterChangedGovernedFiles(allGovernedFiles, root, changedPaths, normalize)
1268
+ : allGovernedFiles;
1297
1269
 
1298
1270
  // --coverage is a pure glob/report view (no TypeScript resolver), so serve it BEFORE the
1299
1271
  // TS import: the report must work — and exit 0 — even when typescript isn't installed.
@@ -1381,7 +1353,7 @@ async function main() {
1381
1353
  printViolationBreakdown(summary, { toStderr: true });
1382
1354
  console.error('');
1383
1355
  console.error('Freezing this would bury a likely CONTRACT bug as "debt". Fix the contract');
1384
- console.error('first (/ark-contract), then re-run. To freeze anyway: --update-baseline --force.');
1356
+ console.error('first (/ark-adopt), then re-run. To freeze anyway: --update-baseline --force.');
1385
1357
  process.exitCode = 2;
1386
1358
  return;
1387
1359
  }
@@ -1430,7 +1402,18 @@ async function main() {
1430
1402
  let suppressed = [];
1431
1403
  let activeViolations = violations;
1432
1404
  let staleBaselineKeys = 0;
1433
- if (args.baseline) {
1405
+ if (args.against) {
1406
+ const ratcheted = applyAgainstRatchet({
1407
+ violations,
1408
+ againstRef: args.against,
1409
+ root,
1410
+ changed: args.changed,
1411
+ changedPaths,
1412
+ occurrenceKeys: baselineOccurrenceKeys(violations),
1413
+ });
1414
+ activeViolations = ratcheted.activeViolations;
1415
+ suppressed = ratcheted.suppressed;
1416
+ } else if (args.baseline) {
1434
1417
  const baseline = readBaseline(root, args.baseline);
1435
1418
  if (baseline.exists) {
1436
1419
  const occurrenceKeys = baselineOccurrenceKeys(violations);
@@ -1616,20 +1599,23 @@ async function main() {
1616
1599
  }),
1617
1600
  }
1618
1601
  : null;
1619
- const currentSnapshot = buildReportSnapshot({
1620
- root,
1621
- config,
1622
- coverage,
1623
- violations: activeViolations,
1624
- ok,
1625
- suppressed: suppressed.length,
1626
- version: arkPackageVersion(),
1627
- fileCountByLayer,
1628
- enforcement: enforcementForReport,
1629
- score: fitness.score,
1630
- mode: fitness.mode,
1631
- improvementCompass: reportCompass,
1632
- });
1602
+ const currentSnapshot = {
1603
+ ...buildReportSnapshot({
1604
+ root,
1605
+ config,
1606
+ coverage,
1607
+ violations: activeViolations,
1608
+ ok,
1609
+ suppressed: suppressed.length,
1610
+ version: arkPackageVersion(),
1611
+ fileCountByLayer,
1612
+ enforcement: enforcementForReport,
1613
+ score: fitness.score,
1614
+ mode: fitness.mode,
1615
+ improvementCompass: reportCompass,
1616
+ }),
1617
+ leftoverDesignWork: designDepth?.designFitness?.designWeak === true,
1618
+ };
1633
1619
  const reportPayload = {
1634
1620
  root,
1635
1621
  config,
@@ -1755,6 +1741,7 @@ async function main() {
1755
1741
  }
1756
1742
  : {}),
1757
1743
  ...(codexRepoSkillGap ? { codexRepoSkillGap } : {}), ...(policyDelta ? { policyDelta } : {}), ...(designDelta ? { edgeValid: edgeOk, designDelta } : {}),
1744
+ ...(teamParliament ? { teamParliament } : {}),
1758
1745
  }, null, 2));
1759
1746
  } else {
1760
1747
  for (const warning of warnings) {