@commonlyai/cli 0.1.13 → 0.1.15

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/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@commonlyai/cli",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "license": "Apache-2.0",
5
- "description": "The Commonly CLI connect agents, manage pods, iterate fast",
5
+ "description": "The Commonly CLI \u2014 connect agents, manage pods, iterate fast",
6
6
  "type": "module",
7
7
  "main": "./src/index.js",
8
8
  "bin": {
@@ -859,7 +859,7 @@ export const performRun = ({
859
859
  // Recording a human trigger sets the streak to 0, so this call and the
860
860
  // completion-time one are idempotent with each other.
861
861
  if (trigger === 'human') cascadeGovernor.record(eventPodId, trigger);
862
- const admission = cascadeGovernor.admit(eventPodId, trigger, event.type);
862
+ const admission = cascadeGovernor.admit(eventPodId, trigger, event.type, event.payload);
863
863
  if (!admission.allowed) {
864
864
  // Name the MESSAGE, not just the pod. Without this the refusal is silent at
865
865
  // three ends, not two: the mentioning agent gets no signal its mention died,
@@ -45,6 +45,14 @@ export const CLAIMABLE_EVENT_TYPES = new Set([
45
45
  */
46
46
  export const classifyTrigger = (event, recentMessages) => {
47
47
  const p = event?.payload || {};
48
+ // The third pricing branch (#1044, fable 55845). Kernel-found work is not
49
+ // agent churn and must not price as it: counted as 'agent' it eats cascade
50
+ // budget exactly when the board is busiest; counted as 'human' it CLEARS the
51
+ // brake on unrelated cascades. 'kernel' is neutral like 'unknown' — no
52
+ // count, no reset — but chosen on purpose rather than fallen into, and the
53
+ // refusal/boot logs can say so. Checked before dmKind: triggerAuthor is the
54
+ // honest field (#1018) and wins where both appear.
55
+ if (p.triggerAuthor === 'kernel') return 'kernel';
48
56
  if (p.dmKind === 'agent-agent') return 'agent';
49
57
  if (p.dmKind === 'user-agent') return 'human';
50
58
  if (!p.messageId || !Array.isArray(recentMessages)) return 'unknown';
@@ -62,6 +70,19 @@ export const classifyTrigger = (event, recentMessages) => {
62
70
  // race is a free stand-down.
63
71
  export const ADDRESSED_EVENT_TYPES = new Set(['chat.mention', 'thread.mention', 'dm.message']);
64
72
 
73
+ // These are the two event types the kernel's bot-to-bot mention dampener
74
+ // bounds as one shared budget. Keep the wrapper out of that same loop's
75
+ // admission path: named seats need to respond even when broadcasts have
76
+ // exhausted their cascade budget. The backend cannot be a runtime import of
77
+ // the published CLI, so cli/__tests__/mention-event-types.contract.test.mjs
78
+ // imports both modules and pins the two lists together.
79
+ //
80
+ // Agent-DM wakes also arrive as chat.mention, but carry payload.dmKind. They
81
+ // stay on this governor's bounded path: event type alone does not identify the
82
+ // producer that owns the kernel mention budget. dm.message is legacy consumer
83
+ // vocabulary and remains on that same ordinary addressed-grace path.
84
+ export const MENTION_EVENT_TYPES = new Set(['chat.mention', 'thread.mention']);
85
+
65
86
  // ── cascade governor ────────────────────────────────────────────────────────
66
87
 
67
88
  export const CASCADE_DEFAULTS = Object.freeze({
@@ -213,9 +234,24 @@ export const createCascadeGovernor = ({
213
234
  };
214
235
 
215
236
  return {
216
- admit(podId, trigger, eventType) {
237
+ admit(podId, trigger, eventType, payload = {}) {
217
238
  if (trigger !== 'agent') return { allowed: true, streak: 0, addressed: false };
218
239
  const s = stateFor(podId);
240
+ const addressed = ADDRESSED_EVENT_TYPES.has(eventType);
241
+ if (MENTION_EVENT_TYPES.has(eventType) && !payload?.dmKind) {
242
+ // Named mentions are bounded upstream by the kernel's shared
243
+ // bot-to-bot mention dampener. A DM emits chat.mention too, but its
244
+ // dmKind identifies a different producer, so it remains locally
245
+ // bounded. Every admitted turn still reaches record() after it
246
+ // completes, consuming broadcast liveness rather than creating an
247
+ // unmetered second loop.
248
+ return {
249
+ allowed: true,
250
+ streak: s.streak,
251
+ addressed,
252
+ graceApplied: false,
253
+ };
254
+ }
219
255
  // Being NAMED outranks a mechanical brake — the same judgement the claim
220
256
  // path already makes forty lines down in agent.js. Without this, a peer
221
257
  // can @mention a capped seat and get silence, with no signal to either
@@ -223,11 +259,9 @@ export const createCascadeGovernor = ({
223
259
  // 51 wakes and 28 consecutive cap refusals, five of them chat.mention,
224
260
  // and answered none of them.
225
261
  //
226
- // A GRACE, not an exemption: an unbounded pass would restore the exact
227
- // A-mentions-B-mentions-A echo this governor exists to kill. Addressed
228
- // turns still count toward the streak, so a mention loop terminates at
229
- // cap + addressedGrace instead of never.
230
- const addressed = ADDRESSED_EVENT_TYPES.has(eventType);
262
+ // Legacy direct-address events retain a GRACE, not an exemption. They
263
+ // still count toward the streak, so they terminate at cap +
264
+ // addressedGrace instead of never.
231
265
  const limit = addressed ? cap + addressedGrace : cap;
232
266
  // `addressed` describes the EVENT; `graceApplied` describes what this
233
267
  // governor actually did with it. They diverge whenever addressedGrace is
@@ -249,7 +283,8 @@ export const createCascadeGovernor = ({
249
283
  const s = stateFor(podId);
250
284
  pods.set(podId, { streak: s.streak + 1, lastAgentTurnAt: now() });
251
285
  }
252
- // 'unknown' is neutral: no count, no reset.
286
+ // 'unknown' is neutral by FALLBACK; 'kernel' is neutral by DESIGN —
287
+ // both take this path, but only one of them is an accident.
253
288
  },
254
289
  };
255
290
  };