@sema-agent/mods-kernel 7.57.0 → 7.58.0

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.
@@ -48,6 +48,7 @@ export interface ModDispatchOptions {
48
48
  readonly frames?: readonly ModFrame[];
49
49
  readonly origin?: ModOrigin;
50
50
  readonly checkAnswer?: ModAnswerCheck;
51
+ readonly checkHandOn?: (payload: ModEventPayload) => string | undefined;
51
52
  readonly ranks?: ModAnswerRanks;
52
53
  readonly participant?: (p: ModParticipant) => boolean;
53
54
  }
package/dist/dispatch.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { CATCH_BUDGET_MS, createSelfBudget, POST_ABORT_GRACE_MS, RUNAWAY_AFTER_MS, unrefTimer, watchRunaway } from "./budget.js";
2
2
  import { expandOnSide, failureRefuses, isModEventName, MOD_SEATS, nextToRefusal, stationOn } from "./events.js";
3
3
  import { ENGINE_ORIGIN, modsInvalid, screenModSeats, } from "./registration.js";
4
- import { answerUpward, answerViolation, detachedCopy, engineObjectsOnce, handedOn, matcherMatches, matcherViolation, methodAnswerViolation, NEXT_IN_FLIGHT, receiveAnswer, receiveEvent, receivePayload, sealedObjects, } from "./site-rules.js";
4
+ import { answerUpward, answerViolation, detachedCopy, engineObjectsOnce, handedOn, handOnViolation, matcherMatches, matcherViolation, methodAnswerViolation, NEXT_IN_FLIGHT, receiveAnswer, receiveEvent, receivePayload, sealedObjects, } from "./site-rules.js";
5
5
  const TIER_RANK = { prepend: 0, user: 1, append: 2, builtin: 3, core: 4 };
6
6
  const bypassed = (floors, tier) => floors.some((f) => TIER_RANK[f.from] < TIER_RANK[tier] && TIER_RANK[tier] < TIER_RANK[f.to]);
7
7
  export async function admitMods(input) {
@@ -31,23 +31,22 @@ export async function admitMods(input) {
31
31
  });
32
32
  if (outcome.kind === "aborted")
33
33
  throw input.signal?.reason ?? new Error("admission aborted");
34
+ const whose = { name: cand.name, seat: cand.seat, tier: cand.tier, ...(cand.provenance !== undefined ? { provenance: cand.provenance } : {}) };
34
35
  if (outcome.kind === "failed") {
35
- records.push(Object.freeze({ name: cand.name, seat: cand.seat, tier: cand.tier, refusedBy: outcome.registration, reason: `${outcome.registration} failed: ${outcome.reason}` }));
36
+ records.push(Object.freeze({ ...whose, refusedBy: outcome.registration, reason: `${outcome.registration} failed: ${outcome.reason}` }));
36
37
  continue;
37
38
  }
38
39
  const refused = refusalOf(outcome.answer);
39
40
  if (refused !== undefined) {
40
- records.push(Object.freeze({ name: cand.name, seat: cand.seat, tier: cand.tier, refusedBy: outcome.answeredBy ?? "engine", reason: refused }));
41
+ records.push(Object.freeze({ ...whose, refusedBy: outcome.answeredBy ?? "engine", reason: refused }));
41
42
  continue;
42
43
  }
43
44
  const own = mountOne(cand, input.side, describe);
44
45
  mounted.push(...own);
45
46
  const events = unique(own.map((h) => h.pattern));
46
- const observe = unique(own.filter((h) => h.observe).map((h) => h.pattern));
47
+ const observe = Object.freeze(events.filter((p) => own.every((h) => h.pattern !== p || h.observe)));
47
48
  records.push(Object.freeze({
48
- name: cand.name,
49
- seat: cand.seat,
50
- tier: cand.tier,
49
+ ...whose,
51
50
  events,
52
51
  ...(observe.length > 0 ? { observe } : {}),
53
52
  ...(outcome.skipped.length > 0 ? { skipped: outcome.skipped } : {}),
@@ -376,7 +375,10 @@ function createBus(side, mounted, bottoms, entries, report, records, describe, i
376
375
  if (passed === e0)
377
376
  return { snap: e0 };
378
377
  const handed = handedOn(st.pinned, e0, passed, engines(), isProxy);
379
- return "violation" in handed ? handed : { snap: handed.payload };
378
+ if ("violation" in handed)
379
+ return handed;
380
+ const why = handOnViolation(handed.payload, options.checkHandOn);
381
+ return why !== undefined ? { violation: why } : { snap: handed.payload };
380
382
  };
381
383
  const trustFloors = new Map();
382
384
  const NO_FLOOR = Object.freeze(MOD_SEATS.map(() => 0));
package/dist/events.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const KERNEL_CONTRACT_VERSION = 3;
1
+ export declare const KERNEL_CONTRACT_VERSION = 4;
2
2
  export declare const MOD_TIERS: readonly ["prepend", "user", "append", "builtin", "core"];
3
3
  export type ModTier = (typeof MOD_TIERS)[number];
4
4
  export type ModRegistrationTier = Exclude<ModTier, "builtin" | "core">;
package/dist/events.js CHANGED
@@ -1,4 +1,4 @@
1
- export const KERNEL_CONTRACT_VERSION = 3;
1
+ export const KERNEL_CONTRACT_VERSION = 4;
2
2
  export const MOD_TIERS = Object.freeze(["prepend", "user", "append", "builtin", "core"]);
3
3
  export const MOD_SEATS = Object.freeze(["deployment", "task"]);
4
4
  export const MOD_EVENT_SIDES = Object.freeze(["engine", "surface", "both"]);
@@ -88,6 +88,7 @@ export type ModAdmissionRecord = {
88
88
  readonly name: string;
89
89
  readonly seat: ModSeat;
90
90
  readonly tier: ModTier;
91
+ readonly provenance?: string;
91
92
  readonly events: readonly string[];
92
93
  readonly observe?: readonly string[];
93
94
  readonly skipped?: readonly ModSkip[];
@@ -95,6 +96,7 @@ export type ModAdmissionRecord = {
95
96
  readonly name: string;
96
97
  readonly seat: ModSeat;
97
98
  readonly tier: ModTier;
99
+ readonly provenance?: string;
98
100
  readonly refusedBy: string;
99
101
  readonly reason: string;
100
102
  };
@@ -44,6 +44,7 @@ export declare function pinnedHandOn(pinned: readonly string[], held: ModEventPa
44
44
  readonly violation: string;
45
45
  };
46
46
  export declare function answerViolation(answer: unknown, check: ModAnswerCheck | undefined, e: ModEventPayload, by: ModAnswerer, below: readonly unknown[], run: ModDispatchRun): string | undefined;
47
+ export declare function handOnViolation(payload: ModEventPayload, check: ((payload: ModEventPayload) => string | undefined) | undefined): string | undefined;
47
48
  export declare function methodAnswerViolation(answer: unknown, _e?: ModEventPayload, _by?: ModAnswerer, below?: readonly unknown[]): string | undefined;
48
49
  export declare function matcherViolation(m: unknown): string | undefined;
49
50
  export declare function matcherMatches(m: ModMatcher | undefined, e: ModEventPayload): boolean;
@@ -203,6 +203,16 @@ export function answerViolation(answer, check, e, by, below, run) {
203
203
  return "returned an answer the station cannot read";
204
204
  }
205
205
  }
206
+ export function handOnViolation(payload, check) {
207
+ if (check === undefined)
208
+ return undefined;
209
+ try {
210
+ return check(payload);
211
+ }
212
+ catch {
213
+ return "handed on an event the station cannot read";
214
+ }
215
+ }
206
216
  const denyOf = (a) => (typeof a === "object" && a !== null && Object.prototype.hasOwnProperty.call(a, "deny") ? Reflect.get(a, "deny") : undefined);
207
217
  export function methodAnswerViolation(answer, _e, _by, below = []) {
208
218
  if (!isPlainRecord(answer))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/mods-kernel",
3
- "version": "7.57.0",
3
+ "version": "7.58.0",
4
4
  "private": false,
5
5
  "description": "The sema mods kernel: one extension bus (registration, admission, chain, failure and budget law) shared by the engine and the shell. Zero dependencies.",
6
6
  "type": "module",
@@ -31,5 +31,5 @@
31
31
  "scripts": {
32
32
  "build": "tsc -p tsconfig.json"
33
33
  },
34
- "gitHead": "84be0e09dcdd8e157f88f083241ceafedc0f33aa"
34
+ "gitHead": "05f1a14710d078da0b338fe8712e16f8d790f6bd"
35
35
  }