@sema-agent/settings-schema 13.0.0 → 14.0.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.
- package/CHANGELOG.md +108 -0
- package/README.md +20 -2
- package/conformance/VERSION +1 -1
- package/conformance/baseline.json +1 -3
- package/conformance/cases/c01-entry-salvage-then-typo/expected.json +1 -3
- package/conformance/cases/c02-hosts-clamp-stacked/expected.json +1 -3
- package/conformance/cases/c03-literal-dotted-top-key/expected.json +1 -3
- package/conformance/cases/c04-all-bad-collection-not-salvaged/expected.json +1 -3
- package/conformance/cases/c07-hooks-is-not-a-config-domain/expected.json +1 -3
- package/conformance/cases/c08-limits-unknown-carried-64/expected.json +1 -3
- package/conformance/cases/c09-limits-unknown-carried-65/expected.json +1 -3
- package/conformance/cases/c10-record-key-secret-redacted-twice/expected.json +1 -3
- package/conformance/cases/c11-unicode-unknown-keys/expected.json +1 -3
- package/conformance/cases/c12-prototype-name-top-keys/expected.json +1 -3
- package/conformance/cases/c13-models-field-null/expected.json +1 -3
- package/conformance/cases/c14-models-field-empty-array/expected.json +1 -3
- package/conformance/cases/c15-models-field-number/expected.json +1 -3
- package/conformance/cases/c16-deep-nesting-205/expected.json +1 -3
- package/conformance/cases/c17-empty-domain-file/expected.json +1 -3
- package/conformance/cases/c18-wire-envelope-not-an-object/expected.json +1 -3
- package/conformance/cases/c19-wire-envelope-no-version/expected.json +1 -3
- package/conformance/cases/c21-governance-empty-object-wins/expected.json +1 -3
- package/conformance/cases/c23-mixed-validity-models/expected.json +1 -3
- package/conformance/cases/c24-valid-entries-with-unknown-keys/expected.json +1 -3
- package/conformance/cases/c25-published-roundtrip-zero-warnings/expected.json +1 -3
- package/conformance/cases/c26-hosts-array-1024/expected.json +1 -3
- package/conformance/cases/c27-hosts-array-1025/expected.json +1 -3
- package/conformance/cases/c28-large-document-over-1mb/expected.json +1 -3
- package/conformance/cases/c29-salvage-then-domain-refine-fails/expected.json +1 -3
- package/conformance/cases/c30-version-triple-a-first/expected.json +1 -3
- package/conformance/cases/c31-version-triple-b-changed/expected.json +1 -3
- package/conformance/cases/c32-version-triple-a-restored/expected.json +1 -3
- package/conformance/cases/c33-limits-nested-carried-key/expected.json +1 -3
- package/conformance/cases/c34-skills-content-vs-manifest/expected.json +1 -3
- package/conformance/cases/c35-portable-domain-file-is-null/expected.json +1 -3
- package/conformance/cases/c36-skills-entry-without-content/expected.json +1 -3
- package/conformance/cases/c37-skills-field-null/expected.json +1 -3
- package/conformance/cases/c38-remote-exec-is-a-non-domain-file/expected.json +1 -3
- package/conformance/cases/c39-hidden-file-in-config-d/expected.json +1 -3
- package/conformance/cases/c40-s712-identity-only-what-reads-out/expected.json +1 -3
- package/conformance/cases/c41-s792-encoded-pem-identity/expected.json +1 -3
- package/conformance/cases/c42-s792-unknown-key-secret-redacted/expected.json +1 -3
- package/conformance/cases/c43-s792-form-and-deep-encoded-pem/expected.json +1 -3
- package/conformance/cases/c44-s792-utf8-escape-glued-token/expected.json +1 -3
- package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/expected.json +1 -3
- package/conformance/cases/c46-s811-host-name-url-userinfo-withheld/expected.json +1 -3
- package/conformance/cases/c47-s811-roles-key-url-userinfo-withheld/expected.json +1 -3
- package/conformance/cases/c48-s935-model-headers-transported/expected.json +1 -3
- package/conformance/cases/c49-s935-model-headers-secret-entry-dropped/expected.json +1 -3
- package/conformance/cases/c50-s784-lane-host-legal/expected.json +1 -3
- package/conformance/cases/c51-s784-lane-e2b-legal/expected.json +1 -3
- package/conformance/cases/c52-s784-lane-k8s-legal/expected.json +1 -3
- package/conformance/cases/c53-s784-lane-ssh-legal/expected.json +1 -3
- package/conformance/cases/c54-s784-lane-adb-legal/expected.json +1 -3
- package/conformance/cases/c55-s784-lane-local-docker-legal/expected.json +1 -3
- package/conformance/cases/c56-s784-lane-device-legal/expected.json +1 -3
- package/conformance/cases/c57-s784-g1-enabled-no-lane/expected.json +1 -3
- package/conformance/cases/c58-s784-g2-multitenant-host/expected.json +1 -3
- package/conformance/cases/c59-s784-g3-k8s-missing-image/expected.json +1 -3
- package/conformance/cases/c60-s784-g3-e2b-missing-key/expected.json +1 -3
- package/conformance/cases/c61-s784-g3-other-lane-key/expected.json +1 -3
- package/conformance/cases/c62-s784-g7a-session-tidb/expected.json +1 -3
- package/conformance/cases/c63-s784-host-two-replicas/expected.json +1 -3
- package/conformance/cases/c64-s784-multitenant-local-store/expected.json +1 -3
- package/conformance/cases/c65-s784-pg-without-db/expected.json +1 -3
- package/conformance/cases/c66-s784-memory-backend-mismatch/expected.json +1 -3
- package/conformance/cases/c67-s784-retired-field-loud/expected.json +1 -3
- package/conformance/cases/c68-s784-device-local-store/expected.json +1 -3
- package/conformance/cases/c69-deep-encoded-token-past-every-reading/expected.json +1 -3
- package/conformance/cases/c70-rewritten-token-in-front-of-encoded-pem-header/expected.json +1 -3
- package/conformance/cases/c71-one-scanner-write-reads-display-forms/expected.json +1 -3
- package/conformance/cases/c72-dangling-reference-write-seat-refuses/expected.json +1 -3
- package/conformance/cases/c73-projects-extended-registration-reads/expected.json +1 -3
- package/conformance/cases/c74-projects-over-bound-refused/expected.json +1 -3
- package/conformance/cases/c75-projects-patch-remote-uniqueness/expected.json +1 -3
- package/conformance/cases/c76-projects-entry-salvage-nested/expected.json +1 -3
- package/conformance/cases/c77-prompts-center-artifact-carried/expected.json +252 -0
- package/conformance/cases/c77-prompts-center-artifact-carried/input.json +93 -0
- package/conformance/cases/c77-prompts-center-artifact-carried/meta.json +5 -0
- package/conformance/cases/c78-prompts-empty-bindings-refused/expected.json +82 -0
- package/conformance/cases/c78-prompts-empty-bindings-refused/input.json +11 -0
- package/conformance/cases/c78-prompts-empty-bindings-refused/meta.json +5 -0
- package/conformance/cases/c79-prompts-bad-worker-artifact-not-salvaged/expected.json +82 -0
- package/conformance/cases/c79-prompts-bad-worker-artifact-not-salvaged/input.json +129 -0
- package/conformance/cases/c79-prompts-bad-worker-artifact-not-salvaged/meta.json +5 -0
- package/conformance/cases/c80-prompts-wire-v2-verbatim/expected.json +195 -0
- package/conformance/cases/c80-prompts-wire-v2-verbatim/input.json +65 -0
- package/conformance/cases/c80-prompts-wire-v2-verbatim/meta.json +5 -0
- package/conformance/cases/c81-prompts-declaration-bindings-refused/expected.json +82 -0
- package/conformance/cases/c81-prompts-declaration-bindings-refused/input.json +23 -0
- package/conformance/cases/c81-prompts-declaration-bindings-refused/meta.json +5 -0
- package/conformance/cases/c82-prompts-v1-catalog-refused/expected.json +82 -0
- package/conformance/cases/c82-prompts-v1-catalog-refused/input.json +35 -0
- package/conformance/cases/c82-prompts-v1-catalog-refused/meta.json +5 -0
- package/conformance/cases/c83-prompts-bad-overlay-not-salvaged/expected.json +82 -0
- package/conformance/cases/c83-prompts-bad-overlay-not-salvaged/input.json +56 -0
- package/conformance/cases/c83-prompts-bad-overlay-not-salvaged/meta.json +5 -0
- package/conformance/cases/cc01-mcp-toolfaces-non-object/expected.json +1 -3
- package/conformance/cases/cc02-mcp-source-key-is-transported/expected.json +1 -3
- package/conformance/cases/cc03-model-compat-unknown-subkey/expected.json +1 -3
- package/conformance/cases/cli01-model-name-nfc-vs-nfd/expected.json +1 -3
- package/conformance/cases/cli02-control-and-zero-width-chars/expected.json +1 -3
- package/conformance/cases/cli03-credential-pasted-into-unknown-key/expected.json +1 -3
- package/conformance/cases/cli04-env-value-with-newline/expected.json +1 -3
- package/conformance/cases/cli05-long-and-prefix-colliding-names/expected.json +1 -3
- package/conformance/cases/t01-absent-domain-key-not-null/expected.json +1 -3
- package/conformance/cases/t03-prototype-name-key-not-swallowed/expected.json +1 -3
- package/conformance/cases/t04-secret-literal-never-in-warning-value/expected.json +1 -3
- package/conformance/cases/z01-every-domain-empty-object/expected.json +2 -6
- package/conformance/cases/z02-every-domain-unknown-key/expected.json +2 -6
- package/dist/config-fns.d.ts +7 -3
- package/dist/config-fns.js +19 -16
- package/dist/conformance/derive.js +2 -2
- package/dist/hooks-config.d.ts +9 -1
- package/dist/hooks-config.js +23 -15
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp-request-entry.d.ts +93 -0
- package/dist/mcp-request-entry.js +157 -0
- package/dist/migration-receipt.d.ts +1 -1
- package/dist/migration-receipt.js +1 -1
- package/dist/node.d.ts +0 -1
- package/dist/node.js +0 -1
- package/dist/one-time-migrations.d.ts +1 -1
- package/dist/one-time-migrations.js +39 -0
- package/dist/safety-merge-spec.d.ts +6 -6
- package/dist/types.d.ts +438 -355
- package/dist/types.js +161 -136
- package/dist/url-shape.d.ts +8 -0
- package/dist/url-shape.js +10 -0
- package/docs/API-SURFACE.md +1409 -0
- package/docs/CC-DIVERGENCE.md +42 -0
- package/docs/CONFORMANCE.md +344 -0
- package/docs/CONSUMER-INTEGRATION.md +283 -0
- package/docs/openapi-auth.yaml +357 -0
- package/docs/openapi-scopes.yaml +281 -0
- package/llms-full.txt +659 -0
- package/llms.txt +179 -0
- package/package.json +5 -2
- package/dist/prompts-digest.d.ts +0 -16
- package/dist/prompts-digest.js +0 -49
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 请求面 MCP 条目(一条任务提交体 `mcpServers[i]`)的形判官 —— 14.0.0 起住本包:一只读法,消费方的请求腿 / 中心腿 / 壳的发送前预检都 import 这一份。
|
|
3
|
+
* 纯函数、浏览器安全(唯一的值依赖是本包自己的内容出处词表)。
|
|
4
|
+
*
|
|
5
|
+
* ## 律(一条)
|
|
6
|
+
* **一条请求面 MCP 条目的每一格「能不能用」只有一只判官。** 此前这些判官是消费方私有的:壳拿不到,只能在发送前披露「判不准、交给服务端」,
|
|
7
|
+
* 或者自己抄一份 —— 两份判据就是将来漂开的那一份。现在判官在契约包,服务端与壳读同一份,同一条条目在两处同受理 / 同拒、同一个键路径、同一句原因。
|
|
8
|
+
*
|
|
9
|
+
* ## 语义是搬来的,不是重写的
|
|
10
|
+
* 判据与原因句逐字等于消费方 7.131.x 的那一份(钉:`test/mcp-request-entry-14.0.0.test.ts` 逐例搬了消费方既有钉的夹具与期望)。
|
|
11
|
+
* 本模块只答「这一格的形」;拒绝的整句(条目下标、条目名的回显清洗、收尾句)与「拒还是降级」的后果仍是消费方按自己的腿定的 —— 判据一份,后果按腿分。
|
|
12
|
+
*
|
|
13
|
+
* ## 依赖的引擎事实(镜像 + 漂移门)
|
|
14
|
+
* · 申报名的线长界 {@link TOOL_WIRE_NAME_MAX_CHARS} = 引擎同名常量(值级对拍:上游漂移门 ⑧);
|
|
15
|
+
* · 请求面传输形 {@link RequestMcpTransport} = 引擎 MCP 条目的传输形,http 形多一个本包承载的 `assertionHeader`(编译期双向对拍:门 ⑧);
|
|
16
|
+
* · 内容出处词表 = {@link MCP_CONTENT_ORIGINS}(已有的镜像,门 ⑥);
|
|
17
|
+
* · url 前缀守卫 = `./url-shape` 的 `startsWithHttpScheme`(本包判 URL 的正则只在那一个模块)。
|
|
18
|
+
*
|
|
19
|
+
* ## 与配置面的关系(如实)
|
|
20
|
+
* 配置面的 MCP 条目(`McpServerSpec`,部署声明:凭据只许 env-NAME 引用)与请求面(提交体:可带字面凭据 `env` / `headers`)是两份契约,本模块只管后者。
|
|
21
|
+
* 两份契约对「名」与「url」今天给的判据不同(配置面:名按字符集、url 按 `NON_SECRET_URL`;请求面:名按长度界、url 按 http(s) 前缀),本版刻意不动
|
|
22
|
+
* (语义逐字搬),是一项已知待收的分歧。
|
|
23
|
+
*/
|
|
24
|
+
import { MCP_CONTENT_ORIGINS } from "./types.js";
|
|
25
|
+
import { startsWithHttpScheme } from "./url-shape.js";
|
|
26
|
+
// ── 值的种类描述(拒句只说「你写的是什么形」,不回显值:值可能带凭据、可能任意长)──────────────────────────────────────
|
|
27
|
+
/** 值的**种类**(不回显值本身)。 */
|
|
28
|
+
export function describeValueShape(v) {
|
|
29
|
+
if (v === undefined)
|
|
30
|
+
return "nothing (the key is absent)";
|
|
31
|
+
if (v === null)
|
|
32
|
+
return "null";
|
|
33
|
+
if (Array.isArray(v))
|
|
34
|
+
return "an array";
|
|
35
|
+
if (typeof v === "string")
|
|
36
|
+
return v.length === 0 ? "an empty string" : `a string of ${v.length} characters`;
|
|
37
|
+
if (typeof v === "object")
|
|
38
|
+
return "an object";
|
|
39
|
+
return `a ${typeof v}`;
|
|
40
|
+
}
|
|
41
|
+
/** 「不是字符串数组」的种类:数组里混了非串元素说那一句,否则回落到 {@link describeValueShape}。 */
|
|
42
|
+
export function describeNotStringArray(v) {
|
|
43
|
+
return Array.isArray(v) ? "an array with a non-string element" : describeValueShape(v);
|
|
44
|
+
}
|
|
45
|
+
/** 「不是字符串值的对象」的种类:对象里混了非串值说那一句,否则回落到 {@link describeValueShape}。 */
|
|
46
|
+
export function describeNotStringRecord(v) {
|
|
47
|
+
return isRecord(v) ? "an object with a non-string value" : describeValueShape(v);
|
|
48
|
+
}
|
|
49
|
+
/** 字符串数组(空数组合法)。 */
|
|
50
|
+
export function isStringArray(v) {
|
|
51
|
+
return Array.isArray(v) && v.every((a) => typeof a === "string");
|
|
52
|
+
}
|
|
53
|
+
/** 字符串值的对象(空对象合法;数组不是)。 */
|
|
54
|
+
export function isStringRecord(v) {
|
|
55
|
+
return !!v && typeof v === "object" && !Array.isArray(v) && Object.values(v).every((x) => typeof x === "string");
|
|
56
|
+
}
|
|
57
|
+
function isRecord(v) {
|
|
58
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
59
|
+
}
|
|
60
|
+
// ── 申报名的线长界 ──────────────────────────────────────────────────────────────────────────────────
|
|
61
|
+
/** 引擎 `TOOL_WIRE_NAME_MAX_CHARS` 的镜像:一台 MCP server(或 A2A 对端)的申报名会成为线上工具名的命名空间段,引擎对超界名是**拒**(不截断)。 */
|
|
62
|
+
export const TOOL_WIRE_NAME_MAX_CHARS = 128;
|
|
63
|
+
/**
|
|
64
|
+
* 这个申报名能用吗。严判:非串、空串、超 {@link TOOL_WIRE_NAME_MAX_CHARS} 一律不可用。不截断、不规范化 —— 截短一个名字就是**换一个身份**,
|
|
65
|
+
* 而被换掉身份的那台 server 上挂的 allowTools / toolFaces 收窄声明会一起对不上号。
|
|
66
|
+
*/
|
|
67
|
+
export function isUsableWireName(v) {
|
|
68
|
+
return typeof v === "string" && v.length > 0 && v.length <= TOOL_WIRE_NAME_MAX_CHARS;
|
|
69
|
+
}
|
|
70
|
+
/** 坏名的**可打印**摘要(进拒句 / 告警元数据):种类、`empty`,或截到 32 字加长度事实 —— 绝不把任意长度的申报串原样回显。 */
|
|
71
|
+
export function describeBadWireName(v) {
|
|
72
|
+
if (typeof v !== "string")
|
|
73
|
+
return v === null ? "null" : Array.isArray(v) ? "array" : typeof v;
|
|
74
|
+
if (v.length === 0)
|
|
75
|
+
return "empty";
|
|
76
|
+
const head = v.length > 32 ? `${JSON.stringify(v.slice(0, 32))}…` : JSON.stringify(v);
|
|
77
|
+
return `${head} (${v.length} chars > ${TOOL_WIRE_NAME_MAX_CHARS})`;
|
|
78
|
+
}
|
|
79
|
+
// ── 内容出处词 ──────────────────────────────────────────────────────────────────────────────────────
|
|
80
|
+
const CONTENT_ORIGIN_WORDS = new Set(MCP_CONTENT_ORIGINS);
|
|
81
|
+
/**
|
|
82
|
+
* 在内容出处词表({@link MCP_CONTENT_ORIGINS})内吗。严判:非串与大小写不符(`"LOCAL"`)一律不在 —— 引擎的词是字面量联合、不做规范化;
|
|
83
|
+
* 替它「宽容一下」等于自造第二份值域语义,而这条轴上宽容的方向恰好是**放宽信任**(把一个写坏的声明读成 `"local"`)。
|
|
84
|
+
*/
|
|
85
|
+
export function isContentOriginWord(v) {
|
|
86
|
+
return typeof v === "string" && CONTENT_ORIGIN_WORDS.has(v);
|
|
87
|
+
}
|
|
88
|
+
/** 坏内容出处值的**可打印**摘要:串 JSON 化、64 字截断加 `…`;非串只说种类。 */
|
|
89
|
+
export function describeBadContentOrigin(v) {
|
|
90
|
+
const raw = typeof v === "string" ? JSON.stringify(v) : v === null ? "null" : Array.isArray(v) ? "array" : typeof v;
|
|
91
|
+
return raw.length > 64 ? `${raw.slice(0, 64)}…` : raw;
|
|
92
|
+
}
|
|
93
|
+
// ── 两个身份头 ──────────────────────────────────────────────────────────────────────────────────────
|
|
94
|
+
/**
|
|
95
|
+
* 一份 http 传输上两个身份头(`principalHeader` / `assertionHeader`)的读法:字符串才收;**`principalHeader` 胜** —— 它在场(不论值形)时
|
|
96
|
+
* `assertionHeader` 不收。所以读后的形**结构上不可能同带两键**;同设(一份声明给出两个答案)由调用方在读之前对**原始**传输判(判的是写了什么,不是读后留下什么)。
|
|
97
|
+
*/
|
|
98
|
+
export function readMcpIdentityHeaders(transport) {
|
|
99
|
+
return {
|
|
100
|
+
...(typeof transport.principalHeader === "string" ? { principalHeader: transport.principalHeader } : {}),
|
|
101
|
+
...(transport.principalHeader === undefined && typeof transport.assertionHeader === "string" ? { assertionHeader: transport.assertionHeader } : {}),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const transportBad = (path, reason) => ({ ok: false, issue: { path, reason } });
|
|
105
|
+
/**
|
|
106
|
+
* 请求面 `transport` 的**唯一读器**:读器投影 transport 用它,发送前 / 受理时的判形读它报的 `lost` —— 同一只函数两个消费点,「读器丢了什么」与「门拒什么」不可能分岔。
|
|
107
|
+
* · 硬坏形(`transport` 不是对象 / `kind` 出闭集 / stdio 缺 `command` / http 的 `url` 不是 http(s))⇒ `ok:false`,`path` 是读器点名的键路径;
|
|
108
|
+
* · 软坏形(`args` 不是串数组 / `env` `headers` 含非串值 / `principalHeader` 非串)⇒ 读器**丢这个键**(重放存量提交体时的升级前读法),并把它记进 `lost`
|
|
109
|
+
* (受理新提交的门据它响亮拒)。`assertionHeader` 不在 `lost` 里:两个身份头的键组合与 `assertionHeader` 的值形由调用方在读之前对原始传输判。
|
|
110
|
+
* url 的拒句不回显值:它常规地带凭据(userinfo)。
|
|
111
|
+
*/
|
|
112
|
+
export function readRequestMcpTransport(t) {
|
|
113
|
+
if (!t || typeof t !== "object")
|
|
114
|
+
return transportBad("transport", `must be an object with a "kind" of "stdio" or "http" — got ${describeValueShape(t)}`);
|
|
115
|
+
const tr = t;
|
|
116
|
+
const lost = [];
|
|
117
|
+
if (tr.kind === "stdio") {
|
|
118
|
+
if (typeof tr.command !== "string" || tr.command.length === 0)
|
|
119
|
+
return transportBad("transport.command", `must be a non-empty string (the command to run) — got ${describeValueShape(tr.command)}`);
|
|
120
|
+
if (tr.args !== undefined && !isStringArray(tr.args))
|
|
121
|
+
lost.push({ path: "transport.args", reason: `must be an array of strings — got ${describeNotStringArray(tr.args)}` });
|
|
122
|
+
if (tr.env !== undefined && !isStringRecord(tr.env))
|
|
123
|
+
lost.push({ path: "transport.env", reason: `must be an object of string values — got ${describeNotStringRecord(tr.env)}` });
|
|
124
|
+
return {
|
|
125
|
+
ok: true,
|
|
126
|
+
transport: {
|
|
127
|
+
kind: "stdio",
|
|
128
|
+
command: tr.command,
|
|
129
|
+
...(isStringArray(tr.args) ? { args: tr.args } : {}),
|
|
130
|
+
...(isStringRecord(tr.env) ? { env: tr.env } : {}),
|
|
131
|
+
},
|
|
132
|
+
lost,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if (tr.kind === "http") {
|
|
136
|
+
// http(s) only — never file://, never a bare host (a syntactic guard, not the URL shape judge).
|
|
137
|
+
if (typeof tr.url !== "string" || !startsWithHttpScheme(tr.url))
|
|
138
|
+
return transportBad("transport.url", "must be an absolute http(s) URL (put credentials in transport.headers, never in the URL)");
|
|
139
|
+
const ids = readMcpIdentityHeaders(tr);
|
|
140
|
+
if (tr.headers !== undefined && !isStringRecord(tr.headers))
|
|
141
|
+
lost.push({ path: "transport.headers", reason: `must be an object of string values — got ${describeNotStringRecord(tr.headers)}` });
|
|
142
|
+
if (tr.principalHeader !== undefined && ids.principalHeader === undefined) {
|
|
143
|
+
lost.push({ path: "transport.principalHeader", reason: `must be a string (the HTTP header NAME the end-user principal is injected into) — got ${describeValueShape(tr.principalHeader)}` });
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
ok: true,
|
|
147
|
+
transport: {
|
|
148
|
+
kind: "http",
|
|
149
|
+
url: tr.url,
|
|
150
|
+
...(isStringRecord(tr.headers) ? { headers: tr.headers } : {}),
|
|
151
|
+
...ids,
|
|
152
|
+
},
|
|
153
|
+
lost,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return transportBad("transport.kind", `must be "stdio" or "http" — got ${describeValueShape(tr.kind)}`);
|
|
157
|
+
}
|
|
@@ -6,7 +6,7 @@ import type { REMOTE_EXEC_DOCUMENT } from "./remote-exec.js";
|
|
|
6
6
|
import type { DomainName, RetiredDomainName } from "./types.js";
|
|
7
7
|
/** 本版登记的一次性**数据**迁移 id(闭集;每个 id 在 `ONE_TIME_MIGRATIONS` 登记表里恰一行)。收据只许这些 id —— 同表登记的 wire 删码位
|
|
8
8
|
* (`WIRE_RETIREMENT_IDS`,`./one-time-migrations`)不改任何存储形,铸不出收据,不在本集。 */
|
|
9
|
-
export declare const ONE_TIME_MIGRATION_IDS: readonly ["SS-M1", "SS-M2", "SS-M3", "SS-M4", "SS-M5", "SS-M6", "SS-M7", "SS-M8", "SS-M9"];
|
|
9
|
+
export declare const ONE_TIME_MIGRATION_IDS: readonly ["SS-M1", "SS-M2", "SS-M3", "SS-M4", "SS-M5", "SS-M6", "SS-M7", "SS-M8", "SS-M9", "SS-M10"];
|
|
10
10
|
export type OneTimeMigrationId = (typeof ONE_TIME_MIGRATION_IDS)[number];
|
|
11
11
|
/**
|
|
12
12
|
* 一条收据说迁移**对一个坐标做了什么**(闭集,每词一义):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** 本版登记的一次性**数据**迁移 id(闭集;每个 id 在 `ONE_TIME_MIGRATIONS` 登记表里恰一行)。收据只许这些 id —— 同表登记的 wire 删码位
|
|
2
2
|
* (`WIRE_RETIREMENT_IDS`,`./one-time-migrations`)不改任何存储形,铸不出收据,不在本集。 */
|
|
3
|
-
export const ONE_TIME_MIGRATION_IDS = ["SS-M1", "SS-M2", "SS-M3", "SS-M4", "SS-M5", "SS-M6", "SS-M7", "SS-M8", "SS-M9"];
|
|
3
|
+
export const ONE_TIME_MIGRATION_IDS = ["SS-M1", "SS-M2", "SS-M3", "SS-M4", "SS-M5", "SS-M6", "SS-M7", "SS-M8", "SS-M9", "SS-M10"];
|
|
4
4
|
/**
|
|
5
5
|
* 一条收据说迁移**对一个坐标做了什么**(闭集,每词一义):
|
|
6
6
|
* - `moved` — 值搬到新位(`to`),义不变;
|
package/dist/node.d.ts
CHANGED
|
@@ -9,6 +9,5 @@ export * from "./file-edit.js";
|
|
|
9
9
|
export * from "./bundle.js";
|
|
10
10
|
export * from "./local-load.js";
|
|
11
11
|
export * from "./scheduler-store-node.js";
|
|
12
|
-
export * from "./prompts-digest.js";
|
|
13
12
|
export { migrateConfigDirectory, type ConfigDirectoryDocument, type ConfigDirectoryIo, type ConfigDirectoryMigration, type ConfigDirectoryRefusal, type MigrateConfigDirectoryOptions } from "./config-dir-migration.js";
|
|
14
13
|
export { nodeConfigDirectoryIo } from "./config-dir-io.js";
|
package/dist/node.js
CHANGED
|
@@ -9,7 +9,6 @@ export * from "./file-edit.js";
|
|
|
9
9
|
export * from "./bundle.js";
|
|
10
10
|
export * from "./local-load.js";
|
|
11
11
|
export * from "./scheduler-store-node.js"; // R7 self-wake scheduler store — fs binding of the ./scheduler-store contract
|
|
12
|
-
export * from "./prompts-digest.js"; // prompts 下发包的内容摘要(4.0.0 从 scheduler-store-node 搬来 —— 与调度存储无关;出口路径不变)
|
|
13
12
|
// 目录形的一次性迁移(读目录 → 迁 → 整域终判 → 原子写 → 删 retired 域文件)—— 语义只此一处,命令行是它的渲染器、引擎起服调同一只。显式列名:该模块的包内私有件(出门形/拼路径)不外泄。
|
|
14
13
|
export { migrateConfigDirectory } from "./config-dir-migration.js";
|
|
15
14
|
export { nodeConfigDirectoryIo } from "./config-dir-io.js"; // 上面那只函数的真 I/O 绑定:node:fs + 本包唯一的原子写器(config-document 模式规则)
|
|
@@ -39,7 +39,7 @@ export type StoredDocuments = Readonly<Partial<Record<DomainName | RetiredDomain
|
|
|
39
39
|
export interface StoredDocumentsMigration {
|
|
40
40
|
/** 迁移后的文档集:没改的文档是**同一引用**;被移除的(retired 域)不在;新建的(例:迁出的 `governance` / `limits`)在。 */
|
|
41
41
|
readonly docs: Readonly<Record<string, unknown>>;
|
|
42
|
-
/** 逐条收据(步序 SS-M1 → SS-M2 → SS-M5 → SS-M6 → SS-M8 → SS-M9 → SS-M7 → SS-M4:纯改写步在前,用新 schema 终判的 SS-M4 最后;步内按坐标)。
|
|
42
|
+
/** 逐条收据(步序 SS-M1 → SS-M2 → SS-M5 → SS-M6 → SS-M8 → SS-M9 → SS-M10 → SS-M7 → SS-M4:纯改写步在前,用新 schema 终判的 SS-M4 最后;步内按坐标)。
|
|
43
43
|
* 只有 `refused` 的收据 = 什么都没改。 */
|
|
44
44
|
readonly receipts: readonly MigrationReceipt[];
|
|
45
45
|
}
|
|
@@ -161,6 +161,19 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
161
161
|
removal: "the next major after the window: delete the SS-M9 step; the models.default tombstone field stays — its SS-M9 clause goes",
|
|
162
162
|
afterRemoval: "the models.default tombstone field (permanent): a residual key is refused on read and write (the models domain degrades to its default)",
|
|
163
163
|
},
|
|
164
|
+
{
|
|
165
|
+
id: "SS-M10",
|
|
166
|
+
oldForm: "refused",
|
|
167
|
+
introducedIn: "14.0.0",
|
|
168
|
+
releasedOn: "2026-10-17",
|
|
169
|
+
removableAfter: "2026-11-16",
|
|
170
|
+
rewrites: "prompts: an empty `bindings` array (the default every document carried before 14.0.0 — it served nothing) is removed; a non-empty " +
|
|
171
|
+
"`bindings` and a `catalog` are refused and kept verbatim — declarations compile to center overlays only through the center's card " +
|
|
172
|
+
"compiler (republish), and a catalog's digest is the engine's (rebuild it with the engine's buildPromptArtifact)",
|
|
173
|
+
removal: "the next major after the window: delete the SS-M10 step; the prompts `bindings` / `catalog` tombstone fields stay — their SS-M10 clause goes",
|
|
174
|
+
afterRemoval: "the prompts `bindings` / `catalog` tombstone fields (permanent): a residual key is refused on read and write (the prompts domain degrades " +
|
|
175
|
+
"to its default — no center layer is served)",
|
|
176
|
+
},
|
|
164
177
|
{
|
|
165
178
|
// 一条 wire 位的删码登记,不是数据迁移(id 在 WIRE_RETIREMENT_IDS,不在收据闭集)。
|
|
166
179
|
id: "SS-W1",
|
|
@@ -205,6 +218,7 @@ export function migrateStoredDocuments(docs, opts) {
|
|
|
205
218
|
stepAtMention(out, receipts);
|
|
206
219
|
stepRetiredRoleWords(out, receipts);
|
|
207
220
|
stepModelsDefault(out, receipts);
|
|
221
|
+
stepPromptsAxes(out, receipts);
|
|
208
222
|
stepUrlFragments(out, receipts);
|
|
209
223
|
stepWorkers6x(out, receipts);
|
|
210
224
|
return { docs: out, receipts };
|
|
@@ -749,6 +763,31 @@ function stepModelsDefault(out, receipts) {
|
|
|
749
763
|
receipts.push(moved("SS-M9", "models", ["default"], { document: "models", path: ["roles", "default"] }));
|
|
750
764
|
out.models = { ...without(doc, "default"), roles: { ...roles, default: { model: name } } };
|
|
751
765
|
}
|
|
766
|
+
// ── SS-M10:prompts 两轴退役 ───────────────────────────────────────────────────────────────────────────
|
|
767
|
+
/** 14.0.0 的 prompts 域只装中心 artifact;13.x 的两轴键是墓碑。迁移只做只认形的那一件:空的 `bindings: []`(13.x 每份文档恒物化的默认值,
|
|
768
|
+
* 从不下发任何内容)删掉。非空 `bindings` / 不是数组的 `bindings` / `catalog` 一律 refused、原样留着 —— 声明要经中心的卡编译器才编得成
|
|
769
|
+
* overlay,catalog 的 digest 是引擎铸的,替运维机械转就是第二个编译器 / 第二个铸点。`prompts` 不是对象 ⇒ 不动(判形是读者的事)。 */
|
|
770
|
+
function stepPromptsAxes(out, receipts) {
|
|
771
|
+
const doc = out.prompts;
|
|
772
|
+
if (!isPlainObject(doc))
|
|
773
|
+
return;
|
|
774
|
+
let next = doc;
|
|
775
|
+
if (has(doc, "bindings") && doc.bindings !== undefined) {
|
|
776
|
+
if (Array.isArray(doc.bindings) && doc.bindings.length === 0) {
|
|
777
|
+
next = without(next, "bindings");
|
|
778
|
+
receipts.push(receipt("SS-M10", "prompts", ["bindings"], "dropped-inert"));
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
receipts.push(refused("SS-M10", "prompts", ["bindings"], "declaration bindings compile to center overlays only through the center's card compiler — republish the prompts from the web-admin editor " +
|
|
782
|
+
"(a local config.d copy was never read by the engine: delete the key)"));
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
if (has(doc, "catalog") && doc.catalog !== undefined) {
|
|
786
|
+
receipts.push(refused("SS-M10", "prompts", ["catalog"], "a v1 catalog cannot be converted (its digest is the engine's) — republish from the web-admin, or rebuild with the engine's buildPromptArtifact"));
|
|
787
|
+
}
|
|
788
|
+
if (next !== doc)
|
|
789
|
+
out.prompts = next;
|
|
790
|
+
}
|
|
752
791
|
// ── SS-M7:URL fragment ────────────────────────────────────────────────────────────────────────────────
|
|
753
792
|
/** SS-M7 走查的文档 → 它的 schema(座位从 schema 派生的那一只来源):配置域按 `DOMAIN_SCHEMAS`,`remote-exec` 按 `RemoteExecSpec`;别的文档没有 URL 座位。 */
|
|
754
793
|
function urlSeatSchemaOf(document) {
|
|
@@ -69,8 +69,8 @@ export type MergeShape = z.infer<typeof MergeShape>;
|
|
|
69
69
|
export declare const MinTrust: z.ZodEnum<{
|
|
70
70
|
local: "local";
|
|
71
71
|
session: "session";
|
|
72
|
-
global: "global";
|
|
73
72
|
project: "project";
|
|
73
|
+
global: "global";
|
|
74
74
|
managed: "managed";
|
|
75
75
|
task: "task";
|
|
76
76
|
}>;
|
|
@@ -118,8 +118,8 @@ export declare const MemberAdmission: z.ZodObject<{
|
|
|
118
118
|
minTrust: z.ZodOptional<z.ZodEnum<{
|
|
119
119
|
local: "local";
|
|
120
120
|
session: "session";
|
|
121
|
-
global: "global";
|
|
122
121
|
project: "project";
|
|
122
|
+
global: "global";
|
|
123
123
|
managed: "managed";
|
|
124
124
|
task: "task";
|
|
125
125
|
}>>;
|
|
@@ -128,8 +128,8 @@ export declare const MemberAdmission: z.ZodObject<{
|
|
|
128
128
|
minTrust: z.ZodEnum<{
|
|
129
129
|
local: "local";
|
|
130
130
|
session: "session";
|
|
131
|
-
global: "global";
|
|
132
131
|
project: "project";
|
|
132
|
+
global: "global";
|
|
133
133
|
managed: "managed";
|
|
134
134
|
task: "task";
|
|
135
135
|
}>;
|
|
@@ -194,8 +194,8 @@ export declare const MergeCategorySpec: z.ZodObject<{
|
|
|
194
194
|
minTrust: z.ZodEnum<{
|
|
195
195
|
local: "local";
|
|
196
196
|
session: "session";
|
|
197
|
-
global: "global";
|
|
198
197
|
project: "project";
|
|
198
|
+
global: "global";
|
|
199
199
|
managed: "managed";
|
|
200
200
|
task: "task";
|
|
201
201
|
}>;
|
|
@@ -240,8 +240,8 @@ export declare const MergeCategorySpec: z.ZodObject<{
|
|
|
240
240
|
minTrust: z.ZodOptional<z.ZodEnum<{
|
|
241
241
|
local: "local";
|
|
242
242
|
session: "session";
|
|
243
|
-
global: "global";
|
|
244
243
|
project: "project";
|
|
244
|
+
global: "global";
|
|
245
245
|
managed: "managed";
|
|
246
246
|
task: "task";
|
|
247
247
|
}>>;
|
|
@@ -250,8 +250,8 @@ export declare const MergeCategorySpec: z.ZodObject<{
|
|
|
250
250
|
minTrust: z.ZodEnum<{
|
|
251
251
|
local: "local";
|
|
252
252
|
session: "session";
|
|
253
|
-
global: "global";
|
|
254
253
|
project: "project";
|
|
254
|
+
global: "global";
|
|
255
255
|
managed: "managed";
|
|
256
256
|
task: "task";
|
|
257
257
|
}>;
|