@agentxm/workspace-lint 0.28.5 → 0.28.6
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/dist/src/catalog/workspace/mcps-agent-drift.js +3 -4
- package/dist/src/catalog/workspace/projection-contributors-rendered.d.ts +11 -0
- package/dist/src/catalog/workspace/projection-contributors-rendered.js +30 -0
- package/dist/src/catalog/workspace.js +3 -3
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/package.json +8 -8
- package/dist/src/catalog/workspace/mcps-shared-target-compatible.d.ts +0 -4
- package/dist/src/catalog/workspace/mcps-shared-target-compatible.js +0 -72
|
@@ -3,7 +3,7 @@ import * as Option from "effect/Option";
|
|
|
3
3
|
import * as Result from "effect/Result";
|
|
4
4
|
import { CONFIGURABLE_AGENTS_BY_ID, } from "@agentxm/extension-model/unstable/agent-capabilities";
|
|
5
5
|
import { isAxmManagedMcpEntry } from "@agentxm/workspace-state";
|
|
6
|
-
import { diffAgentEntry, inferInlineRemoteTransport, projectExpectedEntry, resolveSharedMcpTarget,
|
|
6
|
+
import { diffAgentEntry, inferInlineRemoteTransport, projectExpectedEntry, resolveSharedMcpTarget, groupConfiguredMcpTargets, } from "@agentxm/extension-workspace";
|
|
7
7
|
const RULE_ID = "workspace/mcps-agent-drift";
|
|
8
8
|
const relativeToRoot = (root, file) => {
|
|
9
9
|
if (file === root)
|
|
@@ -44,9 +44,8 @@ const configFileMatchesTarget = (configFile, targetPath) => configFile === targe
|
|
|
44
44
|
const checkActual = (args) => {
|
|
45
45
|
if (args.actual.config === null || args.actual.configFile === null)
|
|
46
46
|
return undefined;
|
|
47
|
-
const groups =
|
|
48
|
-
|
|
49
|
-
entry: args.entry,
|
|
47
|
+
const groups = groupConfiguredMcpTargets({
|
|
48
|
+
agentIds: [...args.configuredAgents],
|
|
50
49
|
scope: args.row.key.scope,
|
|
51
50
|
});
|
|
52
51
|
const agentId = args.actual.origin._tag === "agent-mcp-config" ? args.actual.origin.agentId : undefined;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ProjectionInvariantFact } from "@agentxm/extension-workspace";
|
|
2
|
+
import type { WorkspaceRuleContext } from "../../workspace-context.js";
|
|
3
|
+
import type { AdvisoryRule, LintFinding } from "@agentxm/registry-protocol/unstable/lint/rule";
|
|
4
|
+
/**
|
|
5
|
+
* A generated file that omits a desired contributor is still written, so no
|
|
6
|
+
* command fails on it. This rule is the durable reminder: it reports each
|
|
7
|
+
* omission, and why, until the package is fixed or removed.
|
|
8
|
+
*/
|
|
9
|
+
export declare const projectionContributorsRenderedRule: AdvisoryRule<WorkspaceRuleContext>;
|
|
10
|
+
export declare const findingsForProjectionExclusions: (facts: ReadonlyArray<ProjectionInvariantFact>) => ReadonlyArray<LintFinding>;
|
|
11
|
+
//# sourceMappingURL=projection-contributors-rendered.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { formatProjectionExclusion, } from "@agentxm/extension-workspace";
|
|
3
|
+
import { EMPTY_LINT_FINDINGS } from "./helpers/empty.js";
|
|
4
|
+
const RULE_ID = "workspace/projection-contributors-rendered";
|
|
5
|
+
/**
|
|
6
|
+
* A generated file that omits a desired contributor is still written, so no
|
|
7
|
+
* command fails on it. This rule is the durable reminder: it reports each
|
|
8
|
+
* omission, and why, until the package is fixed or removed.
|
|
9
|
+
*/
|
|
10
|
+
export const projectionContributorsRenderedRule = {
|
|
11
|
+
id: RULE_ID,
|
|
12
|
+
description: "Every desired contributor reaches the AXM-managed file it belongs in.",
|
|
13
|
+
kind: "advisory",
|
|
14
|
+
severity: "warning",
|
|
15
|
+
check: (context) => Effect.gen(function* () {
|
|
16
|
+
if (context.projections === undefined)
|
|
17
|
+
return EMPTY_LINT_FINDINGS;
|
|
18
|
+
return findingsForProjectionExclusions(yield* context.projections.facts);
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
export const findingsForProjectionExclusions = (facts) => facts.flatMap((fact) => (fact.observation.exclusions ?? []).map((exclusion) => ({
|
|
22
|
+
kind: "advisory",
|
|
23
|
+
ruleId: RULE_ID,
|
|
24
|
+
severity: "warning",
|
|
25
|
+
message: formatProjectionExclusion({
|
|
26
|
+
exclusion,
|
|
27
|
+
targetFile: fact.subject.path.split("#", 1)[0] ?? fact.subject.path,
|
|
28
|
+
}),
|
|
29
|
+
})));
|
|
30
|
+
//# sourceMappingURL=projection-contributors-rendered.js.map
|
|
@@ -21,6 +21,7 @@ import { instructionsTargetCurrentRule } from "./workspace/instructions-target-c
|
|
|
21
21
|
import { instructionsTargetUnownedRule } from "./workspace/instructions-target-unowned.js";
|
|
22
22
|
import { instructionsTargetStaleRule } from "./workspace/instructions-target-stale.js";
|
|
23
23
|
import { projectionOwnershipValidRule } from "./workspace/projection-ownership-valid.js";
|
|
24
|
+
import { projectionContributorsRenderedRule } from "./workspace/projection-contributors-rendered.js";
|
|
24
25
|
import { instructionsAgentSupportedRule } from "./workspace/instructions-agent-supported.js";
|
|
25
26
|
import { instructionsGitignoreCurrentRule } from "./workspace/instructions-gitignore-current.js";
|
|
26
27
|
import { skillsDeclarationsValidRule } from "./workspace/skills-declarations-valid.js";
|
|
@@ -33,7 +34,6 @@ import { configuredButNotInstalledRule } from "./workspace/configured-but-not-in
|
|
|
33
34
|
import { mcpServerNoSecretLiteralRule } from "./workspace/mcps-no-secret-literal.js";
|
|
34
35
|
import { mcpServerTransportExclusivityRule } from "./workspace/mcps-transport-exclusivity.js";
|
|
35
36
|
import { mcpServerAgentDriftRule } from "./workspace/mcps-agent-drift.js";
|
|
36
|
-
import { mcpServerSharedTargetCompatibleRule } from "./workspace/mcps-shared-target-compatible.js";
|
|
37
37
|
import { mcpServerAgentOrphanedRule } from "./workspace/mcps-agent-orphaned.js";
|
|
38
38
|
import { desiredStateReconcilableRule } from "./workspace/desired-state-reconcilable.js";
|
|
39
39
|
import { knowledgeStateValidRule } from "./workspace/knowledge-state-valid.js";
|
|
@@ -70,7 +70,6 @@ export const repositoryWorkspaceRules = [
|
|
|
70
70
|
knowledgeStateValidRule,
|
|
71
71
|
mcpServerTransportExclusivityRule,
|
|
72
72
|
mcpServerNoSecretLiteralRule,
|
|
73
|
-
mcpServerSharedTargetCompatibleRule,
|
|
74
73
|
// Lockfile aligned (configured).
|
|
75
74
|
skillsLockfileAlignedRule,
|
|
76
75
|
// Integrity intact (configured + implicit).
|
|
@@ -88,6 +87,7 @@ export const liveOnlyWorkspaceRules = [
|
|
|
88
87
|
instructionsTargetUnownedRule,
|
|
89
88
|
instructionsTargetStaleRule,
|
|
90
89
|
projectionOwnershipValidRule,
|
|
90
|
+
projectionContributorsRenderedRule,
|
|
91
91
|
hookOwnershipAmbiguousRule,
|
|
92
92
|
managedFileUnownedRule,
|
|
93
93
|
mcpServerAgentDriftRule,
|
|
@@ -114,6 +114,7 @@ export const workspaceRules = [
|
|
|
114
114
|
instructionsAgentSupportedRule,
|
|
115
115
|
instructionsGitignoreCurrentRule,
|
|
116
116
|
projectionOwnershipValidRule,
|
|
117
|
+
projectionContributorsRenderedRule,
|
|
117
118
|
hookOwnershipAmbiguousRule,
|
|
118
119
|
managedFileUnownedRule,
|
|
119
120
|
skillsDeclarationsValidRule,
|
|
@@ -122,7 +123,6 @@ export const workspaceRules = [
|
|
|
122
123
|
knowledgeStateValidRule,
|
|
123
124
|
mcpServerTransportExclusivityRule,
|
|
124
125
|
mcpServerNoSecretLiteralRule,
|
|
125
|
-
mcpServerSharedTargetCompatibleRule,
|
|
126
126
|
mcpServerAgentDriftRule,
|
|
127
127
|
mcpServerAgentOrphanedRule,
|
|
128
128
|
skillsLockfileAlignedRule,
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export type { WorkspaceRuleContext, WorkspaceSubject } from "./workspace-context
|
|
|
2
2
|
export { CATALOG_GROUP_ORDER, LIVE_ONLY_LINT_CATALOGS, LINT_CATALOGS, REPOSITORY_LINT_CATALOGS, emptyCatalogRuleContexts, lintCatalogsForView, type CatalogContext, type CatalogGroup, type CatalogRuleContexts, type LintView, } from "./catalog-contexts.js";
|
|
3
3
|
export { LintInputSchema, LintJsonDocumentSchema, LintJsonFindingSchema, type LintInput, type LintJsonDocument, type LintJsonFinding, } from "./json-schema.js";
|
|
4
4
|
export { findingsForProjectionOwnership } from "./catalog/workspace/projection-ownership-valid.js";
|
|
5
|
+
export { findingsForProjectionExclusions } from "./catalog/workspace/projection-contributors-rendered.js";
|
|
5
6
|
export { collectRenderedFindings, countFindings, detectPublishGateDrift, evaluateAllCatalogs, renderFindingsText, resolveLintExitCategory, summarizeEvaluations, toLintHumanBlocks, toLintJsonDocument, type FindingCounts, type GroupEvaluations, type LintHumanBlock, type LintHumanDiagnostic, type LintHumanReporter, type LintExitCategory, type LintSummary, type RenderFindingsArgs, type RenderedFinding, } from "./cli.js";
|
|
6
7
|
export { allCatalogErrorRuleIds, allCatalogRuleMetadata, allCatalogRuleIds, buildAcquiredInstalledSkillInfo, buildInstalledPackInfo, buildLintWorkspace, buildNativeInstalledSkillInfo, acquiredSkillDisplayRoot, registryNativeSkillDisplayRoot, registryPackDisplayRoot, liveOnlyWorkspaceRules, repositoryWorkspaceRules, workspaceRules, type BuildInstalledPackInfoArgs, type BuildAcquiredInstalledSkillInfoArgs, type BuildInstalledSkillInfoNativeArgs, type BuildLintWorkspaceArgs, type LintWorkspace, type LintWorkspaceView, } from "./catalog/index.js";
|
|
7
8
|
export { LintStagingFailed } from "./run/errors.js";
|
package/dist/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { CATALOG_GROUP_ORDER, LIVE_ONLY_LINT_CATALOGS, LINT_CATALOGS, REPOSITORY
|
|
|
4
4
|
// `--json` document schema + derived types
|
|
5
5
|
export { LintInputSchema, LintJsonDocumentSchema, LintJsonFindingSchema, } from "./json-schema.js";
|
|
6
6
|
export { findingsForProjectionOwnership } from "./catalog/workspace/projection-ownership-valid.js";
|
|
7
|
+
export { findingsForProjectionExclusions } from "./catalog/workspace/projection-contributors-rendered.js";
|
|
7
8
|
// Lint runner (Phase 5) — reusable primitives the `axm lint` CLI composes
|
|
8
9
|
// over. Keeps the CLI command file a thin surface over flag parsing and
|
|
9
10
|
// rendering per task 5.11.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentxm/workspace-lint",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.6",
|
|
4
4
|
"description": "AXM workspace-lint feature: workspace facts, lint rules, findings, normalization, and bounded fix planning for the axm CLI. Unstable and unsupported — use the axm.sh CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-MIT",
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"effect": "4.0.0-rc.112",
|
|
40
|
-
"@agentxm/extension-
|
|
41
|
-
"@agentxm/
|
|
42
|
-
"@agentxm/workspace
|
|
43
|
-
"@agentxm/
|
|
44
|
-
"@agentxm/
|
|
45
|
-
"@agentxm/
|
|
40
|
+
"@agentxm/extension-model": "^0.28.6",
|
|
41
|
+
"@agentxm/extension-sources": "^0.28.6",
|
|
42
|
+
"@agentxm/extension-workspace": "^0.28.6",
|
|
43
|
+
"@agentxm/registry-protocol": "^0.28.6",
|
|
44
|
+
"@agentxm/workspace-state": "^0.28.6",
|
|
45
|
+
"@agentxm/workspace-operations": "^0.28.6"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
@@ -51,6 +51,6 @@
|
|
|
51
51
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
52
52
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
53
53
|
"vitest": "^4.1.10",
|
|
54
|
-
"@agentxm/agent-integration": "^0.28.
|
|
54
|
+
"@agentxm/agent-integration": "^0.28.6"
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { WorkspaceRuleContext } from "../../workspace-context.js";
|
|
2
|
-
import type { AdvisoryRule } from "@agentxm/registry-protocol/unstable/lint/rule";
|
|
3
|
-
export declare const mcpServerSharedTargetCompatibleRule: AdvisoryRule<WorkspaceRuleContext>;
|
|
4
|
-
//# sourceMappingURL=mcps-shared-target-compatible.d.ts.map
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import * as Effect from "effect/Effect";
|
|
2
|
-
import * as Option from "effect/Option";
|
|
3
|
-
import * as Result from "effect/Result";
|
|
4
|
-
import { inferInlineRemoteTransport, resolveSharedMcpTarget, groupConfiguredMcpTargets, } from "@agentxm/extension-workspace";
|
|
5
|
-
import { isMcpServerApplicableToAgent } from "@agentxm/workspace-state";
|
|
6
|
-
import { settingsDisplayPath } from "./display-paths.js";
|
|
7
|
-
const RULE_ID = "workspace/mcps-shared-target-compatible";
|
|
8
|
-
const transportFor = (entry) => {
|
|
9
|
-
if (entry.command !== undefined)
|
|
10
|
-
return "stdio";
|
|
11
|
-
if (entry.url === undefined)
|
|
12
|
-
return undefined;
|
|
13
|
-
const inference = inferInlineRemoteTransport(entry.url);
|
|
14
|
-
return inference._tag === "supported" ? inference.transport : undefined;
|
|
15
|
-
};
|
|
16
|
-
const findingFor = (serverName, path, reason, settingsPath) => ({
|
|
17
|
-
kind: "advisory",
|
|
18
|
-
ruleId: RULE_ID,
|
|
19
|
-
severity: "error",
|
|
20
|
-
message: "MCP server '" +
|
|
21
|
-
serverName +
|
|
22
|
-
"' projects a value that another configured agent rejects in shared target '" +
|
|
23
|
-
path +
|
|
24
|
-
"'. " +
|
|
25
|
-
reason +
|
|
26
|
-
" Update the configured agents or their MCP compatibility metadata before syncing.",
|
|
27
|
-
location: { file: settingsPath },
|
|
28
|
-
});
|
|
29
|
-
export const mcpServerSharedTargetCompatibleRule = {
|
|
30
|
-
id: RULE_ID,
|
|
31
|
-
description: "Configured agents accept the values projected into shared MCP config targets.",
|
|
32
|
-
kind: "advisory",
|
|
33
|
-
severity: "error",
|
|
34
|
-
check: (context) => Effect.gen(function* () {
|
|
35
|
-
const settings = yield* Effect.result(context.workspace.state.settings);
|
|
36
|
-
if (Result.isFailure(settings) || Option.isNone(settings.success))
|
|
37
|
-
return [];
|
|
38
|
-
const agentIds = settings.success.value.agents ?? [];
|
|
39
|
-
const entries = settings.success.value.mcpServers ?? {};
|
|
40
|
-
const groups = groupConfiguredMcpTargets({
|
|
41
|
-
agentIds,
|
|
42
|
-
scope: context.subject.scope,
|
|
43
|
-
}).filter((group) => group.members.length > 1);
|
|
44
|
-
return Object.entries(entries).flatMap(([serverName, entry]) => {
|
|
45
|
-
const transport = transportFor(entry);
|
|
46
|
-
if (transport === undefined)
|
|
47
|
-
return [];
|
|
48
|
-
return groups.flatMap((group) => {
|
|
49
|
-
const applicableAgentIds = group.members
|
|
50
|
-
.filter((member) => isMcpServerApplicableToAgent(entry, member.agentId))
|
|
51
|
-
.map((member) => member.agentId);
|
|
52
|
-
if (applicableAgentIds.length === 0)
|
|
53
|
-
return [];
|
|
54
|
-
if (applicableAgentIds.length < group.members.length) {
|
|
55
|
-
const untargetedAgentIds = group.members
|
|
56
|
-
.filter((member) => !isMcpServerApplicableToAgent(entry, member.agentId))
|
|
57
|
-
.map((member) => member.agentId);
|
|
58
|
-
return [
|
|
59
|
-
findingFor(serverName, group.path, `MCP target policy cannot be represented; targeted agents ${applicableAgentIds.join(", ")} share it with untargeted agents ${untargetedAgentIds.join(", ")}.`, settingsDisplayPath(context.subject.scope)),
|
|
60
|
-
];
|
|
61
|
-
}
|
|
62
|
-
const resolution = resolveSharedMcpTarget({ members: group.members, transport });
|
|
63
|
-
return resolution._tag === "conflict"
|
|
64
|
-
? [
|
|
65
|
-
findingFor(serverName, resolution.path, resolution.reason, settingsDisplayPath(context.subject.scope)),
|
|
66
|
-
]
|
|
67
|
-
: [];
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
}),
|
|
71
|
-
};
|
|
72
|
-
//# sourceMappingURL=mcps-shared-target-compatible.js.map
|