@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.
@@ -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, planMcpTargetGroups, } from "@agentxm/extension-workspace";
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 = planMcpTargetGroups({
48
- configuredAgentIds: [...args.configuredAgents],
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,
@@ -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.5",
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-sources": "^0.28.5",
41
- "@agentxm/registry-protocol": "^0.28.5",
42
- "@agentxm/workspace-state": "^0.28.5",
43
- "@agentxm/workspace-operations": "^0.28.5",
44
- "@agentxm/extension-model": "^0.28.5",
45
- "@agentxm/extension-workspace": "^0.28.5"
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.5"
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