@sema-agent/settings-schema 1.10.0 → 2.1.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.
@@ -61,7 +61,7 @@ export declare const RemoteExecSpec: z.ZodDiscriminatedUnion<"provider", [z.ZodO
61
61
  memory?: string | undefined;
62
62
  workdir?: string | undefined;
63
63
  cpus?: number | undefined;
64
- network?: "host" | "none" | "bridge" | undefined;
64
+ network?: "none" | "host" | "bridge" | undefined;
65
65
  mountPath?: string | undefined;
66
66
  }, {
67
67
  provider: "local-docker";
@@ -69,7 +69,7 @@ export declare const RemoteExecSpec: z.ZodDiscriminatedUnion<"provider", [z.ZodO
69
69
  memory?: string | undefined;
70
70
  workdir?: string | undefined;
71
71
  cpus?: number | undefined;
72
- network?: "host" | "none" | "bridge" | undefined;
72
+ network?: "none" | "host" | "bridge" | undefined;
73
73
  mountPath?: string | undefined;
74
74
  }>, z.ZodObject<{
75
75
  /** The remote docker endpoint — a DOCKER_HOST url: `ssh://user@host` or `tcp://host:2376`. A `user@` is OK
@@ -96,7 +96,7 @@ export declare const RemoteExecSpec: z.ZodDiscriminatedUnion<"provider", [z.ZodO
96
96
  memory?: string | undefined;
97
97
  workdir?: string | undefined;
98
98
  cpus?: number | undefined;
99
- network?: "host" | "none" | "bridge" | undefined;
99
+ network?: "none" | "host" | "bridge" | undefined;
100
100
  mountPath?: string | undefined;
101
101
  tlsCertEnv?: string | undefined;
102
102
  tlsKeyEnv?: string | undefined;
@@ -109,7 +109,7 @@ export declare const RemoteExecSpec: z.ZodDiscriminatedUnion<"provider", [z.ZodO
109
109
  memory?: string | undefined;
110
110
  workdir?: string | undefined;
111
111
  cpus?: number | undefined;
112
- network?: "host" | "none" | "bridge" | undefined;
112
+ network?: "none" | "host" | "bridge" | undefined;
113
113
  mountPath?: string | undefined;
114
114
  tlsCertEnv?: string | undefined;
115
115
  tlsKeyEnv?: string | undefined;
@@ -28,7 +28,7 @@ import { ENV_NAME, K8S_QUANTITY, NON_SECRET_URL, TCP_PORT, containsSecretToken,
28
28
  * byte uniformly — a NUL validates here but makes Node throw at spawn/boot (fail-OPEN → runtime crash). R20. */
29
29
  const execStr = z.string().min(1).refine((s) => !hasNul(s), "must not contain a NUL byte");
30
30
  /** Container knobs shared by the two docker lanes (local-docker / remote-docker). `network` defaults to
31
- * `none` at the adapter (the safe posture for untrusted code — see DUAL-MODE-DESIGN.md). */
31
+ * `none` at the adapter (the safe posture for untrusted code — see the dual-mode design note). */
32
32
  const DOCKER_FIELDS = {
33
33
  /** Sandbox image (required — a run must be reproducible). */
34
34
  image: execStr,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Per-worker roster resolution (docs/MULTI-ROSTER.md). Turns the GLOBAL effective config + a worker name
2
+ * Per-worker roster resolution (the multi-roster design note). Turns the GLOBAL effective config + a worker name
3
3
  * into THAT worker's effective config: its `models` domain is the roster's view (model subset + role-map +
4
4
  * @-allowlist override), everything else stays global. The `rosters` domain is control-plane-only and is
5
5
  * always stripped from the wire payload (no /effective consumer reads it).
@@ -54,13 +54,23 @@ export interface SchedulerStore {
54
54
  }
55
55
  /** Structural validation of one record (required fields + a well-formed `when`). Unknown fields are allowed. */
56
56
  export declare function isSchedulerRecord(v: unknown): v is SchedulerRecord;
57
- /** One record dropped by {@link parseSchedulerStore} for failing {@link isSchedulerRecord} (malformed shape).
58
- * `index` = its position in the parsed array (for correlating with the source file); `record` = the raw
59
- * (unvalidated) value, for diagnostics. Additive — passing `onWarning` is optional. */
57
+ /** Something {@link parseSchedulerStore} DID to the data it read, rather than reading it verbatim. `index` =
58
+ * the record's position in the parsed array (for correlating with the source file). Additive — passing
59
+ * `onWarning` is optional, and a new `kind` is an additive union member (a consumer with an exhaustive
60
+ * `switch` gains an arm to write).
61
+ * - `malformed-record` — the record failed {@link isSchedulerRecord} and was dropped; `record` = the
62
+ * raw (unvalidated) value, for diagnostics.
63
+ * - `durable-scope-rekeyed` — the durable-scope compat arm rewrote this row's `scope` (1.11.0; before that
64
+ * the rewrite happened silently every parse). */
60
65
  export type SchedulerParseWarning = {
61
66
  index: number;
62
67
  kind: 'malformed-record';
63
68
  record: unknown;
69
+ } | {
70
+ index: number;
71
+ kind: 'durable-scope-rekeyed';
72
+ from: string;
73
+ to: string;
64
74
  };
65
75
  export declare function parseSchedulerStore(text: string, onWarning?: (w: SchedulerParseWarning) => void): SchedulerRecord[];
66
76
  /** Serialize the store to its canonical on-disk form (stable, pretty JSON). The WRITE half of the format contract. */
@@ -55,6 +55,11 @@ export function isSchedulerRecord(v) {
55
55
  *
56
56
  * 窄读判据:`lifetime` 不在本契约的显式键上(server 写侧作为 forward-compat 字段随行),按未知
57
57
  * 字段窄读——`"session"` 行是会话链键,零触碰;其余(缺席=durable 默认)按 durable 归一。
58
+ *
59
+ * 落日(1.11.0):删除它 = **持久数据**面的破坏(仍按旧键存着的 durable 行会就此找不回),所以不能在
60
+ * minor 上一删了事 —— 归下一个 MAJOR,按持久数据的规矩办(响亮拒收 + 一次性迁移)。在那之前,本版把
61
+ * 这次重写从**静默**改成**出声**(`durable-scope-rekeyed`,带改写前后):关窗的前提是有人能证明它
62
+ * 已经不再触发,而不是有人记得它还在。
58
63
  */
59
64
  function normalizeDurableScope(r) {
60
65
  if (r.lifetime === 'session')
@@ -76,10 +81,15 @@ export function parseSchedulerStore(text, onWarning) {
76
81
  return parsed.filter(isSchedulerRecord).map(normalizeDurableScope);
77
82
  const out = [];
78
83
  parsed.forEach((record, index) => {
79
- if (isSchedulerRecord(record))
80
- out.push(normalizeDurableScope(record));
81
- else
84
+ if (!isSchedulerRecord(record)) {
82
85
  onWarning({ index, kind: 'malformed-record', record });
86
+ return;
87
+ }
88
+ const normalized = normalizeDurableScope(record);
89
+ // 兼容臂真改写了这一行才出声(未改写时 normalizeDurableScope 返回同一个引用)。
90
+ if (normalized !== record)
91
+ onWarning({ index, kind: 'durable-scope-rekeyed', from: record.scope, to: normalized.scope });
92
+ out.push(normalized);
83
93
  });
84
94
  return out;
85
95
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Skills content-addressing (docs/MCP-SKILLS.md §3.1, slice 2). The /effective payload ships skills as a
2
+ * Skills content-addressing (the mcp/skills design note §3.1, slice 2). The /effective payload ships skills as a
3
3
  * MANIFEST — each skill's markdown `content` replaced by a `contentHash` — so the frequent 60s refresh stays
4
4
  * small; the service pulls each body ONCE (at boot) via GET /api/config/skills/content/<hash>, caches it by
5
5
  * hash, and re-pulls only when the hash changes (skills rarely change → big win). Bodies are immutable +