@lexq/cli 0.1.57 → 0.1.59

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/index.js CHANGED
@@ -2129,7 +2129,8 @@ function registerAnalyticsCommands(program) {
2129
2129
  "after",
2130
2130
  dedent8`
2131
2131
 
2132
- Shows progress, match rate, metric comparison (if baseline set), and per-rule stats.
2132
+ Shows progress, match rate, metric comparison and its change distribution (if a
2133
+ baseline is set), and per-rule stats.
2133
2134
 
2134
2135
  Example:
2135
2136
  $ lexq analytics simulation status --id <simId> --format table
@@ -2172,6 +2173,21 @@ function registerAnalyticsCommands(program) {
2172
2173
  console.log(
2173
2174
  `Change: ${data.metricSummary.deltaPercentage > 0 ? "+" : ""}${data.metricSummary.deltaPercentage.toFixed(1)}%`
2174
2175
  );
2176
+ const dist = data.metricSummary.distribution;
2177
+ if (dist) {
2178
+ console.log(`
2179
+ \u2500\u2500 Distribution \u2500\u2500`);
2180
+ console.log(`Changed: ${dist.changedRecords}`);
2181
+ console.log(`Increased: ${dist.increasedRecords}`);
2182
+ console.log(`Decreased: ${dist.decreasedRecords}`);
2183
+ console.log(
2184
+ `Largest +: ${dist.largestIncrease === null ? "\u2013" : `${signPrefix(dist.largestIncrease)}${String(dist.largestIncrease)}`}`
2185
+ );
2186
+ console.log(
2187
+ `Largest -: ${dist.largestDecrease === null ? "\u2013" : String(dist.largestDecrease)}`
2188
+ );
2189
+ console.log(`Measured: ${dist.measuredRecords}`);
2190
+ }
2175
2191
  }
2176
2192
  if (data.policyImpact?.comparison) {
2177
2193
  const diff = data.policyImpact.comparison.difference;
@@ -3425,14 +3441,18 @@ function registerGroupTools(server, callApi) {
3425
3441
  "lexq_groups_create",
3426
3442
  {
3427
3443
  title: "Create Policy Group",
3428
- description: "Create a new policy group. Requires name. Priority is auto-assigned (appended last, tenant-wide); use lexq_groups_reorder to change order. Optionally set conflict resolution, activation group, and description. Groups sharing an activationGroup must share the same activationMode / activationStrategy / executionLimit.",
3444
+ description: "Create a new policy group. Requires name. Priority is auto-assigned (appended last, tenant-wide); use lexq_groups_reorder to change order. Optionally set conflict resolution, activation group, and description. Policy groups that share an activationGroup form a cluster and must share the same activationMode / activationStrategy / executionLimit; executionLimit is how many of those groups run, not how many rules.",
3429
3445
  inputSchema: {
3430
3446
  name: z.string().describe("Group name (unique among non-ARCHIVED)"),
3431
3447
  description: z.string().optional().describe("Group description"),
3432
3448
  activationMode: z.enum(ConflictResolutionMode).optional().describe("Conflict resolution mode"),
3433
- activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Strategy when mode is EXCLUSIVE or MAX_N"),
3434
- executionLimit: z.number().int().min(1).optional().describe("Max rule executions (required when mode is MAX_N)"),
3435
- activationGroup: z.string().optional().describe("Activation group name")
3449
+ activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Ranking used to pick the winning groups when mode is EXCLUSIVE or MAX_N"),
3450
+ executionLimit: z.number().int().min(1).optional().describe(
3451
+ "How many policy groups sharing this activationGroup may run (required when mode is MAX_N). Counts groups, not rules: every rule of a winning group runs."
3452
+ ),
3453
+ activationGroup: z.string().optional().describe(
3454
+ "Activation group (Execution Group) cluster key. Policy groups sharing this key compete, and group priority picks the winners."
3455
+ )
3436
3456
  }
3437
3457
  },
3438
3458
  async (args) => {
@@ -3457,10 +3477,14 @@ function registerGroupTools(server, callApi) {
3457
3477
  name: z.string().optional().describe("New name"),
3458
3478
  description: z.string().optional().describe("New description"),
3459
3479
  status: z.enum(["ACTIVE", "DISABLED"]).optional().describe("Status (DISABLED = emergency stop)"),
3460
- activationGroup: z.string().optional().describe("Activation group (Execution Group) cluster key"),
3480
+ activationGroup: z.string().optional().describe(
3481
+ "Activation group (Execution Group) cluster key. Policy groups sharing this key compete, and group priority picks the winners."
3482
+ ),
3461
3483
  activationMode: z.enum(ConflictResolutionMode).optional().describe("Conflict resolution mode"),
3462
- activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Strategy"),
3463
- executionLimit: z.number().int().min(1).optional().describe("Max rule executions")
3484
+ activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Ranking used to pick the winning groups"),
3485
+ executionLimit: z.number().int().min(1).optional().describe(
3486
+ "How many policy groups sharing this activationGroup may run. Counts groups, not rules."
3487
+ )
3464
3488
  }
3465
3489
  },
3466
3490
  async ({ groupId, ...body }) => callApi("PUT", `policy-groups/${groupId}`, { body })
@@ -58,14 +58,18 @@ function registerGroupTools(server, callApi) {
58
58
  "lexq_groups_create",
59
59
  {
60
60
  title: "Create Policy Group",
61
- description: "Create a new policy group. Requires name. Priority is auto-assigned (appended last, tenant-wide); use lexq_groups_reorder to change order. Optionally set conflict resolution, activation group, and description. Groups sharing an activationGroup must share the same activationMode / activationStrategy / executionLimit.",
61
+ description: "Create a new policy group. Requires name. Priority is auto-assigned (appended last, tenant-wide); use lexq_groups_reorder to change order. Optionally set conflict resolution, activation group, and description. Policy groups that share an activationGroup form a cluster and must share the same activationMode / activationStrategy / executionLimit; executionLimit is how many of those groups run, not how many rules.",
62
62
  inputSchema: {
63
63
  name: z.string().describe("Group name (unique among non-ARCHIVED)"),
64
64
  description: z.string().optional().describe("Group description"),
65
65
  activationMode: z.enum(ConflictResolutionMode).optional().describe("Conflict resolution mode"),
66
- activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Strategy when mode is EXCLUSIVE or MAX_N"),
67
- executionLimit: z.number().int().min(1).optional().describe("Max rule executions (required when mode is MAX_N)"),
68
- activationGroup: z.string().optional().describe("Activation group name")
66
+ activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Ranking used to pick the winning groups when mode is EXCLUSIVE or MAX_N"),
67
+ executionLimit: z.number().int().min(1).optional().describe(
68
+ "How many policy groups sharing this activationGroup may run (required when mode is MAX_N). Counts groups, not rules: every rule of a winning group runs."
69
+ ),
70
+ activationGroup: z.string().optional().describe(
71
+ "Activation group (Execution Group) cluster key. Policy groups sharing this key compete, and group priority picks the winners."
72
+ )
69
73
  }
70
74
  },
71
75
  async (args) => {
@@ -90,10 +94,14 @@ function registerGroupTools(server, callApi) {
90
94
  name: z.string().optional().describe("New name"),
91
95
  description: z.string().optional().describe("New description"),
92
96
  status: z.enum(["ACTIVE", "DISABLED"]).optional().describe("Status (DISABLED = emergency stop)"),
93
- activationGroup: z.string().optional().describe("Activation group (Execution Group) cluster key"),
97
+ activationGroup: z.string().optional().describe(
98
+ "Activation group (Execution Group) cluster key. Policy groups sharing this key compete, and group priority picks the winners."
99
+ ),
94
100
  activationMode: z.enum(ConflictResolutionMode).optional().describe("Conflict resolution mode"),
95
- activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Strategy"),
96
- executionLimit: z.number().int().min(1).optional().describe("Max rule executions")
101
+ activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Ranking used to pick the winning groups"),
102
+ executionLimit: z.number().int().min(1).optional().describe(
103
+ "How many policy groups sharing this activationGroup may run. Counts groups, not rules."
104
+ )
97
105
  }
98
106
  },
99
107
  async ({ groupId, ...body }) => callApi("PUT", `policy-groups/${groupId}`, { body })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lexq/cli",
3
- "version": "0.1.57",
3
+ "version": "0.1.59",
4
4
  "description": "LexQ CLI — manage policies, simulate rules, and deploy from the terminal. Built for humans and AI agents.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -328,7 +328,15 @@ lexq analytics simulation export --id <simulationId> --as csv --output results.c
328
328
  "baselineValue": 5000000,
329
329
  "simulatedValue": 4500000,
330
330
  "delta": -500000,
331
- "deltaPercentage": -10.0
331
+ "deltaPercentage": -10.0,
332
+ "distribution": {
333
+ "changedRecords": 8700,
334
+ "increasedRecords": 400,
335
+ "decreasedRecords": 8300,
336
+ "largestIncrease": 1500,
337
+ "largestDecrease": -2000,
338
+ "measuredRecords": 8300
339
+ }
332
340
  },
333
341
  "policyImpact": {
334
342
  "policyVersionId": "...",