@sema-agent/server 7.98.0 → 7.100.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/MIGRATION.md +19 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +86 -60
- package/deploy/sema-up/lib/envf.sh +110 -42
- package/deploy/sema-up/sema-up.sh +76 -34
- package/dist/approval-ask-machine.d.ts +10 -0
- package/dist/approval-ask-machine.js +3 -0
- package/dist/approval-card.d.ts +74 -1
- package/dist/approval-card.js +41 -8
- package/dist/approval.d.ts +44 -20
- package/dist/approval.js +14 -6
- package/dist/boot/config-center.d.ts +16 -8
- package/dist/boot/config-center.js +206 -103
- package/dist/boot/execution-env.d.ts +1 -2
- package/dist/boot/execution-env.js +2 -2
- package/dist/boot/leader.js +12 -9
- package/dist/boot/memory-consolidation.d.ts +38 -0
- package/dist/boot/memory-consolidation.js +35 -0
- package/dist/boot/org-memory.d.ts +2 -1
- package/dist/boot/org-memory.js +9 -5
- package/dist/boot/resolve-spec.d.ts +0 -1
- package/dist/boot/resolve-spec.js +4 -3
- package/dist/boot/runner-deps.d.ts +2 -2
- package/dist/boot/runtime-caps.js +4 -4
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +3 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -3
- package/dist/boot/stage-07-capability-layer.js +6 -6
- package/dist/boot/stage-08-reapers.d.ts +3 -4
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +2 -3
- package/dist/boot/stage-10-http-server.d.ts +2 -3
- package/dist/boot/stage-10-http-server.js +2 -2
- package/dist/capabilities/center-plugins.d.ts +14 -2
- package/dist/capabilities/center-plugins.js +13 -5
- package/dist/capabilities/center-prompts.d.ts +3 -0
- package/dist/capabilities/center-prompts.js +1 -1
- package/dist/capabilities/hands-lane.js +2 -1
- package/dist/capabilities/scenarios.js +18 -5
- package/dist/capabilities/tool-defer.d.ts +2 -2
- package/dist/center-credential.d.ts +112 -0
- package/dist/center-credential.js +131 -0
- package/dist/config-catalog.d.ts +2 -2
- package/dist/config-catalog.js +15 -15
- package/dist/config-center/apply-effective.d.ts +34 -39
- package/dist/config-center/apply-effective.js +100 -64
- package/dist/config-center/apply-ledger.d.ts +35 -16
- package/dist/config-center/apply-ledger.js +25 -18
- package/dist/config-center/center-request.d.ts +60 -0
- package/dist/config-center/center-request.js +71 -0
- package/dist/config-center/facade.d.ts +11 -5
- package/dist/config-center/facade.js +1 -1
- package/dist/config-center/hot-keys-registry.d.ts +11 -4
- package/dist/config-center/hot-keys-registry.js +11 -7
- package/dist/config-center/http-client.d.ts +17 -9
- package/dist/config-center/http-client.js +27 -36
- package/dist/config-center/restart-signal.d.ts +21 -14
- package/dist/config-center/restart-signal.js +16 -22
- package/dist/config-center/skills-mcp.d.ts +4 -1
- package/dist/config-center/skills-mcp.js +2 -2
- package/dist/config-center/types.d.ts +3 -3
- package/dist/config-invariants.d.ts +2 -2
- package/dist/config-invariants.js +0 -8
- package/dist/config-lkg.d.ts +47 -8
- package/dist/config-lkg.js +107 -20
- package/dist/config-provider.d.ts +8 -7
- package/dist/config-provider.js +5 -5
- package/dist/config-types.d.ts +30 -11
- package/dist/config.js +11 -13
- package/dist/cross-session-settings.js +1 -1
- package/dist/fleet-client.d.ts +8 -8
- package/dist/fleet-client.js +7 -7
- package/dist/fleet-lease.d.ts +11 -11
- package/dist/fleet-lease.js +17 -13
- package/dist/host-lsp-manager.d.ts +29 -0
- package/dist/host-lsp-manager.js +14 -0
- package/dist/hosted-posture.d.ts +49 -93
- package/dist/hosted-posture.js +1 -25
- package/dist/http/active-run-conflict.d.ts +2 -12
- package/dist/http/active-run-conflict.js +1 -6
- package/dist/http/admission.js +8 -0
- package/dist/http/resume-legs.d.ts +1 -1
- package/dist/http/resume-legs.js +14 -10
- package/dist/http/route-ctx.d.ts +2 -2
- package/dist/http/routes/approvals-assistant.d.ts +1 -1
- package/dist/http/routes/approvals-assistant.js +2 -2
- package/dist/http/routes/memory-compliance.js +5 -0
- package/dist/http/routes/memory-origin.js +5 -0
- package/dist/http/routes/sessions.js +6 -0
- package/dist/http/routes/tasks.js +7 -6
- package/dist/http/server.d.ts +6 -5
- package/dist/http/wire-types.d.ts +6 -3
- package/dist/leader/wire.d.ts +20 -12
- package/dist/leader/wire.js +7 -6
- package/dist/memory-layer-preflight.d.ts +46 -0
- package/dist/memory-layer-preflight.js +121 -0
- package/dist/memory-operator-faces.js +17 -1
- package/dist/observability/corrupt-read-seat.d.ts +21 -4
- package/dist/observability/corrupt-read-seat.js +31 -0
- package/dist/observability/fail-open.d.ts +8 -4
- package/dist/observability/fail-open.js +8 -4
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +3 -26
- package/dist/observability/secret-env-scrub.js +3 -2
- package/dist/orchestration/workflow-completion-inbox.d.ts +31 -23
- package/dist/orchestration/workflow-completion-inbox.js +8 -3
- package/dist/plugins/approval-ask-store-file.d.ts +20 -2
- package/dist/plugins/approval-ask-store-file.js +21 -3
- package/dist/plugins/approval-ask-store-memory.d.ts +2 -0
- package/dist/plugins/approval-ask-store-memory.js +39 -13
- package/dist/plugins/approval-ask-store-sql.d.ts +24 -5
- package/dist/plugins/approval-ask-store-sql.js +27 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +9 -3
- package/dist/plugins/checkpoint-store-sql.js +19 -2
- package/dist/plugins/local-checkpoint-store.js +2 -0
- package/dist/plugins/mailbox-store-sql.d.ts +7 -5
- package/dist/plugins/mailbox-store-sql.js +6 -4
- package/dist/plugins/permission-rule-store-file.js +3 -2
- package/dist/plugins/remote-env-host.d.ts +3 -1
- package/dist/plugins/remote-env-host.js +3 -2
- package/dist/plugins/sql-json-column.d.ts +16 -3
- package/dist/plugins/sql-json-column.js +15 -4
- package/dist/plugins/web-search.d.ts +42 -22
- package/dist/plugins/web-search.js +141 -49
- package/dist/project-memory.d.ts +28 -1
- package/dist/project-memory.js +22 -22
- package/dist/run-local.js +6 -7
- package/dist/runs.js +6 -5
- package/dist/runtime-caps-resolver.d.ts +8 -8
- package/dist/runtime-caps-resolver.js +16 -14
- package/dist/runtime-governance.d.ts +50 -3
- package/dist/runtime-governance.js +5 -0
- package/dist/sealed-key.js +3 -7
- package/dist/server-secret-env.d.ts +43 -0
- package/dist/server-secret-env.js +18 -0
- package/dist/task-settings.d.ts +1 -1
- package/dist/tool-approval.d.ts +144 -9
- package/dist/tool-approval.js +74 -18
- package/dist/trace/core-keyset-guard.d.ts +5 -5
- package/dist/trace/ledger-sink.js +2 -2
- package/dist/trace/project.d.ts +13 -0
- package/dist/trace/project.js +22 -5
- package/dist/trace/projection-drop.d.ts +2 -0
- package/dist/trace/projection-drop.js +6 -0
- package/dist/trace/sema-provenance.d.ts +4 -1
- package/dist/trace/sema-provenance.js +1 -1
- package/dist/trace/task-notification-facets.d.ts +65 -0
- package/dist/trace/task-notification-facets.js +31 -0
- package/dist/trace/wire-projection-faces.d.ts +3 -3
- package/dist/trace/wire-projection-faces.js +3 -3
- package/package.json +5 -4
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
set -euo pipefail
|
|
16
16
|
|
|
17
17
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
18
|
-
# `.env` 文法(写口
|
|
18
|
+
# `.env` 文法(写口 envf_representable + envf_encode / 读口 envf_canonical_line)的唯一定义 —— 写读两半从这一处取判据。
|
|
19
19
|
. "$HERE/lib/envf.sh"
|
|
20
20
|
# 执行车道表的唯一读者(S-599)。定义在**最前面**:`--help` 的词表也从表渲(手抄的词表会在加一条
|
|
21
21
|
# 车道时静默分叉),而 `-h` 在参数循环里就被处理,那时后面的函数还没定义。
|
|
@@ -169,11 +169,20 @@ log() { printf '[sema-up] %s\n' "$*" >&2; }
|
|
|
169
169
|
|
|
170
170
|
# compose 入口解析:优先 docker compose(插件),缺了退 docker-compose(独立版)——
|
|
171
171
|
# homebrew 裸 docker CLI 不带插件是真场景;都没有=报错带下一步
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
# dc_argv 设 DC_ARGV(选中的 compose 入口);dc 调它 —— 渲染对账给运维的复现命令也从 DC_ARGV 渲,不另写一份。
|
|
173
|
+
dc_argv() {
|
|
174
|
+
if docker compose version >/dev/null 2>&1; then DC_ARGV=(docker compose)
|
|
175
|
+
elif command -v docker-compose >/dev/null 2>&1; then DC_ARGV=(docker-compose)
|
|
175
176
|
else log "⛔ 没有可用的 compose(docker compose 插件/docker-compose 都缺)。下一步:装 Docker Desktop/OrbStack,或 brew install docker-compose"; exit 1; fi
|
|
176
177
|
}
|
|
178
|
+
dc() { dc_argv; "${DC_ARGV[@]}" "$@"; }
|
|
179
|
+
# compose 的全局参数(-p / --env-file / -f)只在这里拼一次(相对 `$HERE/stack`):up / config 走 compose()、teardown 的
|
|
180
|
+
# down、渲染对账给运维的复现命令,都从同一张 COMPOSE_GLOBALS 取(S-646 ④:复现命令曾是手抄的第二份,漏了
|
|
181
|
+
# -f compose.dataroot.yaml 与 profile;teardown 是第三份)。数据根由调用方先定好 DATA_ROOT。
|
|
182
|
+
compose_globals() {
|
|
183
|
+
COMPOSE_GLOBALS=(--project-name "$PROJECT" --env-file "$ENVF" -f compose.yaml)
|
|
184
|
+
if [ -n "$DATA_ROOT" ]; then COMPOSE_GLOBALS+=(-f compose.dataroot.yaml); fi
|
|
185
|
+
}
|
|
177
186
|
|
|
178
187
|
# ── 跨平台探针(Linux 目标机为主;macOS 开发机跑 docker 档也是真场景——npx 分发)────────────
|
|
179
188
|
ram_mb() { if [ -r /proc/meminfo ]; then awk '/MemTotal/{printf "%d", $2/1024}' /proc/meminfo
|
|
@@ -237,22 +246,23 @@ if $TEARDOWN; then
|
|
|
237
246
|
cd "$HERE/stack"
|
|
238
247
|
if [ -f "$ENVF" ]; then
|
|
239
248
|
# 读 .env 一律经 lib 的严格读口(S-618 续):裸 grep|cut 会连编码形的单引号一起读出来。
|
|
240
|
-
|
|
249
|
+
# 数据根以 .env 登记的为准(卸载的是首装那一份,不看本次 --data-root);全局参数与 up 同一张表(compose_globals)。
|
|
250
|
+
DATA_ROOT="$(envf_get DATA_ROOT_DIR)" || exit 1
|
|
241
251
|
# 全 profile down 会对未启用服务也做 config 校验——.env 缺 SEMA_*_IMAGE(该面没开过)时
|
|
242
252
|
# 整个 down 失败(真踩:假「已卸载」)。补占位符只为过校验;shell env 优先级高于 --env-file
|
|
243
253
|
envf_has SEMA_SERVER_IMAGE || export SEMA_SERVER_IMAGE="teardown-placeholder"
|
|
244
254
|
envf_has SEMA_REGISTRY_IMAGE || export SEMA_REGISTRY_IMAGE="teardown-placeholder"
|
|
245
|
-
|
|
255
|
+
compose_globals
|
|
256
|
+
if ! dc "${COMPOSE_GLOBALS[@]}" \
|
|
246
257
|
--profile data --profile pg --profile s3 --profile agent --profile registry --profile git \
|
|
247
258
|
down $($TEARDOWN_VOLUMES && echo -v); then
|
|
248
259
|
log "⛔ 卸载未完全成功。下一步:docker ps -a --filter label=com.docker.compose.project=$PROJECT 手查残留"
|
|
249
260
|
exit 1
|
|
250
261
|
fi
|
|
251
262
|
log "已卸载 project=$PROJECT $($TEARDOWN_VOLUMES && echo '(含数据卷)' || echo '(数据卷保留:pgdata/miniodata/registrydata/gitdata)')"
|
|
252
|
-
if $TEARDOWN_VOLUMES && [ -n "$
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
log "⚠ 数据根在大盘 bind 目录 ${DR}——卷对象已删,盘上文件还在;确认不要了再手动 rm -rf"
|
|
263
|
+
if $TEARDOWN_VOLUMES && [ -n "$DATA_ROOT" ]; then
|
|
264
|
+
# ${DATA_ROOT} 必须带花括号:后面紧跟中文破折号,bash 3.2(macOS 系统壳)会把多字节并进变量名(真踩)
|
|
265
|
+
log "⚠ 数据根在大盘 bind 目录 ${DATA_ROOT}——卷对象已删,盘上文件还在;确认不要了再手动 rm -rf"
|
|
256
266
|
fi
|
|
257
267
|
else log "没有找到 $ENVF,无可卸载"; fi
|
|
258
268
|
exit 0
|
|
@@ -566,8 +576,8 @@ PG_TUNE_FLAGS="-c max_connections=100 -c shared_buffers=${SB}MB -c effective_cac
|
|
|
566
576
|
genpw() { openssl rand -hex 24; }
|
|
567
577
|
touch "$ENVF"; chmod 600 "$ENVF"
|
|
568
578
|
# 写口 = lib/envf.sh 的 envf_put(setk / setk_new / resetk 都落到它):值按同一文法序列化 —— 安全裸词原样,
|
|
569
|
-
# 含空白 /
|
|
570
|
-
# 回车 / 单引号 ⇒
|
|
579
|
+
# 含空白 / 特殊字符 / 反斜杠的走整值单引号编码形(compose 读成字面量、闭引号后不续解析;被 source 也不执行);换行 /
|
|
580
|
+
# 回车 / 单引号 / 以奇数个反斜杠结尾 ⇒ 写之前响亮拒,点名键、不回显值,「下一步」按拒因给。setk 判「键在不在」也走严格读口:旧文件里该键那一行不是
|
|
571
581
|
# 规范形(比如同物理行闭引号带出的二次赋值)⇒ 响亮拒,不再「见行在就跳过」把毒行原样留着(test srv796 RT1)。
|
|
572
582
|
setk SEMA_PROJECT "$PROJECT"
|
|
573
583
|
setk PG_PASSWORD "$(genpw)"
|
|
@@ -683,7 +693,9 @@ fi
|
|
|
683
693
|
envf_load SERVER_PORT PG_PORT MINIO_PORT MINIO_CONSOLE_PORT REGISTRY_PORT GIT_HTTP_PORT GIT_SSH_PORT
|
|
684
694
|
|
|
685
695
|
command -v docker >/dev/null || { log "⛔ 未装 docker。下一步:curl -fsSL https://get.docker.com | sh(cn region 用镜像站,如 https://mirrors.aliyun.com/docker-ce)"; exit 1; }
|
|
686
|
-
compose() { ( cd "$HERE/stack" && dc
|
|
696
|
+
compose() { compose_globals; ( cd "$HERE/stack" && dc "${COMPOSE_GLOBALS[@]}" "$@" ); }
|
|
697
|
+
# shq —— 单引号引用一个词(复现命令要能原样粘贴:路径里可能有空格)。
|
|
698
|
+
shq() { printf "'%s'" "$(printf '%s' "$1" | sed "s/'/'\\\\''/g")"; }
|
|
687
699
|
|
|
688
700
|
# ── D:渲染对账(S-618 的类闭环;生成 .env 之后、compose up 之前)──────────────────────────────────
|
|
689
701
|
# .env 的写口 / 读口都按物理行判,认不出 compose dotenv 的跨行引号值等边角;唯一能确知「容器真正拿到
|
|
@@ -692,22 +704,23 @@ compose() { ( cd "$HERE/stack" && dc --project-name "$PROJECT" --env-file "$ENVF
|
|
|
692
704
|
# REQUIRE_EXECUTION_LANE,与本次决策逐值对比,不一致 ⇒ 拒并点名渲染值与决策值。**以 compose 为唯一属主**。
|
|
693
705
|
# docker 不可达在上面 `command -v docker` 那道已 fail-loud 拦下;config 本身失败(YAML/插值坏)也拒,
|
|
694
706
|
# 不新铸降级臂:未经对账就不 up。只有 agent 面有这三个决策键,别的档跳过。
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
exit 1
|
|
705
|
-
}
|
|
706
|
-
RECON_JSON="$rendered" python3 - "$exp_rp" "$exp_re" "$exp_rl" <<'PY' || {
|
|
707
|
-
import json, os, sys
|
|
707
|
+
#
|
|
708
|
+
# 拒因分两种、各给各的出路(S-656;7.98.0 曾把 stderr 并进 stdout 当 JSON 解析 ⇒ compose 的任何警告都让它 traceback,
|
|
709
|
+
# 拒因还冒充「不一致」):
|
|
710
|
+
# · 渲染结果解析失败 —— compose 退出码非零,或退出 0 但 stdout 不是可解析的 compose JSON:没拿到渲染值,谈不上比对;
|
|
711
|
+
# · 渲染值与决策值不一致 —— 拿到了、逐值比对不上。
|
|
712
|
+
# JSON 只从 stdout 取;stderr 只数行数作诊断,**不转印**(compose 解析 `.env` 失败时报文会原样引用那一行,凭据就在行里;
|
|
713
|
+
# 插值警告里的变量名也可能是凭据的一段)。
|
|
714
|
+
RECON_PY='
|
|
715
|
+
import json, sys
|
|
708
716
|
want = {"REQUIRE_PRINCIPAL": sys.argv[1], "REMOTE_EXEC": sys.argv[2], "REQUIRE_EXECUTION_LANE": sys.argv[3]}
|
|
709
|
-
|
|
710
|
-
|
|
717
|
+
try:
|
|
718
|
+
d = json.loads(sys.stdin.read())
|
|
719
|
+
env = d["services"]["server"].get("environment") or {}
|
|
720
|
+
if not isinstance(env, dict):
|
|
721
|
+
raise TypeError("environment")
|
|
722
|
+
except Exception:
|
|
723
|
+
raise SystemExit(4) # 渲染结果解析失败:不是 compose JSON / 没有 server 服务
|
|
711
724
|
bad = []
|
|
712
725
|
for k, w in want.items():
|
|
713
726
|
got = env.get(k)
|
|
@@ -716,13 +729,42 @@ for k, w in want.items():
|
|
|
716
729
|
bad.append("%s:渲染=%r 决策=%r" % (k, got, w))
|
|
717
730
|
if bad:
|
|
718
731
|
sys.stderr.write("[sema-up] ↳ 明细:" + " | ".join(bad) + "\n")
|
|
719
|
-
raise SystemExit(3)
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
732
|
+
raise SystemExit(3) # 渲染值与决策值不一致
|
|
733
|
+
'
|
|
734
|
+
reconcile_render() {
|
|
735
|
+
case ",$COMPOSE_PROFILES," in *,agent,*) : ;; *) return 0 ;; esac
|
|
736
|
+
local exp_rp="$REQUIRE_PRINCIPAL_WANT" exp_re="$LANE_REMOTE_EXEC" exp_rl rendered errf nerr rc=0 prc=0 repro a
|
|
737
|
+
exp_rl="$(printf '%s\n' "$LANE_ENV" | sed -n 's/^REQUIRE_EXECUTION_LANE=//p')"
|
|
738
|
+
# 复现命令:与这次 config 同一个 compose 入口、同一张全局参数表、同一组 profile(从源渲,不手抄)。
|
|
739
|
+
dc_argv; compose_globals
|
|
740
|
+
repro="(cd $(shq "$HERE/stack") && COMPOSE_PROFILES=$(shq "$COMPOSE_PROFILES") ${DC_ARGV[*]}"
|
|
741
|
+
for a in "${COMPOSE_GLOBALS[@]}"; do repro="$repro $(shq "$a")"; done
|
|
742
|
+
repro="$repro 'config' '--format' 'json')"
|
|
743
|
+
errf="$(umask 077 && mktemp "$WORK/.recon-stderr.XXXXXX")" || { log "⛔ 渲染对账:在 $WORK 建不了临时文件,无法对账 —— 拒绝在未对账的情况下 up"; exit 1; }
|
|
744
|
+
rendered="$(COMPOSE_PROFILES="$COMPOSE_PROFILES" compose config --format json 2>"$errf")" || rc=$?
|
|
745
|
+
nerr="$(wc -l < "$errf" | tr -d '[:space:]')"; rm -f "$errf"
|
|
746
|
+
if [ "$rc" -ne 0 ]; then
|
|
747
|
+
log "⛔ 渲染对账:渲染结果解析失败 —— docker compose config 失败(退出码 $rc;它在 stderr 输出了 $nerr 行,本脚本不转印),无法确认容器会拿到什么 —— 拒绝在未对账的情况下 up"
|
|
748
|
+
log " ↳ 下一步:在本机亲跑 $repro 看 compose 的报文(本脚本不转印它:.env 解析失败的报文会原样引用那一行,可能带凭据);常见成因是手改过的 .env 行"
|
|
723
749
|
exit 1
|
|
724
|
-
|
|
725
|
-
|
|
750
|
+
fi
|
|
751
|
+
printf '%s' "$rendered" | python3 -c "$RECON_PY" "$exp_rp" "$exp_re" "$exp_rl" || prc=$?
|
|
752
|
+
case "$prc" in
|
|
753
|
+
0) : ;;
|
|
754
|
+
3)
|
|
755
|
+
log "⛔ 渲染对账:渲染值与决策值不一致 —— compose 渲染出的容器决策值与本次决策对不上;以 compose 为唯一属主,拒绝 up"
|
|
756
|
+
log " ↳ 下一步:检查 $ENVF 里 REQUIRE_PRINCIPAL / REMOTE_EXEC / REQUIRE_EXECUTION_LANE,以及 shell / -f 里是否**导出**了同名变量(compose 插值 shell 优先于 --env-file,导出为空会盖掉 .env);亲跑 $repro 可看容器 environment"
|
|
757
|
+
exit 1 ;;
|
|
758
|
+
4)
|
|
759
|
+
log "⛔ 渲染对账:渲染结果解析失败 —— docker compose config 退出 0,但 stdout 不是可解析的 compose JSON(或其中没有 server 服务;compose 另在 stderr 输出了 $nerr 行,本脚本不转印),无法确认容器会拿到什么 —— 拒绝在未对账的情况下 up"
|
|
760
|
+
log " ↳ 下一步:亲跑 $repro 看 stdout 是不是一份 JSON;不是 ⇒ 这个 compose 入口不支持 --format json 或往 stdout 多打了东西(${DC_ARGV[*]}),换 Docker Compose v2(docker compose 插件)后重跑"
|
|
761
|
+
exit 1 ;;
|
|
762
|
+
*)
|
|
763
|
+
log "⛔ 渲染对账:对账脚本自身失败(python3 退出码 $prc),无法确认容器会拿到什么 —— 拒绝在未对账的情况下 up"
|
|
764
|
+
log " ↳ 下一步:确认本机 python3 可用(python3 -c 'import json'),然后重跑"
|
|
765
|
+
exit 1 ;;
|
|
766
|
+
esac
|
|
767
|
+
log "渲染对账通过:REQUIRE_PRINCIPAL=$exp_rp REMOTE_EXEC=$exp_re REQUIRE_EXECUTION_LANE=$exp_rl(compose 渲染逐值一致)$([ "$nerr" -gt 0 ] && printf ';compose 另在 stderr 输出了 %s 行(多为插值警告;本脚本不转印,up 时 compose 会自己打出来)' "$nerr")"
|
|
726
768
|
}
|
|
727
769
|
|
|
728
770
|
# ── 外接端点连接检测(装配前 fail-loud;只验兼容可用,不校验证书——内网自签是常态)────────────
|
|
@@ -46,4 +46,14 @@ export declare function deriveAskId(sourceTaskId: string, runId: string, toolCal
|
|
|
46
46
|
/** batch_id = sha256('batch' ⊕ sourceTaskId ⊕ runId ⊕ legKey).slice(0,64)。同一 (sourceTaskId, runId,
|
|
47
47
|
* legKey) 恒派生同一批——批 = 同一决策点的兄弟 ask 集合,故不掺 toolCallId。 */
|
|
48
48
|
export declare function deriveBatchId(sourceTaskId: string, runId: string, legKey: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* 🔴 S-689 codex R1-F1:**单 ask 批** —— batch_id = sha256('ask-batch' ⊕ askId).slice(0,64)。
|
|
51
|
+
*
|
|
52
|
+
* 批是 **park 路由的单位**:窗到期赢家把整批转投递面(OPEN → ROUTING_UNBOUND)、兄弟连坐 VOID,core 随后 park,
|
|
53
|
+
* 这条腿就此结束 —— 所以「整腿一批」成立。不走 park 路由的部署(`UNATTENDED_APPROVAL_POLICY=deny`)上这个前提
|
|
54
|
+
* 不在:core 拿到的是部署政策拒,腿**继续跑**。整腿一批时,首只到期就把批关了,同腿后续每一只卡 `decideAsk`
|
|
55
|
+
* 恒 `batch_closed`(卡看得见、答不了),兄弟还被连坐成 VOID。⇒ 没有 park 路由时,批退化成 ask 自己。
|
|
56
|
+
* 选用处 = 协调器的 `batchIdFor`(唯一消费者);前缀与腿批不同(`ask-batch` 一元组 vs `batch` 三元组),两族 id 不相撞。
|
|
57
|
+
*/
|
|
58
|
+
export declare function deriveAskScopedBatchId(askId: string): string;
|
|
49
59
|
//# sourceMappingURL=approval-ask-machine.d.ts.map
|
|
@@ -33,4 +33,7 @@ export function deriveAskId(sourceTaskId, runId, toolCallId, legKey, parentToolC
|
|
|
33
33
|
export function deriveBatchId(sourceTaskId, runId, legKey) {
|
|
34
34
|
return deterministicId("batch", [sourceTaskId, runId, legKey]);
|
|
35
35
|
}
|
|
36
|
+
export function deriveAskScopedBatchId(askId) {
|
|
37
|
+
return deterministicId("ask-batch", [askId]);
|
|
38
|
+
}
|
|
36
39
|
//# sourceMappingURL=approval-ask-machine.js.map
|
package/dist/approval-card.d.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* 没有方法、没有捕获的行为。
|
|
22
22
|
*/
|
|
23
23
|
import { z } from "zod";
|
|
24
|
-
import { READ_ROOT_CANDIDATE_DIR_MAX, type AskEvidenceAbsence, type AskRequest as CoreAskRequest, type ReadRootGrantCandidate, type RuleOffer } from "@sema-agent/core";
|
|
24
|
+
import { READ_ROOT_CANDIDATE_DIR_MAX, type AskEvidenceAbsence, type AskRequest as CoreAskRequest, type PendingAction as CorePendingAction, type ReadRootGrantCandidate, type RuleOffer } from "@sema-agent/core";
|
|
25
25
|
import type { AskRow } from "./plugins/approval-ask-store-sql.js";
|
|
26
26
|
/** 模型自由文本(`sourceAgentName` / `delegation.agentName`)的限长(设计稿 §6.2)。设计 §3.1 把
|
|
27
27
|
* 「限长 + 脱敏」写成 **server 新增责任**(引擎无此层):spawning model 挑的名字是自由文本,
|
|
@@ -351,12 +351,85 @@ export declare const RuleOffersAbsenceSchema: z.ZodEnum<{
|
|
|
351
351
|
lane_cannot_speak: "lane_cannot_speak";
|
|
352
352
|
shadowed: "shadowed";
|
|
353
353
|
}>;
|
|
354
|
+
/**
|
|
355
|
+
* `ruleOffersAbsence` 座的**三态读数**(S-663 codex r1 起;此前是 {@link readRuleOffersAbsence} 函数体内的两步)。
|
|
356
|
+
* 一只 schema、一处解析,两个读者各自处置「**在场却读不出**」(集外词 / 非串值 = 世代差或第三方 producer):
|
|
357
|
+
* · 展示面 {@link readRuleOffersAbsence}(活卡帧 / `card_json`)—— 按缺席丢并计 F 类(卡上少一行解释 ≪ 卡上出现生词);
|
|
358
|
+
* · 耐久 `/decide` 腿的 remember 判据(`tool-approval.ts` 的 `parkRowStandingAnswerFacts` 的 `mandated` 一格,读 park 行上的
|
|
359
|
+
* 孪生座 `PendingAction.tool_approval.ruleOffersAbsence`,core 同一 factory 铸)—— 判不出是不是强制 ⇒ **按强制**(fail-closed)。
|
|
360
|
+
* 同一个词在两处方向相反是刻意的:展示面的最坏后果是少一行字,权限面的最坏后果是一张会话级免询问。
|
|
361
|
+
* 本函数**不计数**(计不计、计哪个 tag 是读者的处置,不是读数)。
|
|
362
|
+
*/
|
|
363
|
+
export type RuleOffersAbsenceSeat = {
|
|
364
|
+
readonly state: "absent";
|
|
365
|
+
} | {
|
|
366
|
+
readonly state: "word";
|
|
367
|
+
readonly word: RuleOffersAbsence;
|
|
368
|
+
} | {
|
|
369
|
+
readonly state: "unreadable";
|
|
370
|
+
readonly raw: unknown;
|
|
371
|
+
};
|
|
372
|
+
export declare function readRuleOffersAbsenceSeat(x: unknown): RuleOffersAbsenceSeat;
|
|
354
373
|
/**
|
|
355
374
|
* `AskRequest.ruleOffersAbsence`(core [ref] 修②)的**边界窄读** —— 活卡帧与 `card_json` 的唯一铸造点
|
|
356
375
|
* (与 {@link readProbeCause} 同款分工),两面结构性同值。闭集词 verbatim(非内容族,零 redact);
|
|
357
376
|
* 形不合/缺席 ⇒ 不铸键(缺席不是断言 —— 它同时覆盖「有 offers」与结构性无车道的门,core 契约逐字)。
|
|
377
|
+
* 解析在 {@link readRuleOffersAbsenceSeat}(与耐久腿判据共用一只 schema)。S-700 起第三个读者:运维队列行经
|
|
378
|
+
* {@link parkRowFacts} 读寄存行上的 park 孪生座(`PendingAction.tool_approval.ruleOffersAbsence`,core 同一个 factory 铸的同一
|
|
379
|
+
* 闭集)—— 同一只 schema、同一个集外 tag,三面结构性同值;集外 detail 经 {@link outOfSetDetail}(只读值,从不调用值)。
|
|
358
380
|
*/
|
|
359
381
|
export declare function readRuleOffersAbsence(req: unknown): RuleOffersAbsence | undefined;
|
|
382
|
+
/**
|
|
383
|
+
* park 行 `requiresRealApproval` 座的读数(NP-1 起;此前是 {@link parkRowFacts} 函数体内的一行)—— **`=== true` 严判**,
|
|
384
|
+
* `false` 与其它值读作缺席(core d.ts「Absent otherwise (never `false`)」;与 core `summarizeCheckpoint` 同一条判法)。
|
|
385
|
+
* `kind` 由调用方先判(本函数只读这一位)。两个读者共用这一只,解析单源、处置各归读者(与 {@link readRuleOffersAbsenceSeat}
|
|
386
|
+
* 同一条分工):展示投影 {@link parkRowFacts}(队列行顶层展开)与耐久 `/decide` 腿的 remember 判据(`tool-approval.ts`
|
|
387
|
+
* 的 `parkRowStandingAnswerFacts`)。这一位在两处方向相同(在场才算、读不出 = 缺席)⇒ 不需要三态;也因此权限面读它
|
|
388
|
+
* **不经** `parkRowFacts` —— 那只展示投影顺手读 `ruleOffersAbsence` 并对集外词计展示面的 F 类 tag,而权限面对同一格是
|
|
389
|
+
* fail-closed 的另一种处置(S-663 codex r1 钉「权限面不计展示面 tag」)。
|
|
390
|
+
*/
|
|
391
|
+
export declare function readRequiresRealApprovalSeat(toolApproval: object): boolean;
|
|
392
|
+
/** core 寄存行的 `tool_approval` 臂(park 行事实全部住在这一臂上;其余臂没有工具字段)。 */
|
|
393
|
+
type ToolApprovalPark = Extract<CorePendingAction, {
|
|
394
|
+
kind: "tool_approval";
|
|
395
|
+
}>;
|
|
396
|
+
/**
|
|
397
|
+
* 🔴 S-700 P1(client-core CC-180 / cli L-652 的根子;板 [ref] 订正 → [ref] 立案)—— **park 行事实**:
|
|
398
|
+
* 运维队列行(`GET /v1/approvals` + `/stream`)顶层展开的那几位。型**从 core 寄存行派生,不手抄**(S-249 同一条
|
|
399
|
+
* 纪律):core 改名 / 退役任一位 ⇒ 这里 tsc 红;这一位与 {@link RuleOffersAbsence}(从 `AskRequest` 派生)两个
|
|
400
|
+
* 联合漂开 ⇒ {@link parkRowFacts} 的返回处 tsc 红(core 说两座是同一个 factory 铸的同一闭集,本仓照此钉)。
|
|
401
|
+
*
|
|
402
|
+
* 两只店的 `PendingCheckpoint` **直接继承本型**(`extends`),于是 core 再给这一臂加一位同类事实时,改的只有
|
|
403
|
+
* 下面这张 Pick 表 + {@link parkRowFacts} 函数体一行,两店与路由零改。
|
|
404
|
+
* `mandated`(core #1079,7.31.0):7.30.1 的 `PendingAction` 上**没有**这一位 ⇒ 本版不铸;到货后表里加
|
|
405
|
+
* `"mandated"`、函数体按 `requiresRealApproval` 同式加一行。
|
|
406
|
+
*/
|
|
407
|
+
export type ParkRowFacts = Pick<ToolApprovalPark, "requiresRealApproval" | "ruleOffersAbsence">;
|
|
408
|
+
/**
|
|
409
|
+
* S-700 —— park 行事实的**唯一投影**(`pendingAction` 是寄存行上 core 铸的那一只,读自持久层 ⇒ `unknown`)。
|
|
410
|
+
*
|
|
411
|
+
* 病:core 在寄存行 `PendingAction.tool_approval` 上铸的「卡读者该看的事实」(core [ref] 原话:「the SAME fact,
|
|
412
|
+
* restated where a card reader looks for it」)中 `requiresRealApproval` 经 core `summarizeCheckpoint` 早就上了 inbox(`ruleOffersAbsence`
|
|
413
|
+
* 不在 core 的 `CheckpointSummary` 上),而运维队列的两只店
|
|
414
|
+
* `listPending` 是逐键手工组行、一位都没取 ⇒ 同一张卡「inbox 上看得到只有真人能清、队列上看不到」,壳的 park
|
|
415
|
+
* 卡因此恒不知道这件事(client-core 0.82.4 `26fca98b` 的透传在真部署上恒不触发)。
|
|
416
|
+
*
|
|
417
|
+
* 判据(每一条都是 core d.ts 的消费纪律,不是本仓自定):
|
|
418
|
+
* · **kind 先判**(「Every consumer that reads the tool fields MUST branch on `kind` first」)—— 非对象 / 缺席 /
|
|
419
|
+
* 非 `tool_approval` 臂 ⇒ `{}`,那些臂上出现的同名键不是这两位;
|
|
420
|
+
* · `requiresRealApproval` —— 经 {@link readRequiresRealApprovalSeat}(`=== true` 严判,真才带;`false` 与其它值读作
|
|
421
|
+
* 缺席,「Absent otherwise (never `false`)」)。与 core `summarizeCheckpoint` 逐字同一条判法 ⇒ inbox 行与队列行对同一张卡
|
|
422
|
+
* 同答(`test/park-row-facts.test.ts` 钉)。不计数:inbox 那一面对同一形同样静默缺席,两面同律;
|
|
423
|
+
* · `ruleOffersAbsence` —— 经 {@link readRuleOffersAbsence}(活卡帧 / `card_json` 同一只 schema、同一个集外 tag):
|
|
424
|
+
* park 孪生座与同步座是 core 同一个 factory 铸的同一闭集,不另起第二份词表;
|
|
425
|
+
* · 缺席 ≠ false:两位都只在「真」时在场,消费端读**在场**。
|
|
426
|
+
*
|
|
427
|
+
* 🔴 **这是展示/分诊投影,不是权限判据**(core 对两位的定性都是 display metadata:「the resume belts keep reading
|
|
428
|
+
* the gate's own bit」)。本投影对「在场却读不出」的方向是**缺席**(卡上少一行 ≪ 卡上出现生词);一条要从
|
|
429
|
+
* `ruleOffersAbsence` 推「强制」的**权限**判据需要的是三态(读不出 ⇒ 按强制,fail-closed),方向相反,所以权限面
|
|
430
|
+
* 不许拿本函数的产物去推强制 —— 两者共用的是 schema,不是折叠。
|
|
431
|
+
*/
|
|
432
|
+
export declare function parkRowFacts(pendingAction: unknown): ParkRowFacts;
|
|
360
433
|
/** S-114(core 7.4.0 [ref])—— 回落卡的计数与窗。`limit` 是**闭二词**(core d.ts 逐字),两个计数是
|
|
361
434
|
* 非负整数,`autoDenyAfterMs` 是 core 契约里的 `0..2147483647` 非负整数(`0` = 本卡不武装窗:部署把
|
|
362
435
|
* 旋钮关了,或 TOTAL 档的卡按 [ref]① 恒 0 等人)。四成员**全必填**——core 的 `DenialLimitFallback` 上
|
package/dist/approval-card.js
CHANGED
|
@@ -236,15 +236,48 @@ export function readRuleEvidence(req) {
|
|
|
236
236
|
const RULE_OFFERS_ABSENCE_VALUES = ["mandated", "lane_cannot_speak", "shadowed"];
|
|
237
237
|
export const RuleOffersAbsenceSchema = z.enum(RULE_OFFERS_ABSENCE_VALUES);
|
|
238
238
|
const RuleOffersAbsenceEnvelopeSchema = z.object({ ruleOffersAbsence: RuleOffersAbsenceSchema.optional() });
|
|
239
|
-
export function
|
|
240
|
-
const parsed = RuleOffersAbsenceEnvelopeSchema.safeParse(
|
|
239
|
+
export function readRuleOffersAbsenceSeat(x) {
|
|
240
|
+
const parsed = RuleOffersAbsenceEnvelopeSchema.safeParse(x);
|
|
241
241
|
if (parsed.success)
|
|
242
|
-
return parsed.data.ruleOffersAbsence;
|
|
243
|
-
const raw =
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
242
|
+
return parsed.data.ruleOffersAbsence === undefined ? { state: "absent" } : { state: "word", word: parsed.data.ruleOffersAbsence };
|
|
243
|
+
const raw = x !== null && typeof x === "object" ? x.ruleOffersAbsence : undefined;
|
|
244
|
+
return raw === undefined ? { state: "absent" } : { state: "unreadable", raw };
|
|
245
|
+
}
|
|
246
|
+
export function readRuleOffersAbsence(req) {
|
|
247
|
+
const seat = readRuleOffersAbsenceSeat(req);
|
|
248
|
+
switch (seat.state) {
|
|
249
|
+
case "word":
|
|
250
|
+
return seat.word;
|
|
251
|
+
case "absent":
|
|
252
|
+
return undefined;
|
|
253
|
+
case "unreadable":
|
|
254
|
+
recordFailOpen("server.approval-card.closed-word-out-of-set", `ruleOffersAbsence=${outOfSetDetail(seat.raw)}`);
|
|
255
|
+
return undefined;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function outOfSetDetail(raw) {
|
|
259
|
+
if (typeof raw === "string")
|
|
260
|
+
return redactSecrets(raw).slice(0, 40);
|
|
261
|
+
if (raw === null)
|
|
262
|
+
return "<null>";
|
|
263
|
+
if (Array.isArray(raw))
|
|
264
|
+
return "<array>";
|
|
265
|
+
if (typeof raw === "object" || typeof raw === "function")
|
|
266
|
+
return `<${typeof raw}>`;
|
|
267
|
+
return String(raw).slice(0, 40);
|
|
268
|
+
}
|
|
269
|
+
export function readRequiresRealApprovalSeat(toolApproval) {
|
|
270
|
+
const v = "requiresRealApproval" in toolApproval ? toolApproval.requiresRealApproval : undefined;
|
|
271
|
+
return v === true;
|
|
272
|
+
}
|
|
273
|
+
export function parkRowFacts(pendingAction) {
|
|
274
|
+
if (typeof pendingAction !== "object" || pendingAction === null || !("kind" in pendingAction) || pendingAction.kind !== "tool_approval")
|
|
275
|
+
return {};
|
|
276
|
+
const ruleOffersAbsence = readRuleOffersAbsence(pendingAction);
|
|
277
|
+
return {
|
|
278
|
+
...(readRequiresRealApprovalSeat(pendingAction) ? { requiresRealApproval: true } : {}),
|
|
279
|
+
...(ruleOffersAbsence !== undefined ? { ruleOffersAbsence } : {}),
|
|
280
|
+
};
|
|
248
281
|
}
|
|
249
282
|
const DenialLimitFallbackSchema = z
|
|
250
283
|
.object({
|
package/dist/approval.d.ts
CHANGED
|
@@ -7,7 +7,26 @@ import { type ToolPolicy } from "@sema-agent/core";
|
|
|
7
7
|
import { type PostureSource } from "./posture-source.js";
|
|
8
8
|
import { type ExecutionLane } from "./execution-lane-caps.js";
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* 门意图判据读的五个量(`ServiceConfig` 结构满足)。单独成型是为了让**热路径**能拿「候选视图」来判
|
|
11
|
+
* (S-668 波 2:`{ ...config, approvalRequire: 候选名单 }`)—— 判据只有一份,输入可以是活配置也可以是候选。
|
|
12
|
+
*/
|
|
13
|
+
export interface GateIntentView {
|
|
14
|
+
readonly approvalRequire: readonly string[];
|
|
15
|
+
readonly approvalDeny: readonly string[];
|
|
16
|
+
readonly approvalNeverAuto: readonly string[];
|
|
17
|
+
readonly durableApproval: boolean;
|
|
18
|
+
readonly durableApprovalSource: PostureSource;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 三张审批名单(require / deny / never-auto)里**有没有一张在场** —— 「这台部署有一份要执行的审批策略」。
|
|
22
|
+
*
|
|
23
|
+
* 🔴 S-668 波 2(codex r1 F1):leader 车道的 durable 审批席曾只按 `approvalRequire` 非空给出。require 名单转热之后,
|
|
24
|
+
* 中心热撤空它就把 leader worker 上**独立**的 deny / never-auto 两张表一起撤掉(主车道照旧 deny / ask)—— 三张表是
|
|
25
|
+
* 三条独立的限制,任何一张在场都要装策略。{@link hasOperatorGateIntent} 的名单三格就是本函数(同一判据,不写两份)。
|
|
26
|
+
*/
|
|
27
|
+
export declare function hasApprovalListIntent(config: Pick<GateIntentView, "approvalRequire" | "approvalDeny" | "approvalNeverAuto">): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* 运维**是否表达了门意图** —— 单用户 allow-all 基线只在"零门意图"时才允许铺开,
|
|
11
30
|
* 所以这个谓词漏一格 = 那一格的意图被 allow-all 静默吞掉。
|
|
12
31
|
*
|
|
13
32
|
* 🔴 由来(2026-07-31 缝合审):这判据本来是 `main.ts` 里的一行内联表达式,只枚举了
|
|
@@ -20,26 +39,31 @@ import { type ExecutionLane } from "./execution-lane-caps.js";
|
|
|
20
39
|
* 判定挪到**与 inv#2 同一个文件**就是为了这个:两者再想漂开,得有人同时改这两段。
|
|
21
40
|
* 新增任何"门意图"配置项时,这里必须同步加一格(下面的表驱动测试会点名漏的那格)。
|
|
22
41
|
*/
|
|
23
|
-
export declare function hasOperatorGateIntent(config:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
42
|
+
export declare function hasOperatorGateIntent(config: GateIntentView): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* 单用户 turnkey 的 **auto-accept 基线**适用吗 —— 单用户(未开 `REQUIRE_PRINCIPAL`)∧ 运维零门意图。
|
|
45
|
+
*
|
|
46
|
+
* 🔴 S-668 波 2 ③:**每请求现算**,不是 boot 常量。判据的输入 `approvalRequire` 自本批起在进程内会被中心
|
|
47
|
+
* 热换;boot 期算好的一个布尔会让「名单从空变非空」之后 allow-all 基线仍挂在每个新任务上 —— 运维刚表达的
|
|
48
|
+
* 门意图被基线静默吞掉([ref] 方向)。所以消费点(`boot/resolve-spec.ts` 每个任务、stage-07 的 boot 姿态行、
|
|
49
|
+
* run-local 的补偿 warn)一律调本函数,谁也不持有它的快照。
|
|
50
|
+
*/
|
|
51
|
+
export declare function singleUserAutoAcceptBaselineApplies(config: GateIntentView & {
|
|
52
|
+
readonly requirePrincipal: boolean;
|
|
29
53
|
}): boolean;
|
|
30
54
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
55
|
+
* 门意图**不可服务**的判据 —— 返回拒因(可服务 ⇒ `undefined`)。**全仓唯一一份**,两处调用、处置不同:
|
|
56
|
+
* · **boot**(`boot/stage-07-capability-layer.ts`):对装配完的整份 config 判,拒因 ⇒ **拒启**(全窗复审 D3-F1,
|
|
57
|
+
* HIGH;与 env 墓碑族同谱系)。v4.3.0 的轮询门形(APPROVAL_REQUIRE + DB backend + DURABLE_APPROVAL 未设)在
|
|
58
|
+
* 5.0.0 只剩 core 每任务 warn——**原先拦、现在放**(方向反转)。「留 undefined 让 core warn」对新配置是
|
|
59
|
+
* 曝露误配,对升级存量是门静默消失,后者必须响亮。
|
|
60
|
+
* · **热路径**(S-668 波 2 ④,`config-center/apply-effective.ts` 的审批组 stage):对**候选视图**
|
|
61
|
+
* (活配置 + 候选名单)判,拒因 ⇒ 审批组**整组拒**、活配置零变化、世代账停旧代。进程在跑,拒启不是选项;
|
|
62
|
+
* 而放行一份「没有 checkpoint 店可停车」的名单 = 单用户 auto-accept 基线仍在、名单静默不生效。
|
|
63
|
+
* `checkpointStorePresent` 是**部署事实**(本进程建没建出 checkpoint 店),不在 `ServiceConfig` 里 ⇒ 调用方显式递。
|
|
64
|
+
* 放这文件与 hasOperatorGateIntent/inv#2 同源(意图判据再漂要同时改两段)。
|
|
35
65
|
*/
|
|
36
|
-
export declare function
|
|
37
|
-
approvalRequire: readonly string[];
|
|
38
|
-
approvalDeny: readonly string[];
|
|
39
|
-
approvalNeverAuto: readonly string[];
|
|
40
|
-
durableApproval: boolean;
|
|
41
|
-
durableApprovalSource: PostureSource;
|
|
42
|
-
}, checkpointStorePresent: boolean): void;
|
|
66
|
+
export declare function gateIntentUnserviceableReason(config: GateIntentView, checkpointStorePresent: boolean): string | undefined;
|
|
43
67
|
/**
|
|
44
68
|
* S-602 C3 —— 「**无应答面**」两条 boot warn 的判据与文案(纯函数;stage-07 只负责打日志)。
|
|
45
69
|
*
|
|
@@ -85,8 +109,8 @@ export declare function buildNoResponderBootWarns(input: {
|
|
|
85
109
|
* 为什么在 **boot** 判而不是 resolve 时判:两个入参都是**部署级**的(entitlement 源在不在、durable 门开
|
|
86
110
|
* 不开),per-principal 的那一半改变不了结论;放 resolve 里就得自己造去重,而 boot 天然只跑一次。
|
|
87
111
|
*
|
|
88
|
-
* 纯函数(返回一行或 undefined,不自己写日志)= 红先测得动;调用点在
|
|
89
|
-
* {@link
|
|
112
|
+
* 纯函数(返回一行或 undefined,不自己写日志)= 红先测得动;调用点在 stage-07 的
|
|
113
|
+
* {@link gateIntentUnserviceableReason} 拒启判之后(同一段门装配)。
|
|
90
114
|
*/
|
|
91
115
|
export declare function buildForceDurableGateInertNotice(input: {
|
|
92
116
|
/** center per-principal entitlement 源在不在(`centerEntitlementSourceWired` 的结果 —— 判据单源在那里)。 */
|
package/dist/approval.js
CHANGED
|
@@ -3,19 +3,27 @@ import { operatorAsk } from "./operator-ask.js";
|
|
|
3
3
|
import { ASK_USER_QUESTION_TOOL_NAME } from "./approval-content-kind.js";
|
|
4
4
|
import { isExplicitPosture } from "./posture-source.js";
|
|
5
5
|
import { handsOnWorkerFilePlane } from "./execution-lane-caps.js";
|
|
6
|
-
export function
|
|
6
|
+
export function hasApprovalListIntent(config) {
|
|
7
7
|
return (config.approvalRequire.length > 0 ||
|
|
8
8
|
config.approvalDeny.length > 0 ||
|
|
9
|
-
config.approvalNeverAuto.length > 0
|
|
9
|
+
config.approvalNeverAuto.length > 0);
|
|
10
|
+
}
|
|
11
|
+
export function hasOperatorGateIntent(config) {
|
|
12
|
+
return (hasApprovalListIntent(config) ||
|
|
10
13
|
(config.durableApproval && isExplicitPosture(config.durableApprovalSource)));
|
|
11
14
|
}
|
|
12
|
-
export function
|
|
15
|
+
export function singleUserAutoAcceptBaselineApplies(config) {
|
|
16
|
+
return config.requirePrincipal !== true && !hasOperatorGateIntent(config);
|
|
17
|
+
}
|
|
18
|
+
export function gateIntentUnserviceableReason(config, checkpointStorePresent) {
|
|
13
19
|
if (!hasOperatorGateIntent(config) || checkpointStorePresent)
|
|
14
|
-
return;
|
|
20
|
+
return undefined;
|
|
15
21
|
if (!config.durableApproval) {
|
|
16
|
-
|
|
22
|
+
return ("an approval list is in force (APPROVAL_REQUIRE / APPROVAL_DENY / APPROVAL_NEVER_AUTO, or the center's governance.approvalRequire) but the durable gate is off — " +
|
|
23
|
+
"since 5.0.0 the poll lane is retired and durable is the ONLY gate, so the list would never be enforced. Set DURABLE_APPROVAL=true (with a DB/file backend that has a checkpoint face), " +
|
|
24
|
+
"or remove the approval lists to run ungated on purpose.");
|
|
17
25
|
}
|
|
18
|
-
|
|
26
|
+
return "DURABLE_APPROVAL=true but no checkpoint store is available — the configured DB backend has no checkpoint face (or no backend is configured). Wire a MySQL-protocol/PostgreSQL/file backend, or unset DURABLE_APPROVAL.";
|
|
19
27
|
}
|
|
20
28
|
export function buildNoResponderBootWarns(input) {
|
|
21
29
|
if (input.approvalFaceWired)
|
|
@@ -8,6 +8,7 @@ import { type ModelKeyRef } from "../key-resolver.js";
|
|
|
8
8
|
import type { Logger } from "../observability/logger.js";
|
|
9
9
|
import type { Metrics } from "../observability/metrics.js";
|
|
10
10
|
import type { UnpricedCeilingVerdict } from "./unpriced-ceiling-verdict.js";
|
|
11
|
+
import type { ConsolidationSeatWatch } from "./memory-consolidation.js";
|
|
11
12
|
import { type RestartSignal } from "../config-center/facade.js";
|
|
12
13
|
import { type ConfigApplyLedgerView } from "../config-center/apply-ledger.js";
|
|
13
14
|
import type { LimitSync } from "./limit-sync.js";
|
|
@@ -43,19 +44,25 @@ export interface ConfigCenterRuntime {
|
|
|
43
44
|
/** 60s refresh cadence + boot-deferred 到货续接。
|
|
44
45
|
* `limitSync`([ref] 批1)= 恒构造的两只限额座的换代口:commit 之后**零 await 内**推一把,与 pricing /
|
|
45
46
|
* keyResolver 那两件派生重建同族(缺席 = 这条腿本部署没装配,例如 run-local)。
|
|
46
|
-
* `swapRunnerDeps`(core 7.10.0 `Runner.swapDeps`
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* `swapRunnerDeps`(core 7.10.0 `Runner.swapDeps` 一扇门)= **可换席**的换装口,**必填**:模型面 plane
|
|
48
|
+
* 变更候选在 commit 前喂给全部 boot Runner 原子换代;S-174 起 read **face** 席也走同一只函数(见 refresh
|
|
49
|
+
* 拍里的 `applyLiveReadFace`)。S-668 波 0 起必填 —— 它缺席的那一形(模型面整面 defer 到重启 + `models-tiers`
|
|
50
|
+
* 重启片)在生产上从来到不了(stage-08 唯一调用点恒传),随片一起退役;要刷新环就要有 Runner 可换。
|
|
50
51
|
* `ceilingVerdict`(S-232)= 「配了 $ 天花板但目录未定价」这条判决的活载体,与 `limitSync` **同族同序**
|
|
51
52
|
* (commit 之后、零 await 内重判一次;判决不翻转就静默)。缺席 = 这条腿本部署没装配(run-local 一次性
|
|
52
|
-
* CLI 之后不再有刷新拍,它继续用纯判据判一次)。
|
|
53
|
+
* CLI 之后不再有刷新拍,它继续用纯判据判一次)。
|
|
54
|
+
* `consolidationSeat`(S-668 波 0,过渡)= 整理驱动席的两侧读数口,喂 `memory-consolidation` 重启片;
|
|
55
|
+
* 缺席 = 阀门关着(没有 boot 烤死的席)。
|
|
56
|
+
* `checkpointStorePresent`(S-668 波 2,**必填**)= 部署事实「本进程建没建出 checkpoint 店」(stage-06 的产物,
|
|
57
|
+
* 不在 ServiceConfig 里)。审批名单转热之后,热腿要用它判 ④「门意图不可服务」(与 boot 拒启同一只判据);
|
|
58
|
+
* 必填 = 刷新环不可能在不知道这件事的情况下热应用审批名单。 */
|
|
53
59
|
startRefreshLoop(a: {
|
|
54
|
-
runnerTierFrozen: boolean;
|
|
55
60
|
pricing: ReturnType<typeof buildPricing>;
|
|
56
61
|
limitSync?: LimitSync;
|
|
57
|
-
swapRunnerDeps
|
|
62
|
+
swapRunnerDeps: (next: SwappableDeps) => void;
|
|
58
63
|
ceilingVerdict?: UnpricedCeilingVerdict;
|
|
64
|
+
consolidationSeat?: ConsolidationSeatWatch;
|
|
65
|
+
checkpointStorePresent: boolean;
|
|
59
66
|
}): void;
|
|
60
67
|
/** [ref]-2:停刷新环(hardShutdown 收尾链;幂等,未起环时 no-op)。 */
|
|
61
68
|
stopRefreshLoop(): void;
|
|
@@ -78,7 +85,8 @@ export interface ConfigCenterRuntime {
|
|
|
78
85
|
modelReady(): boolean;
|
|
79
86
|
/** /health.restart(orchestrator 自动重启信号)。 */
|
|
80
87
|
restartState(): RestartSignal | undefined;
|
|
81
|
-
/** /health.modelPlaneDeferred
|
|
88
|
+
/** /health.modelPlaneDeferred:被扣着、还没有 next-boot handoff 的候选(codex R18 起的状态机)。S-668 波 0 起
|
|
89
|
+
* 模型面不再 defer,键名保留,今天承载的是 durable LKG 发布债与 skills 债(见 `planeDeferredNoHandoff`)。 */
|
|
82
90
|
planeDeferredState(): {
|
|
83
91
|
version: number;
|
|
84
92
|
since: number;
|