arkgate 4.4.0 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -2
- package/README.md +5 -4
- package/bin/ark-check-runtime.mjs +34 -13
- package/bin/ark-layer-match.mjs +25 -12
- package/bin/lib/analysis-engine.mjs +5 -5
- package/bin/lib/html-report.mjs +8 -1
- package/bin/lib/improvement-compass-map.mjs +507 -0
- package/bin/lib/improvement-compass-types.mjs +85 -0
- package/bin/lib/improvement-compass.mjs +10 -561
- package/bin/lib/managed-upgrade-honesty.mjs +201 -0
- package/bin/lib/managed-upgrade.mjs +37 -4
- package/bin/lib/status-command.mjs +127 -2
- package/bin/lib/status-manifest.mjs +163 -14
- package/dist/eslint/index.cjs +2 -2
- package/dist/eslint/index.js +2 -2
- package/dist/index.cjs +33 -33
- package/dist/index.d.ts +126 -21
- package/dist/index.js +33 -33
- package/docs/README.md +5 -5
- package/docs/agent-guide.md +35 -8
- package/docs/develop.md +3 -1
- package/docs/package-surface.md +7 -6
- package/docs/product-voice.md +4 -1
- package/docs/use.md +30 -0
- package/package.json +1 -1
- package/schemas/ark.status-manifest.schema.json +28 -1
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,13 +5,58 @@ in the immutable pre-2.0 archive linked below.
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 4.5.0 — 2026-08-10
|
|
9
|
+
|
|
10
|
+
**Minor** over 4.4.0. Session control-plane honesty (status/MCP improvement compass with explicit
|
|
11
|
+
modes), domain module fitness (split oversized pure modules), selective pure verification ratchet,
|
|
12
|
+
self-service upgrade activation honesty, and a short session recipe in product docs. **No required
|
|
13
|
+
config migration.** Codex remains advisory at write time. Skills and AGENTS projection never
|
|
14
|
+
enforce. **Status: prepared in tree — not published on npm until OIDC publish + `npm view` succeed**
|
|
15
|
+
(see `docs/releases/4.5.0.md`).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Status / MCP improvement compass honesty:** `ark status --json` and MCP `ark_status` always
|
|
20
|
+
project `improvementCompass` with explicit mode `full` \| `subset` \| `unavailable`, residual
|
|
21
|
+
lens ids, and `notAScore: true`. Incomplete or missing session facts never invent green residual.
|
|
22
|
+
When mode is `full`, residual ids are a subset of doctor residual for the same facts (report
|
|
23
|
+
snapshots store the thin slice). Residual never flips `valid` / strict-merge / `goal.met`.
|
|
24
|
+
Root helpers: `projectStatusImprovementCompass`, `STATUS_COMPASS_MODES`.
|
|
25
|
+
- **Session recipe (product docs):** identity bind → `ark status` → act on residual / `findingRef`;
|
|
26
|
+
run doctor when status compass mode is not `full`. Documented in use / agent-guide / develop —
|
|
27
|
+
no new skill names.
|
|
28
|
+
- **Managed upgrade self-service honesty:** `ark upgrade [--json]` surfaces `selfService` with
|
|
29
|
+
per-host write-path activation labels (`hard` \| `advisory` \| `unavailable`) and customized
|
|
30
|
+
content-identity preserve (`customizedPaths` / `customizedContentPreserved`). Soft hosts never
|
|
31
|
+
hard; upgrade never invents `hardWriteActive` from disk alone. Always `notAScore: true`. Human
|
|
32
|
+
output: “Self-service honesty” lines.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **Domain module fitness:** pure Domain `improvementCompass` monolith split into
|
|
37
|
+
`improvementCompassTypes` + `improvementCompassMap` + facade `improvementCompass` (public
|
|
38
|
+
re-exports unchanged). All three tracked in `check:module-budgets`; over-ceiling domain modules
|
|
39
|
+
require a behavior-preserving split — raising max alone is not done. CLI pure mirrors:
|
|
40
|
+
`improvement-compass-types.mjs`, `improvement-compass-map.mjs`, `improvement-compass.mjs`.
|
|
41
|
+
- **Critical pure verification ratchet:** selective verification islands on
|
|
42
|
+
`layerMatch` peerIsolation fail-closed (missing paths/slices),
|
|
43
|
+
`policyDeltaAcknowledgementMatches` (hash + finding-id set), and
|
|
44
|
+
`canPromoteInvariant` promote honesty. Property suites under `tests/property/` plus unit fixtures;
|
|
45
|
+
Stryker mutate ranges + critical groups `peer-isolation-fail-closed`,
|
|
46
|
+
`policy-delta-ack-match`, `invariant-promote-honesty`. Mutation remains cost-gated to full-matrix
|
|
47
|
+
CI / publish (`npm run test:mutation` via `test:confidence`) — **not** a whole-repo mutation claim.
|
|
48
|
+
Strict semantics unchanged.
|
|
49
|
+
|
|
50
|
+
**Freezes held:** no principle scores/ranks; no new skill names; no new ArkRules sensors; no LLM
|
|
51
|
+
verdict; projection never enforces; no false hard-write for soft hosts.
|
|
52
|
+
|
|
8
53
|
## 4.4.0 — 2026-08-09
|
|
9
54
|
|
|
10
55
|
**Minor** over 4.3.0. Improvement compass (architecture lenses as a `notAScore` projection of
|
|
11
56
|
existing sensors), doctor/HTML residual coaching, deeper skills + compact router for vibe-coder
|
|
12
57
|
and full-AI workflows, and product-only public docs. **No required config migration.** Codex remains
|
|
13
|
-
advisory at write time. Skills and AGENTS projection never enforce. **Status:
|
|
14
|
-
|
|
58
|
+
advisory at write time. Skills and AGENTS projection never enforce. **Status: published**
|
|
59
|
+
(`arkgate@4.4.0` on npm `latest`; see `docs/releases/4.4.0.md`).
|
|
15
60
|
|
|
16
61
|
### Added
|
|
17
62
|
|
package/README.md
CHANGED
|
@@ -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.4.0** is on npm `latest`. Tree is preparing **4.5.0** (session honesty + upgrade self-service) — see [4.5.0 notes](docs/releases/4.5.0.md) (Status: prepared until publish).
|
|
20
|
+
> [4.5.0 notes](docs/releases/4.5.0.md) · [4.4.0](docs/releases/4.4.0.md) · [4.3.0](docs/releases/4.3.0.md) · [Docs hub](docs/README.md) · [Product voice](docs/product-voice.md)
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -208,8 +208,9 @@ for real systems. Details: [docs/production-hardening.md](docs/production-harden
|
|
|
208
208
|
| Config · package surface · TS | [configuration](docs/configuration.md) · [package-surface](docs/package-surface.md) · [typescript-support](docs/typescript-support.md) |
|
|
209
209
|
| Brownfield | [docs/brownfield-adoption.md](docs/brownfield-adoption.md) |
|
|
210
210
|
| Security | [SECURITY.md](SECURITY.md) |
|
|
211
|
-
| Current release (4.
|
|
212
|
-
| Next prepare (4.
|
|
211
|
+
| Current release (4.4.0 on npm `latest`) | [docs/releases/4.4.0.md](docs/releases/4.4.0.md) · [CHANGELOG](CHANGELOG.md) |
|
|
212
|
+
| Next prepare (4.5.0) | [docs/releases/4.5.0.md](docs/releases/4.5.0.md) (prepared — not published until npm verify) |
|
|
213
|
+
| Prior (4.3.0) | [docs/releases/4.3.0.md](docs/releases/4.3.0.md) |
|
|
213
214
|
| Prior (4.2.1) | [docs/releases/4.2.1.md](docs/releases/4.2.1.md) |
|
|
214
215
|
| Previous (4.2.0) | [docs/releases/4.2.0.md](docs/releases/4.2.0.md) |
|
|
215
216
|
| Previous (4.1.1) | [docs/releases/4.1.1.md](docs/releases/4.1.1.md) |
|
|
@@ -1557,19 +1557,6 @@ async function main() {
|
|
|
1557
1557
|
enforcement: enforcementForReport,
|
|
1558
1558
|
config,
|
|
1559
1559
|
});
|
|
1560
|
-
const currentSnapshot = buildReportSnapshot({
|
|
1561
|
-
root,
|
|
1562
|
-
config,
|
|
1563
|
-
coverage,
|
|
1564
|
-
violations: activeViolations,
|
|
1565
|
-
ok,
|
|
1566
|
-
suppressed: suppressed.length,
|
|
1567
|
-
version: arkPackageVersion(),
|
|
1568
|
-
fileCountByLayer,
|
|
1569
|
-
enforcement: enforcementForReport,
|
|
1570
|
-
score: fitness.score,
|
|
1571
|
-
mode: fitness.mode,
|
|
1572
|
-
});
|
|
1573
1560
|
// Origin is read before archive so the HTML can show "just created" vs deltas.
|
|
1574
1561
|
const existingOrigin = args.resetOrigin
|
|
1575
1562
|
? null
|
|
@@ -1599,6 +1586,40 @@ async function main() {
|
|
|
1599
1586
|
baselineStale: analysisComplete ? reportBaselineStale : null,
|
|
1600
1587
|
}
|
|
1601
1588
|
);
|
|
1589
|
+
// DF02 — thin status compass on report snapshot so `ark status` residual ⊆ doctor.
|
|
1590
|
+
const reportCompass =
|
|
1591
|
+
designDepth?.improvementCompass && designDepth.improvementCompass.notAScore === true
|
|
1592
|
+
? {
|
|
1593
|
+
schemaVersion: '1.0',
|
|
1594
|
+
notAScore: true,
|
|
1595
|
+
mode: analysisComplete ? 'full' : 'subset',
|
|
1596
|
+
topResidual: Array.isArray(designDepth.improvementCompass.topResidual)
|
|
1597
|
+
? designDepth.improvementCompass.topResidual
|
|
1598
|
+
: [],
|
|
1599
|
+
factsSource: 'report-snapshot',
|
|
1600
|
+
...(analysisComplete
|
|
1601
|
+
? {}
|
|
1602
|
+
: {
|
|
1603
|
+
reasonCode: 'FACTS_PARTIAL',
|
|
1604
|
+
reason:
|
|
1605
|
+
'Report analysis was incomplete — status compass is a subset; re-run doctor/report for full residual.',
|
|
1606
|
+
}),
|
|
1607
|
+
}
|
|
1608
|
+
: null;
|
|
1609
|
+
const currentSnapshot = buildReportSnapshot({
|
|
1610
|
+
root,
|
|
1611
|
+
config,
|
|
1612
|
+
coverage,
|
|
1613
|
+
violations: activeViolations,
|
|
1614
|
+
ok,
|
|
1615
|
+
suppressed: suppressed.length,
|
|
1616
|
+
version: arkPackageVersion(),
|
|
1617
|
+
fileCountByLayer,
|
|
1618
|
+
enforcement: enforcementForReport,
|
|
1619
|
+
score: fitness.score,
|
|
1620
|
+
mode: fitness.mode,
|
|
1621
|
+
improvementCompass: reportCompass,
|
|
1622
|
+
});
|
|
1602
1623
|
const reportPayload = {
|
|
1603
1624
|
root,
|
|
1604
1625
|
config,
|
package/bin/ark-layer-match.mjs
CHANGED
|
@@ -258,6 +258,21 @@ function resolveSliceFolders(rule, layerName, layers) {
|
|
|
258
258
|
const layer = (layers ?? []).find((l) => l.name === layerName);
|
|
259
259
|
return inferSliceFoldersFromPatterns(layer?.patterns);
|
|
260
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* PeerIsolation deny decision given resolved path/slice evidence (DF04 pure core).
|
|
263
|
+
*
|
|
264
|
+
* Fail-closed: missing path, no classifiable folders, or unclassifiable either
|
|
265
|
+
* side → deny. Same-slice → allow (return false). Cross-slice → deny.
|
|
266
|
+
*/
|
|
267
|
+
export function peerIsolationMustDeny(input) {
|
|
268
|
+
if (!input.fromPath || !input.toPath)
|
|
269
|
+
return true;
|
|
270
|
+
if (input.folderCount <= 0)
|
|
271
|
+
return true;
|
|
272
|
+
if (!input.fromSlice || !input.toSlice)
|
|
273
|
+
return true;
|
|
274
|
+
return input.fromSlice !== input.toSlice;
|
|
275
|
+
}
|
|
261
276
|
/**
|
|
262
277
|
* Find the first denying rule for a layer edge.
|
|
263
278
|
*
|
|
@@ -279,20 +294,18 @@ export function findDeniedEdgeRule(rules, from, to, options) {
|
|
|
279
294
|
if (rule.peerIsolation) {
|
|
280
295
|
const fromPath = options?.fromPath;
|
|
281
296
|
const toPath = options?.toPath;
|
|
282
|
-
// Isolation is active: without both paths we cannot prove same-slice.
|
|
283
|
-
if (!fromPath || !toPath)
|
|
284
|
-
return rule;
|
|
285
297
|
const folders = resolveSliceFolders(rule, from, options?.layers);
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
298
|
+
const fromSlice = fromPath && toPath ? sliceIdForPath(fromPath, folders) : undefined;
|
|
299
|
+
const toSlice = fromPath && toPath ? sliceIdForPath(toPath, folders) : undefined;
|
|
300
|
+
if (peerIsolationMustDeny({
|
|
301
|
+
fromPath,
|
|
302
|
+
toPath,
|
|
303
|
+
folderCount: folders.length,
|
|
304
|
+
fromSlice,
|
|
305
|
+
toSlice,
|
|
306
|
+
})) {
|
|
295
307
|
return rule;
|
|
308
|
+
}
|
|
296
309
|
continue; // same slice: this peerIsolation rule does not deny
|
|
297
310
|
}
|
|
298
311
|
// Classic deny — same-layer always allowed without peerIsolation
|