arkgate 4.5.7 → 4.6.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.
- package/CHANGELOG.md +48 -1
- package/README.md +18 -12
- package/bin/ark-check-runtime.mjs +107 -8
- package/bin/ark-mcp-runtime.mjs +17 -1
- package/bin/ark.mjs +5 -3
- package/bin/lib/agent-homes.mjs +296 -0
- package/bin/lib/agent-projection.mjs +2 -2
- package/bin/lib/analysis-engine.mjs +3 -3
- package/bin/lib/ci-and-commands.mjs +16 -16
- package/bin/lib/config-contract.mjs +2 -0
- package/bin/lib/contract-smells.mjs +5 -5
- package/bin/lib/design-smells.mjs +4 -8
- package/bin/lib/doctor-advisories.mjs +9 -0
- package/bin/lib/doctor-plan.mjs +39 -15
- package/bin/lib/field-install.mjs +1 -1
- package/bin/lib/golden-pattern.mjs +1 -1
- package/bin/lib/host-support-matrix.mjs +4 -4
- package/bin/lib/html-report-advisories.mjs +20 -0
- package/bin/lib/html-report-depth.mjs +7 -8
- package/bin/lib/html-report.mjs +2 -1
- package/bin/lib/improvement-compass-map.mjs +20 -20
- package/bin/lib/install-migrate.mjs +12 -0
- package/bin/lib/pilot-loop.mjs +1 -1
- package/bin/lib/post-green-path.mjs +5 -4
- package/bin/lib/prepare-change.mjs +9 -0
- package/bin/lib/product-copy.mjs +32 -0
- package/bin/lib/skill-write.mjs +1 -1
- package/bin/lib/status-command.mjs +14 -0
- package/bin/lib/status-manifest.mjs +17 -0
- package/bin/lib/team-parliament-io.mjs +338 -0
- package/bin/lib/team-parliament.mjs +383 -0
- package/bin/lib/upgrade-whats-new.mjs +32 -0
- package/bin/lib/violations.mjs +8 -4
- package/dist/{configTypes-CC0FEXoF.d.ts → configTypes-B8uIcLaG.d.ts} +5 -0
- package/dist/eslint/index.cjs +2 -2
- package/dist/eslint/index.d.ts +1 -1
- package/dist/eslint/index.js +2 -2
- package/dist/index.cjs +8 -8
- package/dist/index.d.ts +61 -2
- package/dist/index.js +8 -8
- package/docs/README.md +5 -4
- package/docs/agent-guide.md +31 -24
- package/docs/ai-gates.md +19 -0
- package/docs/configuration.md +36 -2
- package/docs/develop.md +16 -4
- package/docs/enthusiast/README.md +1 -1
- package/docs/enthusiast/how-to-agent-gates.md +3 -3
- package/docs/enthusiast/how-to-pick-shape.md +2 -2
- package/docs/enthusiast/tutorial-first-project.md +4 -3
- package/docs/package-surface.md +5 -3
- package/docs/product-voice.md +126 -82
- package/docs/use.md +13 -6
- package/package.json +1 -1
- package/schemas/ark.config.schema.json +9 -0
- package/schemas/ark.status-manifest.schema.json +51 -0
- package/server.json +2 -2
- package/templates/agent-skills/README.md +1 -1
- package/templates/agent-skills/ark-adopt/SKILL.md +46 -19
- package/templates/agent-skills/ark-architect/SKILL.md +24 -145
- package/templates/agent-skills/ark-autopilot/SKILL.md +40 -30
- package/templates/agent-skills/ark-contract/SKILL.md +21 -105
- package/templates/agent-skills/ark-coverage/SKILL.md +3 -0
- package/templates/agent-skills/ark-explain/SKILL.md +7 -4
- package/templates/agent-skills/ark-explore/SKILL.md +29 -21
- package/templates/agent-skills/ark-fix/SKILL.md +34 -157
- package/templates/agent-skills/ark-loop/SKILL.md +31 -153
- package/templates/agent-skills/ark-place/SKILL.md +25 -13
- package/templates/agent-skills/ark-runtime/SKILL.md +3 -3
- package/templates/agent-skills/ark-think/SKILL.md +5 -2
- package/templates/agent-skills/ark-upgrade/SKILL.md +13 -8
- package/templates/skills/ark-adopt.md +46 -19
- package/templates/skills/ark-architect.md +24 -145
- package/templates/skills/ark-autopilot.md +40 -30
- package/templates/skills/ark-contract.md +21 -105
- package/templates/skills/ark-coverage.md +3 -0
- package/templates/skills/ark-explain.md +7 -4
- package/templates/skills/ark-explore.md +29 -21
- package/templates/skills/ark-fix.md +34 -157
- package/templates/skills/ark-loop.md +31 -153
- package/templates/skills/ark-place.md +25 -13
- package/templates/skills/ark-runtime.md +3 -3
- package/templates/skills/ark-think.md +5 -2
- package/templates/skills/ark-upgrade.md +13 -8
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,53 @@ in the immutable pre-2.0 archive linked below.
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 4.6.1 — 2026-08-14
|
|
9
|
+
|
|
10
|
+
**Patch** over **4.6.0**. Five-door autonomy (skills write or map in-turn; CLI is sensor +
|
|
11
|
+
gate) plus team parliament (law vs feature: stewards, mixed-PR deny, ratchet vs the merge
|
|
12
|
+
base, cheap `--changed` check). Same 13 skill names. Steward identity is a GitHub handle or
|
|
13
|
+
email, not git `user.name`. **No required config migration.**
|
|
14
|
+
|
|
15
|
+
**Status: prepared** (not yet on npm `latest`; see `docs/releases/4.6.1.md`).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Five-door autonomy (SK01–SK05):** `/ark-adopt`, `/ark-place`, `/ark-autopilot`,
|
|
20
|
+
`/ark-explore`, `/ark-upgrade` write or map in the same turn. The other eight names stay
|
|
21
|
+
installed as shortcuts. Invoking a door is the approval; the CLI does not apply the change.
|
|
22
|
+
- **Team parliament (TW01–TW08):** mixed law+product deny; optional `stewards` (GitHub handle
|
|
23
|
+
or email); `--contract-session` / `--contract-diff` / `--changed --base` / `--against` /
|
|
24
|
+
`--persona` / `--author`; `ark status --vs`; doctor `stewardNudge` (ask or show list drift).
|
|
25
|
+
`stewards` is excluded from the policy hash.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Doctor, compact router, and public lanes prefer the five doors. Historical changelogs stay
|
|
30
|
+
as shipped.
|
|
31
|
+
|
|
32
|
+
## 4.6.0 — 2026-08-12
|
|
33
|
+
|
|
34
|
+
**Minor** over **4.5.7**. Understandable Ark: doctor, HTML, skills, and public docs use common
|
|
35
|
+
software words (import rules, leftover design work, pre-write block) while **ArkGate** and
|
|
36
|
+
**ArkRules** stay as product names. Shared Claude/Grok agent homes get the same monotonic
|
|
37
|
+
“always latest” floor Codex already had. **No required config migration.** JSON field names
|
|
38
|
+
and `ruleId`s stay stable. No new skill names, sensors, or scores.
|
|
39
|
+
|
|
40
|
+
**Status: published** (on npm `latest`; see `docs/releases/4.6.0.md`).
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- **Shared Claude/Grok home skills:** `--claude-home`, `--grok-home`, and `--agent-homes`
|
|
45
|
+
write monotonic home catalogs (Codex-parity lock + floor). Doctor reports stale
|
|
46
|
+
`~/.claude/skills` / `~/.grok/skills` when those catalogs exist. Temp/upgrade `--root`
|
|
47
|
+
never mutates default user homes.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- **Human language:** doctor, HTML report, compact router, skills, and public lanes prefer
|
|
52
|
+
common terms. Leftover design work replaces “design-weak” in human copy; JSON `designWeak`
|
|
53
|
+
is unchanged.
|
|
54
|
+
|
|
8
55
|
## 4.5.7 — 2026-08-12
|
|
9
56
|
|
|
10
57
|
**Patch** over **4.5.6**. Cursor hard write path: project `.cursor/hooks.json` `preToolUse`
|
|
@@ -13,7 +60,7 @@ gate for `Write` / `StrReplace` (failClosed), host matrix + doctor honesty, payl
|
|
|
13
60
|
emit; Write `updated_input` reinjection is **not** claimed. Codex/OpenCode stay advisory at
|
|
14
61
|
write. Shell/Tab/human edits still rely on required CI. **No required config migration.**
|
|
15
62
|
|
|
16
|
-
**Status:
|
|
63
|
+
**Status: published** (on npm `latest`; see `docs/releases/4.5.7.md`).
|
|
17
64
|
|
|
18
65
|
### Added
|
|
19
66
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# ArkGate — Architecture Co-pilot for AI TypeScript
|
|
4
4
|
|
|
5
|
-
**One
|
|
5
|
+
**One architecture config. One check. One coach.**
|
|
6
6
|
|
|
7
7
|
Your AI writes most of the code. ArkGate keeps that work inside an architecture you can trust —
|
|
8
8
|
and makes sure a “green” check means something real.
|
|
@@ -16,8 +16,8 @@ and makes sure a “green” check means something real.
|
|
|
16
16
|
|
|
17
17
|
</div>
|
|
18
18
|
|
|
19
|
-
> **ArkGate 4.
|
|
20
|
-
> [4.
|
|
19
|
+
> **ArkGate 4.6.0** is on npm `latest` — clearer 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) · [4.5.6](docs/releases/4.5.6.md) · [Docs hub](docs/README.md) · [Product voice](docs/product-voice.md)
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -43,15 +43,18 @@ npx arkgate-check --doctor # control plane: status light + primary next a
|
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
That is the product. Doctor is the control plane — when stuck, do **primary next action #1**.
|
|
46
|
-
Doctor also shows
|
|
47
|
-
dependency inversion — **not a score**).
|
|
48
|
-
are green. Details: [use.md — Improvement compass](docs/use.md#improvement-compass-not-a-score).
|
|
46
|
+
Doctor also shows **what to improve next** (architecture lenses such as separation of concerns and
|
|
47
|
+
dependency inversion — **not a score**). Leftover lenses mean design work may remain even when
|
|
48
|
+
imports are green. Details: [use.md — Improvement compass](docs/use.md#improvement-compass-not-a-score).
|
|
49
49
|
|
|
50
50
|
```text
|
|
51
|
-
start → doctor (+ compass) → day-to-day
|
|
52
|
-
↘
|
|
51
|
+
start → doctor (+ compass) → /ark-adopt (session 0) → day-to-day /ark-place
|
|
52
|
+
↘ /ark-explore then /ark-autopilot when leftover design remains
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
Teams: keep the constitution out of product PRs. Local gate
|
|
56
|
+
`ark-check --changed --base origin/dev`. Steward law PRs use `--contract-session`.
|
|
57
|
+
|
|
55
58
|
Aliases `ark` / `ark-check` / `ark-mcp` still work. npm / pnpm / yarn. No install lifecycle scripts.
|
|
56
59
|
|
|
57
60
|

|
|
@@ -64,15 +67,15 @@ A machine-readable architecture file (`ark.config.json`) plus enforcement:
|
|
|
64
67
|
|
|
65
68
|
| When | Tool |
|
|
66
69
|
|------|------|
|
|
67
|
-
| **While the AI writes** |
|
|
70
|
+
| **While the AI writes** | Pre-write block on supported hosts; warning only elsewhere |
|
|
68
71
|
| **Before merge** | `arkgate-check` as a **required** CI status |
|
|
69
72
|
|
|
70
73
|
### Two planes (4.0)
|
|
71
74
|
|
|
72
75
|
| Plane | What it guards | Config |
|
|
73
76
|
|-------|----------------|--------|
|
|
74
|
-
| **Layers** (always) | Who may
|
|
75
|
-
| **ArkRules** (opt-in) | Habits *inside* a layer — structure sensors + domain invariants as data | `arkRules` → `arkrules/<Layer>.json` |
|
|
77
|
+
| **Layers** (always) | Who may import whom — imports, placement, purity, isolation | `ark.config.json` layers + rules |
|
|
78
|
+
| **ArkRules** (opt-in; structure rules inside a layer) | Habits *inside* a layer — structure sensors + domain invariants as data | `arkRules` → `arkrules/<Layer>.json` |
|
|
76
79
|
|
|
77
80
|
Absence of ArkRules changes no inter-layer verdict. Label residual **`[Layer]`** vs **`[ArkRules]`**.
|
|
78
81
|
Details: [configuration](docs/configuration.md#arkrules-intra-layer-opt-in) · [use path](docs/use.md).
|
|
@@ -175,6 +178,8 @@ npx arkgate-check --plan
|
|
|
175
178
|
npx arkgate-check --coverage
|
|
176
179
|
npx arkgate-check --strict-merge # CI / required status
|
|
177
180
|
npx arkgate-check --install-agent-gates --tools claude,cursor,codex,grok
|
|
181
|
+
# optional: refresh shared home skills (Claude/Grok/Codex; never downgrades)
|
|
182
|
+
# npx arkgate-check --install-agent-gates --skills-only --agent-homes --force
|
|
178
183
|
# optional: same 13 skills via Agent Skills ecosystem (no new names)
|
|
179
184
|
# npx skills add ./node_modules/arkgate/templates/agent-skills
|
|
180
185
|
```
|
|
@@ -208,7 +213,8 @@ for real systems. Details: [docs/production-hardening.md](docs/production-harden
|
|
|
208
213
|
| Config · package surface · TS | [configuration](docs/configuration.md) · [package-surface](docs/package-surface.md) · [typescript-support](docs/typescript-support.md) |
|
|
209
214
|
| Brownfield | [docs/brownfield-adoption.md](docs/brownfield-adoption.md) |
|
|
210
215
|
| Security | [SECURITY.md](SECURITY.md) |
|
|
211
|
-
| Current release (4.
|
|
216
|
+
| Current release (4.6.0 on npm `latest`) | [docs/releases/4.6.0.md](docs/releases/4.6.0.md) · [CHANGELOG](CHANGELOG.md) |
|
|
217
|
+
| Prior (4.5.7) | [docs/releases/4.5.7.md](docs/releases/4.5.7.md) |
|
|
212
218
|
| Prior (4.5.0) | [docs/releases/4.5.0.md](docs/releases/4.5.0.md) |
|
|
213
219
|
| Prior (4.4.0) | [docs/releases/4.4.0.md](docs/releases/4.4.0.md) |
|
|
214
220
|
| Prior (4.3.0) | [docs/releases/4.3.0.md](docs/releases/4.3.0.md) |
|
|
@@ -103,6 +103,13 @@ import { ANALYSIS_COMPLETENESS, analysisIncompleteStatement } from './lib/analys
|
|
|
103
103
|
import { reportUnavailableAnalysis } from './lib/unavailable-analysis.mjs';
|
|
104
104
|
import { validateHardWriteRequest } from './lib/enforcement-profiles.mjs';
|
|
105
105
|
import { analyzePolicyTransition } from './lib/policy-delta-io.mjs';
|
|
106
|
+
import {
|
|
107
|
+
applyAgainstRatchet,
|
|
108
|
+
bindTeamBaseRefs,
|
|
109
|
+
filterChangedGovernedFiles,
|
|
110
|
+
runTeamPreflight,
|
|
111
|
+
ungovernedDumpMessage,
|
|
112
|
+
} from './lib/team-parliament-io.mjs';
|
|
106
113
|
import { tryResidentDoctor } from './lib/resident-doctor-client.mjs';
|
|
107
114
|
import { createDesignDeltaCheck } from './lib/design-delta.mjs';
|
|
108
115
|
import {
|
|
@@ -134,6 +141,14 @@ function parseArgs(argv) {
|
|
|
134
141
|
policyBase: undefined,
|
|
135
142
|
policyBaseRef: undefined,
|
|
136
143
|
policyAck: undefined, failOnNewSmells: false, baseRef: undefined,
|
|
144
|
+
contractSession: false,
|
|
145
|
+
contractDiff: false,
|
|
146
|
+
changed: false,
|
|
147
|
+
against: undefined,
|
|
148
|
+
base: undefined,
|
|
149
|
+
persona: undefined,
|
|
150
|
+
author: undefined,
|
|
151
|
+
failUngoverned: false,
|
|
137
152
|
updateBaseline: false,
|
|
138
153
|
noCache: false,
|
|
139
154
|
resident: false,
|
|
@@ -213,6 +228,14 @@ function parseArgs(argv) {
|
|
|
213
228
|
else if (arg === '--watch') args.watch = true;
|
|
214
229
|
else if (arg === '--beginner') args.beginner = true;
|
|
215
230
|
else if (arg === '--codex-home') args.codexHome = true;
|
|
231
|
+
else if (arg === '--claude-home') args.claudeHome = true;
|
|
232
|
+
else if (arg === '--grok-home') args.grokHome = true;
|
|
233
|
+
else if (arg === '--agent-homes') {
|
|
234
|
+
args.agentHomes = true;
|
|
235
|
+
args.codexHome = true;
|
|
236
|
+
args.claudeHome = true;
|
|
237
|
+
args.grokHome = true;
|
|
238
|
+
}
|
|
216
239
|
else if (arg === '--migrate-commands') args.migrateCommands = true;
|
|
217
240
|
else if (arg === '--no-cache') args.noCache = true;
|
|
218
241
|
else if (arg === '--resident') args.resident = true;
|
|
@@ -233,6 +256,13 @@ function parseArgs(argv) {
|
|
|
233
256
|
else if (arg === '--policy-base') args.policyBase = requireValue(arg, i++);
|
|
234
257
|
else if (arg === '--policy-base-ref') args.policyBaseRef = requireValue(arg, i++);
|
|
235
258
|
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++);
|
|
259
|
+
else if (arg === '--contract-session') args.contractSession = true;
|
|
260
|
+
else if (arg === '--contract-diff') args.contractDiff = true;
|
|
261
|
+
else if (arg === '--changed') args.changed = true;
|
|
262
|
+
else if (arg === '--against') args.against = requireValue(arg, i++);
|
|
263
|
+
else if (arg === '--base') args.base = requireValue(arg, i++);
|
|
264
|
+
else if (arg === '--persona') args.persona = requireValue(arg, i++);
|
|
265
|
+
else if (arg === '--author') args.author = requireValue(arg, i++);
|
|
236
266
|
else if (arg === '--root') args.root = path.resolve(requireValue(arg, i++));
|
|
237
267
|
else if (arg === '--config') args.config = requireValue(arg, i++);
|
|
238
268
|
else if (arg === '--manifest') args.manifest = requireValue(arg, i++);
|
|
@@ -257,7 +287,7 @@ function usage() {
|
|
|
257
287
|
return [
|
|
258
288
|
'Usage: arkgate-check | ark-check (identical bins; product name ArkGate)',
|
|
259
289
|
' ark-check --version',
|
|
260
|
-
' 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]',
|
|
290
|
+
' 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>] [--contract-diff] [--contract-session] [--changed] [--against <git-ref>] [--base <git-ref>] [--persona touch|contributor|agent|steward] [--author <id>] [--require-gates] [--require-write-hook <host>] [--json] [--baseline [file]] [--report [file.html]] [--no-cache]',
|
|
261
291
|
' ark-check --doctor [--json] [--resident] [--fail-on-new-smells --base-ref <git-ref>] read-only diagnosis; resident JSON falls back cold',
|
|
262
292
|
' ark-check --coverage [--json] per-layer file counts + full unclassified list (report only, exit 0)',
|
|
263
293
|
' ark-check --plan [--json] classified remediation plan (mechanical-safe / judgment / deferred) + goal; report only',
|
|
@@ -275,7 +305,7 @@ function usage() {
|
|
|
275
305
|
' Best-effort open in browser (local TTY). No-op if open fails. --no-open / ARK_NO_OPEN_REPORT=1 to skip; --open forces open.',
|
|
276
306
|
' 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]',
|
|
277
307
|
' --follow-config-root On writes (init/install-agent-gates/migrate --write/…), adopt walked-up monorepo config root (default: keep explicit --root)',
|
|
278
|
-
' ark-check --install-agent-gates [--tools claude,cursor,codex,grok] [--require-write-hook <host>] [--skills-only] [--codex-home] [--force]',
|
|
308
|
+
' 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]',
|
|
279
309
|
' ark-check --update-baseline [file] freeze current violations (default .ark-baseline.json)',
|
|
280
310
|
' ark-check --print-config eleven-layer',
|
|
281
311
|
'',
|
|
@@ -283,6 +313,11 @@ function usage() {
|
|
|
283
313
|
'violations, commit the baseline file, and gate CI with --baseline: only NEW violations',
|
|
284
314
|
'fail the check, so the ratchet only moves toward zero.',
|
|
285
315
|
'',
|
|
316
|
+
'Team parliament: law files (ark.config / arkrules / .ark-baseline.json) cannot ship in',
|
|
317
|
+
'the same diff as product source. --changed --base <ref> checks touched files only.',
|
|
318
|
+
'--against <ref> ratchets new keys vs that ref\'s baseline. --contract-session is a',
|
|
319
|
+
'steward law-only PR. Loosen / baseline-grow need stewards[] + --author when set.',
|
|
320
|
+
'',
|
|
286
321
|
'--init scans the project for the built-in layer directory conventions (src/domain,',
|
|
287
322
|
'src/application, src/adapters/persistence, ...) and writes an ark.config.json covering',
|
|
288
323
|
'only the layers that actually exist, with the default rules filtered to those layers.',
|
|
@@ -538,7 +573,7 @@ function runApplyPolicyPack(args) {
|
|
|
538
573
|
|
|
539
574
|
if (fs.existsSync(configPath) && !args.force) {
|
|
540
575
|
console.error(
|
|
541
|
-
`${configPath} already exists. Re-run with --force to overwrite, or use /ark-
|
|
576
|
+
`${configPath} already exists. Re-run with --force to overwrite, or use /ark-adopt to evolve it.`
|
|
542
577
|
);
|
|
543
578
|
process.exitCode = 2;
|
|
544
579
|
return;
|
|
@@ -1022,7 +1057,7 @@ function runInit(args) {
|
|
|
1022
1057
|
console.log('A green check ignores this code; it is not "clean", it is unchecked.');
|
|
1023
1058
|
if (recognized.length > 0) {
|
|
1024
1059
|
console.log('');
|
|
1025
|
-
console.log('Proposed layer for each (from the 11-layer profile + presets — apply via /ark-
|
|
1060
|
+
console.log('Proposed layer for each (from the 11-layer profile + presets — apply via /ark-adopt):');
|
|
1026
1061
|
for (const p of recognized) {
|
|
1027
1062
|
const alt = p.alternatives?.length ? ` (or ${p.alternatives.join(' / ')} — confirm)` : '';
|
|
1028
1063
|
console.log(` ${p.dir}/ → ${p.layer}${alt}`);
|
|
@@ -1273,19 +1308,71 @@ async function main() {
|
|
|
1273
1308
|
}
|
|
1274
1309
|
|
|
1275
1310
|
const root = args.root;
|
|
1311
|
+
const bound = bindTeamBaseRefs(args, root);
|
|
1312
|
+
Object.assign(args, bound.args);
|
|
1276
1313
|
const config = readConfig(root, args.config);
|
|
1277
1314
|
const policyDelta = analyzePolicyTransition({
|
|
1278
1315
|
root,
|
|
1279
1316
|
configPath: args.config,
|
|
1280
1317
|
candidateConfig: config,
|
|
1281
|
-
strictMerge: args.strictMerge,
|
|
1318
|
+
strictMerge: args.strictMerge || args.contractDiff,
|
|
1282
1319
|
basePath: args.policyBase,
|
|
1283
1320
|
baseRef: args.policyBaseRef,
|
|
1284
1321
|
acknowledgementPath: args.policyAck,
|
|
1285
1322
|
});
|
|
1323
|
+
const preflight = runTeamPreflight({
|
|
1324
|
+
root,
|
|
1325
|
+
args,
|
|
1326
|
+
config,
|
|
1327
|
+
policyDelta,
|
|
1328
|
+
teamBase: bound.teamBase,
|
|
1329
|
+
});
|
|
1330
|
+
const teamParliament = preflight.teamParliament;
|
|
1331
|
+
const changedPaths = preflight.changedPaths;
|
|
1332
|
+
if (preflight.halt) {
|
|
1333
|
+
if (args.json) {
|
|
1334
|
+
console.log(
|
|
1335
|
+
JSON.stringify(
|
|
1336
|
+
{
|
|
1337
|
+
ok: preflight.halt.exitCode === 0,
|
|
1338
|
+
...(preflight.halt.cheap ? { cheap: true } : {}),
|
|
1339
|
+
teamParliament: preflight.halt.teamParliament,
|
|
1340
|
+
...(policyDelta ? { policyDelta } : {}),
|
|
1341
|
+
},
|
|
1342
|
+
null,
|
|
1343
|
+
2
|
|
1344
|
+
)
|
|
1345
|
+
);
|
|
1346
|
+
} else if (preflight.halt.exitCode === 0) {
|
|
1347
|
+
console.log('✔ Ark check passed (no governed source or constitution files in the diff).');
|
|
1348
|
+
} else {
|
|
1349
|
+
console.error(preflight.halt.message);
|
|
1350
|
+
}
|
|
1351
|
+
process.exitCode = preflight.halt.exitCode;
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1286
1354
|
const manifest = readManifest(root, args.manifest);
|
|
1287
1355
|
const rules = manifest?.architecture?.rules ?? config.rules;
|
|
1288
|
-
const
|
|
1356
|
+
const allGovernedFiles = collectGovernedFiles(root, config);
|
|
1357
|
+
if (args.failUngoverned && teamParliament?.changeSet?.productPaths?.length) {
|
|
1358
|
+
const governedRel = new Set(
|
|
1359
|
+
allGovernedFiles.map((abs) => normalize(path.relative(root, abs)))
|
|
1360
|
+
);
|
|
1361
|
+
const dumped = teamParliament.changeSet.productPaths.filter((rel) => !governedRel.has(rel));
|
|
1362
|
+
if (dumped.length > 0) {
|
|
1363
|
+
const message = ungovernedDumpMessage(dumped);
|
|
1364
|
+
if (args.json) {
|
|
1365
|
+
console.log(JSON.stringify({ ok: false, teamParliament: { ...teamParliament, ungoverned: dumped }, message }, null, 2));
|
|
1366
|
+
} else {
|
|
1367
|
+
console.error(message);
|
|
1368
|
+
}
|
|
1369
|
+
process.exitCode = 1;
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
const files = args.changed
|
|
1374
|
+
? filterChangedGovernedFiles(allGovernedFiles, root, changedPaths, normalize)
|
|
1375
|
+
: allGovernedFiles;
|
|
1289
1376
|
|
|
1290
1377
|
// --coverage is a pure glob/report view (no TypeScript resolver), so serve it BEFORE the
|
|
1291
1378
|
// TS import: the report must work — and exit 0 — even when typescript isn't installed.
|
|
@@ -1373,7 +1460,7 @@ async function main() {
|
|
|
1373
1460
|
printViolationBreakdown(summary, { toStderr: true });
|
|
1374
1461
|
console.error('');
|
|
1375
1462
|
console.error('Freezing this would bury a likely CONTRACT bug as "debt". Fix the contract');
|
|
1376
|
-
console.error('first (/ark-
|
|
1463
|
+
console.error('first (/ark-adopt), then re-run. To freeze anyway: --update-baseline --force.');
|
|
1377
1464
|
process.exitCode = 2;
|
|
1378
1465
|
return;
|
|
1379
1466
|
}
|
|
@@ -1422,7 +1509,18 @@ async function main() {
|
|
|
1422
1509
|
let suppressed = [];
|
|
1423
1510
|
let activeViolations = violations;
|
|
1424
1511
|
let staleBaselineKeys = 0;
|
|
1425
|
-
if (args.
|
|
1512
|
+
if (args.against) {
|
|
1513
|
+
const ratcheted = applyAgainstRatchet({
|
|
1514
|
+
violations,
|
|
1515
|
+
againstRef: args.against,
|
|
1516
|
+
root,
|
|
1517
|
+
changed: args.changed,
|
|
1518
|
+
changedPaths,
|
|
1519
|
+
occurrenceKeys: baselineOccurrenceKeys(violations),
|
|
1520
|
+
});
|
|
1521
|
+
activeViolations = ratcheted.activeViolations;
|
|
1522
|
+
suppressed = ratcheted.suppressed;
|
|
1523
|
+
} else if (args.baseline) {
|
|
1426
1524
|
const baseline = readBaseline(root, args.baseline);
|
|
1427
1525
|
if (baseline.exists) {
|
|
1428
1526
|
const occurrenceKeys = baselineOccurrenceKeys(violations);
|
|
@@ -1747,6 +1845,7 @@ async function main() {
|
|
|
1747
1845
|
}
|
|
1748
1846
|
: {}),
|
|
1749
1847
|
...(codexRepoSkillGap ? { codexRepoSkillGap } : {}), ...(policyDelta ? { policyDelta } : {}), ...(designDelta ? { edgeValid: edgeOk, designDelta } : {}),
|
|
1848
|
+
...(teamParliament ? { teamParliament } : {}),
|
|
1750
1849
|
}, null, 2));
|
|
1751
1850
|
} else {
|
|
1752
1851
|
for (const warning of warnings) {
|
package/bin/ark-mcp-runtime.mjs
CHANGED
|
@@ -73,6 +73,8 @@ import {
|
|
|
73
73
|
} from './lib/prepare-change.mjs';
|
|
74
74
|
import { detectWritePathCapabilities } from './lib/write-path-detect.mjs';
|
|
75
75
|
import { collectGovernedFiles, isGovernableSourceFile } from './lib/scan-files.mjs';
|
|
76
|
+
import { classifyChangeSet, evaluateTeamGate } from './lib/team-parliament.mjs';
|
|
77
|
+
import { contractSessionFrom } from './lib/team-parliament-io.mjs';
|
|
76
78
|
import {
|
|
77
79
|
canonicalizeCandidateChanges,
|
|
78
80
|
resolvedCompilerInputPaths,
|
|
@@ -657,6 +659,20 @@ function runHookPayload(payload, gate, config, args, ts, attemptContext, output
|
|
|
657
659
|
return;
|
|
658
660
|
}
|
|
659
661
|
const patchWrites = parsedPatch.writes;
|
|
662
|
+
const patchChangeSet = classifyChangeSet(patchWrites.map((change) => String(change.path)));
|
|
663
|
+
const patchLawGate = evaluateTeamGate({
|
|
664
|
+
changeSet: patchChangeSet,
|
|
665
|
+
contractSession: contractSessionFrom({}),
|
|
666
|
+
});
|
|
667
|
+
if (patchLawGate.deny && patchChangeSet.mixed) {
|
|
668
|
+
const message = patchLawGate.message;
|
|
669
|
+
output.stderr(`Ark architecture gate: ${message}\n`);
|
|
670
|
+
if (grokStyle) {
|
|
671
|
+
output.stdout(`${JSON.stringify({ decision: 'deny', reason: message })}\n`);
|
|
672
|
+
}
|
|
673
|
+
output.status(2);
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
660
676
|
const sourceWrites = patchWrites.filter((change) =>
|
|
661
677
|
isGovernableSourceFile(path.basename(String(change.path)))
|
|
662
678
|
);
|
|
@@ -1387,7 +1403,7 @@ function printSessionContext(config, profile, forbiddenGlobals, args, configPath
|
|
|
1387
1403
|
const governedPercent = coverage?.coverage?.governed?.percent ?? coverage?.governed?.percent;
|
|
1388
1404
|
if (shouldShowNewHereNudge(args.root, configPath, governedPercent, false)) {
|
|
1389
1405
|
lines.push('');
|
|
1390
|
-
lines.push('New to Ark? Run /ark-architect or: ark-check --recommend');
|
|
1406
|
+
lines.push('New to Ark? Run /ark-adopt (or /ark-architect) or: ark-check --recommend');
|
|
1391
1407
|
}
|
|
1392
1408
|
|
|
1393
1409
|
process.stdout.write(`${lines.join('\n')}\n`);
|
package/bin/ark.mjs
CHANGED
|
@@ -138,6 +138,7 @@ function parseArgs(argv) {
|
|
|
138
138
|
}
|
|
139
139
|
else if (arg === '--expected-root') args.expectedRoot = path.resolve(requireValue(arg, i++));
|
|
140
140
|
else if (arg === '--expected-project-id') args.expectedProjectId = requireValue(arg, i++);
|
|
141
|
+
else if (arg === '--vs') args.vs = requireValue(arg, i++);
|
|
141
142
|
else if (arg === '--write') args.write = true;
|
|
142
143
|
else if (arg === '--check') args.check = true;
|
|
143
144
|
else if (arg === '--stdout') args.stdout = true;
|
|
@@ -157,7 +158,7 @@ function usage() {
|
|
|
157
158
|
[--archetype <playbook-id>] [--tools <list>] [--require-write-hook <host>] [--yes] [--force] [--no-strict]
|
|
158
159
|
ark upgrade [--root <project>] [--tools <list>] [--apply] [--plan-digest <sha256>] [--accept-conflicts] [--refresh-skills] [--json] [--no-install] [--no-strict]
|
|
159
160
|
ark preflight --changes <change-set.json> [--change-map <map.json>] [--root <project>] [--config ark.config.json] [--manifest <manifest.json>] [--tsconfig <tsconfig.json>] [--json]
|
|
160
|
-
ark status [--root <project>] [--config ark.config.json] [--json]
|
|
161
|
+
ark status [--root <project>] [--config ark.config.json] [--json] [--vs <git-ref>]
|
|
161
162
|
[--expected-root <abs>] [--expected-project-id sha256:…] [--tools <host>]
|
|
162
163
|
ark agents-md [--root <project>] [--config ark.config.json] [--write] [--check] [--stdout] [--json]
|
|
163
164
|
[--tools <host>]
|
|
@@ -796,7 +797,7 @@ async function start(args) {
|
|
|
796
797
|
console.log('');
|
|
797
798
|
console.log('Next (the only flow you need):');
|
|
798
799
|
if (falseGreenGap) {
|
|
799
|
-
console.log(' 1. In your agent: /ark-adopt
|
|
800
|
+
console.log(' 1. In your agent: /ark-adopt — fix the architecture config first');
|
|
800
801
|
console.log(' → reclassify I/O dirs out of Application; then /ark-autopilot for residual debt.');
|
|
801
802
|
} else {
|
|
802
803
|
console.log(' 1. In your agent: /ark-autopilot');
|
|
@@ -811,7 +812,7 @@ async function start(args) {
|
|
|
811
812
|
}
|
|
812
813
|
console.log('');
|
|
813
814
|
console.log('Optional later: ark-check --report ark-report.html (captures a day-zero/evolution report).');
|
|
814
|
-
console.log('Optional later: --plan · --coverage · /ark-explore · /ark-
|
|
815
|
+
console.log('Optional later: --plan · --coverage · /ark-explore · /ark-autopilot · /ark-place · ark upgrade');
|
|
815
816
|
return 0;
|
|
816
817
|
} finally {
|
|
817
818
|
rl?.close();
|
|
@@ -941,6 +942,7 @@ async function main() {
|
|
|
941
942
|
expectedProjectId: args.expectedProjectId,
|
|
942
943
|
host: args.tools,
|
|
943
944
|
arkgateVersion: cliVersion(),
|
|
945
|
+
vs: args.vs,
|
|
944
946
|
});
|
|
945
947
|
}
|
|
946
948
|
|