arkgate 4.8.7 → 4.8.9
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 +92 -3
- package/README.md +41 -6
- package/bin/ark-check-runtime.mjs +22 -0
- package/bin/ark-dashboard.mjs +423 -0
- package/bin/ark-layer-match.mjs +25 -10
- package/bin/ark.mjs +51 -3
- package/bin/lib/agent-homes.mjs +1 -1
- package/bin/lib/analysis-engine.mjs +8 -8
- package/bin/lib/ark-order-sensors.mjs +103 -3
- package/bin/lib/config-extras.mjs +1 -0
- package/bin/lib/contract-smells.mjs +12 -6
- package/bin/lib/doctor-human.mjs +32 -7
- package/bin/lib/doctor-next-actions.mjs +21 -2
- package/bin/lib/gate-files.mjs +108 -22
- package/bin/lib/managed-upgrade.mjs +9 -1
- package/bin/lib/upgrade-command.mjs +17 -4
- package/dist/{configTypes-0eHpocR3.d.ts → configTypes-j7so8B4O.d.ts} +12 -0
- package/dist/{diagnosticCatalog-wDAH08gH.d.ts → diagnosticCatalog-BrkOiwCk.d.ts} +3 -3
- package/dist/eslint/index.cjs +5 -5
- package/dist/eslint/index.d.ts +6 -4
- package/dist/eslint/index.js +5 -5
- package/dist/index.cjs +30 -30
- package/dist/index.d.ts +13 -4
- package/dist/index.js +31 -31
- package/dist/nestjs/index.cjs +5 -5
- package/dist/nestjs/index.d.ts +3 -3
- package/dist/nestjs/index.js +5 -5
- package/dist/order/index.cjs +1 -1
- package/dist/order/index.d.ts +6 -2
- package/dist/order/index.js +1 -1
- package/dist/runtime/index.cjs +15 -15
- package/dist/runtime/index.d.ts +6 -6
- package/dist/runtime/index.js +15 -15
- package/dist/{types-BK47clMl.d.ts → types-Djbs3KjE.d.ts} +1 -1
- package/dist/{types-CwZ_oz1N.d.ts → types-tGhZUiGX.d.ts} +106 -2
- package/docs/README.md +13 -4
- package/docs/agent-guide.md +38 -2
- package/docs/ai-gates.md +13 -1
- package/docs/arkorder.md +41 -8
- package/docs/configuration.md +47 -12
- package/docs/develop.md +17 -8
- package/docs/enthusiast/README.md +13 -2
- package/docs/package-surface.md +20 -6
- package/docs/product-voice.md +25 -2
- package/docs/use.md +11 -3
- package/package.json +3 -1
- package/schemas/ark.config.schema.json +9 -0
- package/server.json +2 -2
- package/templates/agent-skills/README.md +1 -1
- package/templates/agent-skills/ark-adopt/SKILL.md +1 -0
- package/templates/agent-skills/ark-autopilot/SKILL.md +1 -1
- package/templates/agent-skills/ark-contract/SKILL.md +1 -1
- package/templates/agent-skills/ark-explore/SKILL.md +2 -2
- package/templates/agent-skills/ark-place/SKILL.md +1 -0
- package/templates/skills/ark-adopt.md +1 -0
- package/templates/skills/ark-autopilot.md +1 -1
- package/templates/skills/ark-contract.md +1 -1
- package/templates/skills/ark-explore.md +2 -2
- package/templates/skills/ark-place.md +1 -0
package/bin/ark-layer-match.mjs
CHANGED
|
@@ -362,15 +362,27 @@ export function crossSliceEdgeAllowed(allowedCrossSlice, fromSlice, toSlice) {
|
|
|
362
362
|
* Fail-closed stays fail-closed: absent evidence denies. What changed in 4.8.4
|
|
363
363
|
* is what counts as evidence — a declared shared root, or a declared directed
|
|
364
364
|
* cross-slice edge, is the repo telling us its design, so it is no longer
|
|
365
|
-
* "unclassifiable". Order: no
|
|
366
|
-
*
|
|
365
|
+
* "unclassifiable". Order: no fromPath → no slice folders → intent (no toPath):
|
|
366
|
+
* shared-root allow / slice fail-closed → a side that is neither in a slice nor
|
|
367
|
+
* declared shared → same slice → declared cross edge → deny.
|
|
368
|
+
*
|
|
369
|
+
* Intent/event names are not files. Callers pass fromPath only and must not
|
|
370
|
+
* invent a toPath (that would mis-slice). A declared shared root is classified
|
|
371
|
+
* the same way as on import edges.
|
|
367
372
|
*/
|
|
368
373
|
export function peerIsolationDecision(input) {
|
|
369
|
-
if (!input.fromPath
|
|
374
|
+
if (!input.fromPath)
|
|
370
375
|
return { denied: true, reason: 'missing-path' };
|
|
371
376
|
if (input.folderCount <= 0)
|
|
372
377
|
return { denied: true, reason: 'no-slice-folders' };
|
|
373
378
|
const fromClassified = Boolean(input.fromSlice) || input.fromShared === true;
|
|
379
|
+
if (!input.toPath) {
|
|
380
|
+
if (!fromClassified)
|
|
381
|
+
return { denied: true, reason: 'unclassifiable-path' };
|
|
382
|
+
if (!input.fromSlice)
|
|
383
|
+
return { denied: false };
|
|
384
|
+
return { denied: true, reason: 'missing-path' };
|
|
385
|
+
}
|
|
374
386
|
const toClassified = Boolean(input.toSlice) || input.toShared === true;
|
|
375
387
|
if (!fromClassified || !toClassified)
|
|
376
388
|
return { denied: true, reason: 'unclassifiable-path' };
|
|
@@ -387,8 +399,9 @@ export function peerIsolationDecision(input) {
|
|
|
387
399
|
/**
|
|
388
400
|
* Boolean face of {@link peerIsolationDecision}, kept for parity consumers.
|
|
389
401
|
*
|
|
390
|
-
* Fail-closed: missing
|
|
391
|
-
* side → deny.
|
|
402
|
+
* Fail-closed: missing fromPath, no classifiable folders, or unclassifiable
|
|
403
|
+
* either side → deny. Intent refs (no toPath) allow only a declared shared
|
|
404
|
+
* root. Same-slice → allow (return false). Cross-slice → deny unless the
|
|
392
405
|
* rule declared that directed edge.
|
|
393
406
|
*/
|
|
394
407
|
export function peerIsolationMustDeny(input) {
|
|
@@ -426,9 +439,11 @@ export function peerIsolationDenyExplanation(reason, context) {
|
|
|
426
439
|
* Same-layer is always allowed (historical short-circuit).
|
|
427
440
|
* - `peerIsolation: true` + `allowed: false`: deny only when importer and importee
|
|
428
441
|
* resolve to **different** slice ids (same or cross layer). Same-slice → allow.
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
442
|
+
* File imports pass fromPath + toPath. Intent references pass fromPath only.
|
|
443
|
+
* A declared shared root is classified (no denial). Missing fromPath, no slice
|
|
444
|
+
* folders, or unclassifiable slices → **fail-closed** (deny): isolation is
|
|
445
|
+
* configured, so insufficient evidence must not silently allow a possible
|
|
446
|
+
* cross-slice edge.
|
|
432
447
|
*/
|
|
433
448
|
export function findDeniedEdgeRule(rules, from, to, options) {
|
|
434
449
|
return findDeniedEdgeDecision(rules, from, to, options)?.rule;
|
|
@@ -448,8 +463,8 @@ export function findDeniedEdgeDecision(rules, from, to, options) {
|
|
|
448
463
|
const fromPath = options?.fromPath;
|
|
449
464
|
const toPath = options?.toPath;
|
|
450
465
|
const folders = resolveSliceFolders(rule, from, options?.layers);
|
|
451
|
-
const fromSlice = fromPath
|
|
452
|
-
const toSlice =
|
|
466
|
+
const fromSlice = fromPath ? sliceIdForPath(fromPath, folders) : undefined;
|
|
467
|
+
const toSlice = toPath ? sliceIdForPath(toPath, folders) : undefined;
|
|
453
468
|
const decision = peerIsolationDecision({
|
|
454
469
|
fromPath,
|
|
455
470
|
toPath,
|
package/bin/ark.mjs
CHANGED
|
@@ -39,6 +39,36 @@ import { setupUsage, setupUsageAll, upgradeUsage } from './lib/first-run-help.mj
|
|
|
39
39
|
|
|
40
40
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
41
41
|
const arkCheck = path.join(here, 'ark-check.mjs');
|
|
42
|
+
const arkDashboard = path.join(here, 'ark-dashboard.mjs');
|
|
43
|
+
const dashboardHelp = `arkgate dashboard (alias ark dashboard) — observability TUI.
|
|
44
|
+
Usage: arkgate dashboard [--url <snapshot-url>] [--interval <ms>]
|
|
45
|
+
Polls an ArkRun inspector; it does not start the kernel.`;
|
|
46
|
+
|
|
47
|
+
function withDashboardHelp(text, detailed) {
|
|
48
|
+
if (detailed) {
|
|
49
|
+
return text
|
|
50
|
+
.replace(
|
|
51
|
+
' arkgate agents-md [--root',
|
|
52
|
+
' arkgate dashboard [--url <snapshot-url>] [--interval <ms>]\n arkgate agents-md [--root'
|
|
53
|
+
)
|
|
54
|
+
.replace(
|
|
55
|
+
' agents-md Version-matched',
|
|
56
|
+
' dashboard ANSI observability TUI against a running ArkRun inspector (spawns ark-dashboard).\n agents-md Version-matched'
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return text.replace(
|
|
60
|
+
' arkgate-check --doctor status — one next step\n',
|
|
61
|
+
' arkgate-check --doctor status — one next step\n arkgate dashboard observability TUI (inspector)\n'
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function runDashboard(passthroughArgs) {
|
|
66
|
+
const result = spawnSync(process.execPath, [arkDashboard, ...passthroughArgs], {
|
|
67
|
+
stdio: 'inherit',
|
|
68
|
+
encoding: 'utf8',
|
|
69
|
+
});
|
|
70
|
+
return result.status ?? 1;
|
|
71
|
+
}
|
|
42
72
|
|
|
43
73
|
/**
|
|
44
74
|
* Day-zero architecture picture: freeze origin under `.ark/reports/` as soon as
|
|
@@ -93,6 +123,7 @@ function parseArgs(argv) {
|
|
|
93
123
|
help: false,
|
|
94
124
|
all: false,
|
|
95
125
|
version: false,
|
|
126
|
+
passthrough: [],
|
|
96
127
|
};
|
|
97
128
|
|
|
98
129
|
const requireValue = (flag, index) => {
|
|
@@ -147,7 +178,14 @@ function parseArgs(argv) {
|
|
|
147
178
|
else if (arg === '--help' || arg === '-h' || arg === 'help') args.help = true;
|
|
148
179
|
else if (arg === '--all') args.all = true;
|
|
149
180
|
else if (arg === '--version' || arg === '-V') args.version = true;
|
|
150
|
-
else if (!arg.startsWith('-') && args.command === undefined)
|
|
181
|
+
else if (!arg.startsWith('-') && args.command === undefined) {
|
|
182
|
+
args.command = arg;
|
|
183
|
+
// Dashboard owns its flags (--url/--interval); pass the rest through untouched.
|
|
184
|
+
if (arg === 'dashboard') {
|
|
185
|
+
args.passthrough = argv.slice(i + 1);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
151
189
|
else throw new Error(`Unknown argument: ${arg}. Run arkgate --help for usage.`);
|
|
152
190
|
}
|
|
153
191
|
|
|
@@ -782,11 +820,21 @@ async function main() {
|
|
|
782
820
|
console.log(upgradeUsage());
|
|
783
821
|
return 0;
|
|
784
822
|
}
|
|
823
|
+
if (args.command === 'dashboard' && args.passthrough.some((arg) => ['--help', '-h', 'help'].includes(arg))) {
|
|
824
|
+
console.log(dashboardHelp);
|
|
825
|
+
return 0;
|
|
826
|
+
}
|
|
785
827
|
if (args.help || !args.command) {
|
|
786
|
-
console.log(
|
|
828
|
+
console.log(
|
|
829
|
+
withDashboardHelp(args.all ? setupUsageAll() : setupUsage(), Boolean(args.all))
|
|
830
|
+
);
|
|
787
831
|
return 0;
|
|
788
832
|
}
|
|
789
833
|
|
|
834
|
+
if (args.command === 'dashboard') {
|
|
835
|
+
return runDashboard(args.passthrough);
|
|
836
|
+
}
|
|
837
|
+
|
|
790
838
|
if (args.requireWriteHook && !['start', 'init'].includes(args.command)) {
|
|
791
839
|
console.error('--require-write-hook is supported by ark start and ark init.');
|
|
792
840
|
return 2;
|
|
@@ -913,7 +961,7 @@ async function main() {
|
|
|
913
961
|
}
|
|
914
962
|
|
|
915
963
|
console.error(`Unknown command: ${args.command}`);
|
|
916
|
-
console.error(setupUsage());
|
|
964
|
+
console.error(withDashboardHelp(setupUsage(), false));
|
|
917
965
|
return 2;
|
|
918
966
|
}
|
|
919
967
|
|
package/bin/lib/agent-homes.mjs
CHANGED
|
@@ -108,7 +108,7 @@ function usesDefaultHome(spec, env, homeDir) {
|
|
|
108
108
|
|
|
109
109
|
function skillsDirFor(host, env = process.env) {
|
|
110
110
|
const spec = HOSTS[host];
|
|
111
|
-
return path.join(resolveHomeDir(spec, env), 'skills');
|
|
111
|
+
return path.join(resolveHomeDir(spec, env, os.homedir()), 'skills');
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
function readHomeCatalogFloor(skillsDir) {
|