@sema-agent/server 7.43.0 → 7.44.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/USAGE.md +18 -0
- package/dist/adoption/plan.js +31 -192
- package/dist/adoption/quiesce.js +3 -86
- package/dist/adoption/runner.js +3 -140
- package/dist/adoption/sql.js +0 -74
- package/dist/adoption/wire.js +0 -80
- package/dist/approval-ask-machine.js +0 -75
- package/dist/approval-card.js +0 -323
- package/dist/approval-deny-reasons.js +0 -42
- package/dist/approval-hmac.js +0 -35
- package/dist/approval-reconciler.js +8 -166
- package/dist/approval.js +4 -67
- package/dist/audit.js +1 -44
- package/dist/auth-bridge.js +4 -47
- package/dist/auth-keys.js +0 -23
- package/dist/bake-runner/main.js +4 -65
- package/dist/bake-runner/protocol.js +3 -58
- package/dist/bake-runner/runner.js +5 -91
- package/dist/bench/l8/artifact.js +2 -61
- package/dist/bench/l8/escape.js +0 -25
- package/dist/bench/l8/index.js +0 -14
- package/dist/bench/l8/probes.js +0 -60
- package/dist/bench/l8/run-probes.js +2 -45
- package/dist/bench/s1/arms.js +14 -189
- package/dist/bench/s1/live-deps.js +11 -253
- package/dist/bench/s1/oracle.js +1 -36
- package/dist/bench/s1/repair-oracle-adapter.js +0 -30
- package/dist/bench/s1/reviewer.js +0 -34
- package/dist/bench/s1/row.js +0 -62
- package/dist/bench/s1/run-firm.js +4 -70
- package/dist/bench/s1/runner-ctx.js +0 -40
- package/dist/bench/s1/tasks.js +0 -115
- package/dist/boot/adoption.js +0 -20
- package/dist/boot/budget-tracing.js +3 -55
- package/dist/boot/config-center.js +43 -551
- package/dist/boot/coordinators.js +1 -69
- package/dist/boot/crash-last.js +0 -18
- package/dist/boot/deferred-sandbox-path-env.js +3 -119
- package/dist/boot/execution-env.js +5 -171
- package/dist/boot/governance-seams.js +0 -92
- package/dist/boot/leader.js +0 -69
- package/dist/boot/limit-sync.js +0 -2
- package/dist/boot/memory-boundary.js +3 -91
- package/dist/boot/org-memory.js +1 -25
- package/dist/boot/parked-revive-gate.js +0 -150
- package/dist/boot/permission-rules-audit.js +1 -56
- package/dist/boot/reapers.js +15 -273
- package/dist/boot/resolve-spec.js +9 -768
- package/dist/boot/retention-lane.js +4 -87
- package/dist/boot/runner-deps.js +3 -297
- package/dist/boot/runtime-caps.js +0 -40
- package/dist/boot/session-faces.js +2 -133
- package/dist/boot/shutdown.js +9 -83
- package/dist/boot/side-query-lane.js +2 -137
- package/dist/boot/stores.js +15 -215
- package/dist/boot/task-list-lane.js +0 -18
- package/dist/boot/webfetch-summarize-lane.js +0 -47
- package/dist/boot/workflow-orchestration.js +3 -99
- package/dist/boot-reclaim.js +0 -20
- package/dist/bounded-session-map.js +0 -19
- package/dist/brain.js +2 -139
- package/dist/budget.js +9 -244
- package/dist/capabilities/builtin-tools.js +0 -3
- package/dist/capabilities/center-plugins.js +6 -51
- package/dist/capabilities/center-prompts.js +6 -71
- package/dist/capabilities/code-review-council.js +7 -40
- package/dist/capabilities/collab-workflows.js +1 -44
- package/dist/capabilities/hands-lane.js +0 -65
- package/dist/capabilities/memory-notice.js +0 -70
- package/dist/capabilities/prompt.js +0 -14
- package/dist/capabilities/prompts/code-review.js +0 -14
- package/dist/capabilities/prompts/identity.js +0 -6
- package/dist/capabilities/prompts/team.js +0 -4
- package/dist/capabilities/repo-tools.js +0 -34
- package/dist/capabilities/sandbox-file-send.js +3 -92
- package/dist/capabilities/scenarios.d.ts +0 -1
- package/dist/capabilities/scenarios.js +18 -279
- package/dist/capabilities/select-environment-tool.js +0 -32
- package/dist/capabilities/send-user-file-tool.js +2 -66
- package/dist/capabilities/skills.d.ts +1 -2
- package/dist/capabilities/skills.js +3 -21
- package/dist/capabilities/team.d.ts +3 -11
- package/dist/capabilities/team.js +3 -51
- package/dist/capabilities/tool-defer.js +0 -3
- package/dist/config-center/apply-effective.js +15 -330
- package/dist/config-center/apply-ledger.js +5 -38
- package/dist/config-center/facade.js +0 -41
- package/dist/config-center/hot-keys-registry.js +0 -20
- package/dist/config-center/http-client.js +2 -125
- package/dist/config-center/mcp-revocation.js +2 -34
- package/dist/config-center/read-face.js +0 -59
- package/dist/config-center/restart-signal.js +1 -85
- package/dist/config-center/skills-mcp.d.ts +1 -1
- package/dist/config-center/skills-mcp.js +9 -76
- package/dist/config-center/stage-limits.js +8 -35
- package/dist/config-invariants.js +0 -16
- package/dist/config-lkg.js +0 -42
- package/dist/config-provider.js +3 -186
- package/dist/config-types.js +0 -5
- package/dist/config.js +107 -1145
- package/dist/degenerate-instrument.js +3 -67
- package/dist/deployment-governance.js +0 -124
- package/dist/digest-form.js +0 -12
- package/dist/elicitation.js +3 -86
- package/dist/env-facts.js +7 -75
- package/dist/fleet/fleet-bus.js +34 -507
- package/dist/fleet/fleet-reconciler.js +9 -149
- package/dist/fleet/fleet-terminal-window.js +10 -178
- package/dist/fleet/subagent-tail-bus.js +3 -72
- package/dist/fleet-client.js +10 -70
- package/dist/fleet-lease.js +5 -79
- package/dist/git-api-kind.js +0 -3
- package/dist/governance-ask-marks.js +2 -78
- package/dist/hooks/branch-transcript.js +0 -74
- package/dist/hooks/cc-agent-hook-prompt.js +0 -29
- package/dist/hooks/cc-stop-prompt.js +1 -46
- package/dist/hooks/hook-llm.js +1 -53
- package/dist/hooks/hook-runner.js +20 -414
- package/dist/http/active-run-conflict.js +4 -129
- package/dist/http/cursor-fingerprint.d.ts +5 -0
- package/dist/http/cursor-fingerprint.js +5 -0
- package/dist/http/idempotency.js +0 -37
- package/dist/http/principal-gate.js +3 -40
- package/dist/http/route-ctx.js +0 -9
- package/dist/http/routes/a2a-serve.js +7 -319
- package/dist/http/routes/admin-config-refresh.js +0 -4
- package/dist/http/routes/admin-drain.js +0 -10
- package/dist/http/routes/adoption.js +1 -29
- package/dist/http/routes/agents-roster.js +1 -47
- package/dist/http/routes/approvals-assistant.js +32 -395
- package/dist/http/routes/attachments.js +4 -22
- package/dist/http/routes/capabilities.js +3 -420
- package/dist/http/routes/diagnostics.js +1 -81
- package/dist/http/routes/fleet.js +9 -185
- package/dist/http/routes/images.js +14 -239
- package/dist/http/routes/leader.js +0 -13
- package/dist/http/routes/memory-bundle.js +1 -61
- package/dist/http/routes/memory-policy.js +9 -99
- package/dist/http/routes/notify-wake.js +3 -37
- package/dist/http/routes/observability.js +2 -19
- package/dist/http/routes/retention-ops.js +2 -34
- package/dist/http/routes/rules.js +1 -93
- package/dist/http/routes/runs.js +64 -873
- package/dist/http/routes/session-sync.js +19 -258
- package/dist/http/routes/sessions-list.js +17 -43
- package/dist/http/routes/sessions.js +34 -226
- package/dist/http/routes/shared-memory.js +5 -36
- package/dist/http/routes/side-query.js +1 -87
- package/dist/http/routes/tasks.js +52 -722
- package/dist/http/routes/trace-usage.js +32 -195
- package/dist/http/routes/workflows.js +19 -195
- package/dist/http/run-meta.js +0 -6
- package/dist/http/send.js +0 -32
- package/dist/http/server.js +92 -1597
- package/dist/http/sse-lifecycle.js +2 -13
- package/dist/http/sse-log.js +3 -48
- package/dist/http/tar.js +5 -21
- package/dist/http/verify-rounds.js +0 -5
- package/dist/http/wire-gate.js +0 -9
- package/dist/http/workspace-content.js +0 -10
- package/dist/images/bake-validate.js +1 -70
- package/dist/images/manifest.js +1 -6
- package/dist/index.js +0 -21
- package/dist/key-resolver.js +2 -17
- package/dist/leader/diffout.js +1 -20
- package/dist/leader/diffup.js +0 -47
- package/dist/leader/endpoint.js +2 -57
- package/dist/leader/fanout.js +3 -45
- package/dist/leader/grader-env-factory.js +3 -72
- package/dist/leader/leader.js +5 -156
- package/dist/leader/merge.js +8 -115
- package/dist/leader/planner.js +3 -54
- package/dist/leader/repair-oracle.js +1 -60
- package/dist/leader/repair-wire.js +2 -79
- package/dist/leader/wire.js +8 -307
- package/dist/lsp/e2b-bridge.js +4 -64
- package/dist/lsp/e2b-manager.js +6 -94
- package/dist/lsp/lsp-frames.js +0 -12
- package/dist/lsp/manager.js +4 -96
- package/dist/lsp/ws-transport.js +5 -55
- package/dist/lsp-evict.js +1 -15
- package/dist/main.js +57 -765
- package/dist/memory-bundle-engine.js +0 -55
- package/dist/memory-export.js +0 -4
- package/dist/memory-posture.js +1 -15
- package/dist/memory-scope.js +11 -148
- package/dist/memory-sync-client.js +2 -44
- package/dist/memory-sync.js +1 -80
- package/dist/model-select.js +3 -80
- package/dist/observability/cost-quota.js +1 -17
- package/dist/observability/cost-taxonomy.js +0 -34
- package/dist/observability/fail-open.js +7 -86
- package/dist/observability/logger.js +0 -6
- package/dist/observability/metrics.js +0 -94
- package/dist/observability/otel-exporter.js +3 -13
- package/dist/observability/principal-context.js +0 -9
- package/dist/observability/prompt-manifest.js +1 -37
- package/dist/observability/rate-limit.js +0 -4
- package/dist/observability/secret-env-scrub.js +2 -56
- package/dist/observability/tool-trace.js +1 -70
- package/dist/orchestration/hardened-vm-runner.js +4 -118
- package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
- package/dist/orchestration/hardened-vm-worker.js +0 -27
- package/dist/orchestration/subagent-steer.js +1 -45
- package/dist/orchestration/workflow-agent-steer.js +1 -80
- package/dist/orchestration/workflow-completion-inbox.js +32 -285
- package/dist/orchestration/workflow-notify-journal.js +16 -259
- package/dist/org-memory-admission.js +3 -47
- package/dist/parent-watch.js +2 -48
- package/dist/parked-decide.js +1 -109
- package/dist/per-task-image.js +0 -57
- package/dist/plan-cache-probe.js +3 -27
- package/dist/plugins/adoption-log-sql.js +2 -119
- package/dist/plugins/approval-ask-store-memory.js +3 -38
- package/dist/plugins/approval-ask-store-sql.js +6 -188
- package/dist/plugins/approval-exemption-store.js +2 -28
- package/dist/plugins/background-agent-store-sql.js +4 -105
- package/dist/plugins/background-shell-support.js +14 -122
- package/dist/plugins/blob-backend.js +6 -169
- package/dist/plugins/breaker-state-sql.js +8 -46
- package/dist/plugins/caching-session-store.js +4 -106
- package/dist/plugins/checkpoint-store-sql.js +18 -505
- package/dist/plugins/e2b-orphan-reclaim.js +0 -45
- package/dist/plugins/file-outcome-sink.js +0 -9
- package/dist/plugins/file-resume-anchor-store.js +4 -43
- package/dist/plugins/file-run-store.js +26 -364
- package/dist/plugins/file-snapshot-store-sql.js +10 -181
- package/dist/plugins/fork-routing-session-store.js +8 -111
- package/dist/plugins/host-platform.js +2 -91
- package/dist/plugins/image-bake-store-sql.js +7 -250
- package/dist/plugins/image-index-sql.js +4 -123
- package/dist/plugins/k8s-bg-scripts.js +4 -88
- package/dist/plugins/k8s-exec-protocol.js +0 -41
- package/dist/plugins/leader-run-store-sql.js +0 -101
- package/dist/plugins/local-checkpoint-store.js +8 -128
- package/dist/plugins/local-session-store.js +34 -296
- package/dist/plugins/local-task-attachment-store.js +2 -16
- package/dist/plugins/mailbox-store-sql.js +8 -65
- package/dist/plugins/memory-embedder-fingerprint.js +5 -166
- package/dist/plugins/memory-embedder.js +4 -70
- package/dist/plugins/memory-engine-pg.js +6 -170
- package/dist/plugins/memory-engine-tidb.js +7 -155
- package/dist/plugins/memory-engine-vector-util.js +0 -10
- package/dist/plugins/memory-key-guards.js +0 -34
- package/dist/plugins/memory-origin-law.js +0 -187
- package/dist/plugins/memory-resume-anchor-store.js +0 -17
- package/dist/plugins/memory-run-store.js +12 -89
- package/dist/plugins/memory-session-policy-store.js +0 -17
- package/dist/plugins/memory-sync-store-pg.js +4 -49
- package/dist/plugins/memory-sync-store-tidb.js +3 -35
- package/dist/plugins/outcome-ledger-sql.js +3 -97
- package/dist/plugins/permission-rule-store-file.js +5 -133
- package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
- package/dist/plugins/permission-rule-store-sql.js +50 -307
- package/dist/plugins/pg-cost-quota.js +0 -7
- package/dist/plugins/pg-pool.js +0 -92
- package/dist/plugins/pg-rate-limiter.js +2 -13
- package/dist/plugins/pg-safe-json.js +4 -40
- package/dist/plugins/pg-session-storage.js +25 -189
- package/dist/plugins/posix-shell-fs.js +1 -31
- package/dist/plugins/remote-env-adb.js +12 -101
- package/dist/plugins/remote-env-e2b.js +40 -371
- package/dist/plugins/remote-env-file-error.js +0 -37
- package/dist/plugins/remote-env-host.js +63 -483
- package/dist/plugins/remote-env-k8s.js +32 -326
- package/dist/plugins/remote-env-local-docker.js +24 -157
- package/dist/plugins/remote-env-ssh.js +20 -128
- package/dist/plugins/remote-scratchpad.js +2 -32
- package/dist/plugins/remote-shell.js +1 -32
- package/dist/plugins/resume-anchor-store-sql.js +0 -11
- package/dist/plugins/retention-lane-store-sql.js +0 -108
- package/dist/plugins/retention-store-sql.js +4 -383
- package/dist/plugins/roster-store-sql.js +0 -55
- package/dist/plugins/run-store-sql.js +14 -251
- package/dist/plugins/s3-presign.js +2 -49
- package/dist/plugins/scheduler-support.js +3 -80
- package/dist/plugins/send-file-ledger.js +4 -53
- package/dist/plugins/send-user-file.js +4 -94
- package/dist/plugins/session-placement.js +1 -89
- package/dist/plugins/session-policy-store-sql.js +3 -81
- package/dist/plugins/session-store.js +0 -57
- package/dist/plugins/shared-memory-store-sql.js +4 -167
- package/dist/plugins/sql-driver.js +0 -17
- package/dist/plugins/sql-errors.js +0 -7
- package/dist/plugins/sql-escape.js +0 -8
- package/dist/plugins/sql-row-helpers.js +0 -25
- package/dist/plugins/store-backend.js +42 -222
- package/dist/plugins/store-contracts.js +2 -46
- package/dist/plugins/task-attachment-store.js +3 -49
- package/dist/plugins/task-list-store-sql.js +0 -79
- package/dist/plugins/tidb-cost-quota.js +1 -4
- package/dist/plugins/tidb-pool.js +1 -207
- package/dist/plugins/tidb-rate-limiter.js +3 -9
- package/dist/plugins/tidb-session-storage.js +4 -70
- package/dist/plugins/tidb-session-store.js +19 -341
- package/dist/plugins/tool-result-store-sql.js +4 -179
- package/dist/plugins/usage-window-store-sql.js +0 -8
- package/dist/plugins/web-search.js +10 -132
- package/dist/plugins/workflow-journal-store-sql.js +2 -58
- package/dist/plugins/workflow-run-store-sql.js +6 -91
- package/dist/plugins/worktree-isolation.js +6 -126
- package/dist/plugins/write-behind-counter.js +16 -75
- package/dist/principal-jwt.js +5 -60
- package/dist/project-memory.js +15 -146
- package/dist/prompts-domain-validate.js +1 -51
- package/dist/question.js +2 -111
- package/dist/resource-suspend.js +0 -18
- package/dist/router/route-orchestration.js +0 -77
- package/dist/rules-consent.d.ts +44 -5
- package/dist/rules-consent.js +75 -215
- package/dist/run-local.js +14 -381
- package/dist/runs.js +29 -617
- package/dist/runtime-caps-resolver.js +6 -132
- package/dist/runtime-governance.js +1 -232
- package/dist/sandbox-pkg-source.js +0 -37
- package/dist/sealed-key.js +3 -68
- package/dist/security.js +6 -291
- package/dist/session-leaf-bus.js +0 -32
- package/dist/session-sync-content.js +1 -69
- package/dist/session-sync-kernel.js +3 -60
- package/dist/session-sync.js +3 -66
- package/dist/session-titler.js +7 -41
- package/dist/session-watch.js +9 -73
- package/dist/shared-memory-scope-authorizer.js +0 -18
- package/dist/sighup-idle.js +1 -12
- package/dist/spec-fields.js +4 -143
- package/dist/store-live-probe.js +3 -49
- package/dist/task-a2a.js +1 -126
- package/dist/task-cwd.js +1 -103
- package/dist/task-mcp.js +1 -89
- package/dist/task-settings.js +10 -300
- package/dist/task-workflow.js +8 -75
- package/dist/tool-approval.d.ts +28 -1
- package/dist/tool-approval.js +70 -1430
- package/dist/trace/artifacts.js +5 -20
- package/dist/trace/engine-notice-wire.js +6 -138
- package/dist/trace/ledger-sink.js +7 -96
- package/dist/trace/project.js +4 -448
- package/dist/trace/redact.js +9 -77
- package/dist/turn-activity.js +1 -27
- package/dist/usage-analytics.js +4 -34
- package/dist/wall-clock-jump-guard.js +1 -68
- package/package.json +3 -3
- package/dist/capabilities/scenario-alias.d.ts +0 -27
- package/dist/capabilities/scenario-alias.js +0 -61
|
@@ -1,48 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* center prompts 消费投影腿([1043]④/[1050]③ 分工:web 承存储+covering 解析+下发,server 承本模块;
|
|
3
|
-
* [1057] 下发形定稿 / [1061] registry-core 0.10.16 schema / [1062]⑤「server 零新义务=逐字透传」)。
|
|
4
|
-
*
|
|
5
|
-
* 链路:center(sema-web)把 covering 走完的**基线终形**经 `GET /api/config/effective` 的 additive
|
|
6
|
-
* `prompts` key 下发 → 本模块按任务 scenario 选包(`scenarioOverrides[s] ?? sections`,整包替换非增量,
|
|
7
|
-
* [1057]①c)→ 声明数组**逐字**(含 opt-in `contentHash`,core 1.315 校验+manifest 透传)喂 core 既有
|
|
8
|
-
* typed `stableBlocks` 钩子。守卫全在 core(id 规范/slot 闭集/core/ 命名空间拒绝/identity 三锚
|
|
9
|
-
* pass-through/锁定槽不可写)——server 不做语义复检([1057]①f:identity 完整角色层由 center 编辑面把关)。
|
|
10
|
-
*
|
|
11
|
-
* 仅有的一层「形校验」不是语义复检,是**防炸底线**(详见其现居所 `src/prompts-domain-validate.ts`——
|
|
12
|
-
* 判形半场已下沉到该中立叶子,本文件 re-export 保兼容;design/158 S6,lens2 §G):core 对坏形声明的
|
|
13
|
-
* 守卫是 THROW(assemble 期),server 在采用前做结构判形,坏形=拒绝采用该候选的 prompts 面。
|
|
14
|
-
*
|
|
15
|
-
* 生效语义(两段史):1.222 时 core 1.315 的 epoch 是 bundled-only(声明不进 descriptor),热换=resume
|
|
16
|
-
* 三失真,故临时 restart-to-apply;core 1.316([1068] 裁 a/[1070]d)把声明以 (id,slot,chars,contentHash?)
|
|
17
|
-
* 纳入 artifactDigest——声明变=digest 变=**下任务边界自动重 pin**(既有 legacy_migration 机制接手),
|
|
18
|
-
* 进行中会话 epoch pin 保稳。自此恢复**热采用**(main.ts boot+refresh 双点 adopt),与 center
|
|
19
|
-
* 「发布=新任务生效」产品语义对齐([1051]②b)。字节级检测只认 opt-in contentHash(文本不进 digest,
|
|
20
|
-
* 防会话可导出面字典预映)——center 链路恒逐 section 铸([1065]),本投影逐字透传即全强度。
|
|
21
|
-
*/
|
|
22
1
|
import { verifyPromptArtifact } from "@sema-agent/core";
|
|
23
2
|
import { CORE_ENGINE_VERSION } from "../prompts-domain-validate.js";
|
|
24
|
-
import { scenarioConfigKeys } from "./scenario-alias.js";
|
|
25
3
|
import { SHA256_HEX_RE } from "../digest-form.js";
|
|
26
4
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
27
|
-
/** 判形半场(validateCenterPrompts/validatePromptsDomain/CORE_ENGINE_VERSION 及两 interface)已下沉到
|
|
28
|
-
* 中立叶子 `src/prompts-domain-validate.ts`(design/158 S6);消费者直引真源([2354] 兼容面全清,
|
|
29
|
-
* 此处兼容 re-export 已删)。 */
|
|
30
|
-
/** [985]b / [1285] — §9.4 by-digest 补拉组合店:local miss ⇒ fetchRaw(digest) 从 center 拉 envelope ⇒
|
|
31
|
-
* core verifyPromptArtifact 全管线 + **回验「拿到的=要的」digest 逐位**(center 答非所问=丢弃)⇒
|
|
32
|
-
* best-effort 回写 inner(下次直命中)。任何失败=undefined(诚实缺席,fail-loud 归 core 的
|
|
33
|
-
* prompt_snapshot_unavailable——绝不拼杂交)。 */
|
|
34
5
|
export function withPromptArtifactBackfill(inner, fetchRaw, log) {
|
|
35
|
-
// codex F1(补拉批):per-canonical-digest 单飞——冷副本上 N 个 pinned resume 同时 miss 同一 artifact
|
|
36
|
-
// 只发一次远拉(finally 清账);裸/大写形入口即正则化(FilePromptArtifactStore 只认 canonical 键,
|
|
37
|
-
// 不正则化=非 canonical 请求缓存永 miss 重拉)。坏形 digest 直拒(不上网)。负缓存有意不设:每次
|
|
38
|
-
// miss 都是用户驱动的 resume 尝试,量有界;404 重复由单飞在并发窗内已并。
|
|
39
6
|
const inFlight = new Map();
|
|
40
7
|
return {
|
|
41
8
|
put: (e) => inner.put(e),
|
|
42
9
|
get: async (digest, opts) => {
|
|
43
10
|
const hex = digest.replace(/^sha256:/i, "").toLowerCase();
|
|
44
11
|
if (!SHA256_HEX_RE.test(hex))
|
|
45
|
-
return undefined;
|
|
12
|
+
return undefined;
|
|
46
13
|
const canonical = `sha256:${hex}`;
|
|
47
14
|
const local = await inner.get(canonical, opts);
|
|
48
15
|
if (local)
|
|
@@ -58,8 +25,6 @@ export function withPromptArtifactBackfill(inner, fetchRaw, log) {
|
|
|
58
25
|
log.warn("center_prompts_backfill_rejected", { digest: canonical, ...(v.ok ? { got: v.artifact.artifactDigest, code: "digest_mismatch" } : { code: v.code, reason: v.reason }) });
|
|
59
26
|
return undefined;
|
|
60
27
|
}
|
|
61
|
-
// cache best-effort —— #157:F 类兜底(工件已验签且已返回;失败的代价只是下次再取一次网络),
|
|
62
|
-
// 留痕是为了让"缓存其实一直没写成"不必靠回填流量异常来发现。
|
|
63
28
|
await inner.put(raw).catch(() => recordFailOpen("server.prompts.artifact-cache-write-failed", `digest=${canonical}`));
|
|
64
29
|
log.info("center_prompts_backfilled", { digest: canonical });
|
|
65
30
|
return raw;
|
|
@@ -77,18 +42,11 @@ export function withPromptArtifactBackfill(inner, fetchRaw, log) {
|
|
|
77
42
|
},
|
|
78
43
|
};
|
|
79
44
|
}
|
|
80
|
-
/** e/b 接线([1236]① seam/[985]e):catalog 轴的两态过渡推进 core 的 CenterPromptSource——
|
|
81
|
-
* present(且身份变)⇒ applySnapshot(core 重验+落盘+原子换 candidate;validate 已过 core verify,
|
|
82
|
-
* 此处失败=磁盘/状态写问题,warn 不挡 declaration 轴);absent-after-present / prompts 键整体消失
|
|
83
|
-
* ⇒ applyDisabled(闸关=显式撤下语义的 catalog 轴半场,离线重启不复活)。幂等安全:同 envelope
|
|
84
|
-
* 重放=同 digest 覆盖写。 */
|
|
85
45
|
export async function applyCatalogToSource(source, next, prev, log, phase) {
|
|
86
|
-
// codex-2 F2:返回「过渡是否成功」——false 时 caller **不推进** centerPrompts(身份留在 prev),
|
|
87
|
-
// 下一拍 refresh 身份仍不等=同一过渡自动重试;吞错推进曾让失败的 apply/withdraw 永久静默。
|
|
88
46
|
try {
|
|
89
47
|
if (next?.catalog) {
|
|
90
48
|
if (prev?.identity === next.identity)
|
|
91
|
-
return true;
|
|
49
|
+
return true;
|
|
92
50
|
const r = await source.applySnapshot(next.catalog);
|
|
93
51
|
if (r.ok) {
|
|
94
52
|
log.info("center_prompts_catalog_applied", { phase, artifactDigest: r.artifactDigest });
|
|
@@ -98,8 +56,6 @@ export async function applyCatalogToSource(source, next, prev, log, phase) {
|
|
|
98
56
|
return false;
|
|
99
57
|
}
|
|
100
58
|
if (prev?.catalog || source.current?.() !== undefined) {
|
|
101
|
-
// the axis was live (in-memory marker OR a persisted candidate surviving a restart whose disable was
|
|
102
|
-
// owed) and the face now has no catalog: fail-closed mirror of the cleared semantics — disable durably.
|
|
103
59
|
await source.applyDisabled(`${phase}:catalog-absent`);
|
|
104
60
|
log.info("center_prompts_catalog_disabled", { phase, note: "catalog axis withdrawn — core candidate cleared (does not revive offline)" });
|
|
105
61
|
}
|
|
@@ -110,41 +66,20 @@ export async function applyCatalogToSource(source, next, prev, log, phase) {
|
|
|
110
66
|
return false;
|
|
111
67
|
}
|
|
112
68
|
}
|
|
113
|
-
/**
|
|
114
|
-
* 选包+投影:该 scenario 的终形声明数组(`scenarioOverrides[s] ?? sections`)→ typed `stableBlocks`
|
|
115
|
-
* 钩子(声明**逐字**透传,含 contentHash——core 1.315 校验后进 manifest)。空数组在 validate 已拒
|
|
116
|
-
* (F4:空替换集非 v1 语义),所以这里恒有非空声明——恒返回 provider(center-wins 无死分支)。
|
|
117
|
-
*/
|
|
118
69
|
export function centerPromptProvider(prompts, scenarioName) {
|
|
119
70
|
const decls = scenarioDecls(prompts, scenarioName);
|
|
120
|
-
// 声明数组在候选采用时已判形+冻结(main.ts ref 整体替换,数组不原位变异)——闭包直接引用,core 侧
|
|
121
|
-
// 1.315 还有声明边界快照(getter 无法让「验过的」≠「发出的」)。
|
|
122
71
|
return { stableBlocks: () => decls };
|
|
123
72
|
}
|
|
124
|
-
/** codex R3(appendSystemPrompt 案):该 scenario 的终形 center 声明里是否有「已组装 identity」——core 的
|
|
125
|
-
* M9 迁移卫在 provider.stableBlocks 的 identity 声明上探同三锚,命中即走 pass-through 臂(其保留集无
|
|
126
|
-
* `core/role.append`,任何 append rider/outputStyle 会被静默丢)。选包与 {@link centerPromptProvider}
|
|
127
|
-
* 同式(`overrides[s] ?? sections`);锚谓词由调用方注入(task-settings `hasConstitutionAnchors` 单真源)。
|
|
128
|
-
* [1057]①f 的「server 不做语义复检」不动:这不是复检语义,是为 capabilities.appendSystemPrompt 的诚实面
|
|
129
|
-
* 探 core 会走哪条臂。 */
|
|
130
73
|
export function centerIdentityAssembled(prompts, scenarioName, isAssembled) {
|
|
131
74
|
return scenarioDecls(prompts, scenarioName).some((d) => d.slot === "identity" && isAssembled(d.text));
|
|
132
75
|
}
|
|
133
|
-
/** 选包的**唯一**实现(两个消费面共用,免得「谁赢」这条优先序有两份副本)。
|
|
134
|
-
* #273 alias 窗:`scenarioOverrides` 的键写**旧场景名**时同样命中(`scenarioConfigKeys`,主名优先)——
|
|
135
|
-
* 运维已经写好的 per-scenario 提示词包不因改名当版静默失效。
|
|
136
|
-
* #193 P2-13 同族守卫(顺手补,收拢时发现):`Record` 的裸索引对原型链键会取到 `Object.prototype` 上的
|
|
137
|
-
* 成员,而场景名词法 `SCENARIO_NAME_RE` 恰好**允许** `constructor` 这种名字 ⇒ 旧写法会把一个函数当
|
|
138
|
-
* 声明数组返回,下游 `.some(...)` 直接 TypeError。own-property 判定后这条路不存在。 */
|
|
139
76
|
function scenarioDecls(prompts, scenarioName) {
|
|
140
77
|
const overrides = prompts.scenarioOverrides;
|
|
141
78
|
if (overrides) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return hit;
|
|
147
|
-
}
|
|
79
|
+
if (Object.hasOwn(overrides, scenarioName)) {
|
|
80
|
+
const hit = overrides[scenarioName];
|
|
81
|
+
if (hit)
|
|
82
|
+
return hit;
|
|
148
83
|
}
|
|
149
84
|
}
|
|
150
85
|
return prompts.sections;
|
|
@@ -1,45 +1,30 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { runTeamDiscussion } from "@sema-agent/core";
|
|
3
|
-
import { REVIEW_LENSES, GROUNDING, LENS_SYSTEM_TPL, DEBATE_MEMBER_TPL, DEBATE_TOPIC_TPL, ARBITER_SYSTEM, ARBITER_FALLBACK_HEADER } from "./prompts/code-review.js";
|
|
4
|
-
const LENSES = REVIEW_LENSES;
|
|
5
|
-
/**
|
|
6
|
-
* Caller-tunable lens COUNT (OA request) — a structured cost/coverage dial, sibling of `@model` / `council` /
|
|
7
|
-
* `debate`. The deployment owns WHICH lenses (the `LENSES` order = the priority: security/correctness first =
|
|
8
|
-
* the bug-finders); the caller only picks HOW MANY. Clamp to [1, LENSES.length]; absent / non-numeric = ALL
|
|
9
|
-
* (the current default → zero regression). A named subset is deliberately NOT supported (it would force a
|
|
10
|
-
* published, maintained lens vocabulary contract; the count is the verifiable knob a "light/standard" UI needs).
|
|
11
|
-
*/
|
|
3
|
+
import { REVIEW_LENSES, GROUNDING, LENS_SYSTEM_TPL, DEBATE_MEMBER_TPL, DEBATE_TOPIC_TPL, ARBITER_SYSTEM, ARBITER_FALLBACK_HEADER } from "./prompts/code-review.js";
|
|
4
|
+
const LENSES = REVIEW_LENSES;
|
|
12
5
|
export function pickLenses(count) {
|
|
13
6
|
if (count == null || !Number.isFinite(count))
|
|
14
7
|
return LENSES;
|
|
15
8
|
const n = Math.min(LENSES.length, Math.max(1, Math.floor(count)));
|
|
16
9
|
return LENSES.slice(0, n);
|
|
17
10
|
}
|
|
18
|
-
/** Caller-settable debate rounds: a FINITE integer clamped to [1,3]; non-number / NaN / ±Infinity = undefined
|
|
19
|
-
* (→ the council's default of 1). Mirrors `pickLenses`'s `Number.isFinite` guard — the previous inline clamp let
|
|
20
|
-
* `NaN` through (`typeof NaN === "number"`, `Math.min(3, NaN) === NaN`), corrupting the cost metric (council). */
|
|
21
11
|
export function clampRounds(rounds) {
|
|
22
12
|
if (typeof rounds !== "number" || !Number.isFinite(rounds))
|
|
23
13
|
return undefined;
|
|
24
14
|
return Math.min(3, Math.max(1, Math.floor(rounds)));
|
|
25
15
|
}
|
|
26
|
-
// Guardrail COPY (GROUNDING/templates/arbiter) lives in prompts/code-review.ts — this file keeps
|
|
27
|
-
// only the fill logic. `fillPrompt` is a plain `{key}` substitution (no escaping: values are our own lens
|
|
28
|
-
// names/briefs and the objective/findings the model already sees verbatim elsewhere).
|
|
29
16
|
function fillPrompt(tpl, vars) {
|
|
30
17
|
return tpl.replace(/\{(\w+)\}/g, (m, k) => (k in vars ? vars[k] : m));
|
|
31
18
|
}
|
|
32
19
|
function lensSystem(lens) {
|
|
33
20
|
return fillPrompt(LENS_SYSTEM_TPL, { name: lens.name, brief: lens.brief, grounding: GROUNDING });
|
|
34
21
|
}
|
|
35
|
-
// L2 — peer debate persona (guardrails 5,6): cross-examine, adjust confidence, verify disputes with tools.
|
|
36
22
|
function debateMemberSystem(lens) {
|
|
37
23
|
return fillPrompt(DEBATE_MEMBER_TPL, { name: lens.name, brief: lens.brief });
|
|
38
24
|
}
|
|
39
25
|
function debateTopic(objective, findings) {
|
|
40
26
|
return fillPrompt(DEBATE_TOPIC_TPL, { objective, grounding: GROUNDING, findings });
|
|
41
27
|
}
|
|
42
|
-
/** Build the `run_council` tool. The lead calls it once; it returns the final arbitrated review. */
|
|
43
28
|
export function createCouncilTool(subRunner, repoTools, objective, opts = {}) {
|
|
44
29
|
return {
|
|
45
30
|
name: "run_council",
|
|
@@ -48,23 +33,17 @@ export function createCouncilTool(subRunner, repoTools, objective, opts = {}) {
|
|
|
48
33
|
effect: "read",
|
|
49
34
|
parameters: Type.Object({}),
|
|
50
35
|
execute: async (_args, ctx) => {
|
|
51
|
-
// Caller-chosen lens subset (OA cost/coverage dial); default = all lenses.
|
|
52
36
|
const active = pickLenses(opts.lensCount);
|
|
53
|
-
|
|
54
|
-
// parent is cancelled, instead of each burning to its own timeoutSec (design/16 feature request).
|
|
55
|
-
const lenses = await runLensReviews(subRunner, repoTools, objective, ctx.signal, active); // L1
|
|
37
|
+
const lenses = await runLensReviews(subRunner, repoTools, objective, ctx.signal, active);
|
|
56
38
|
const findings = lenses.map((l) => `### ${l.lens} reviewer\n${l.text}`).join("\n\n");
|
|
57
|
-
const converge = await runConvergence(subRunner, repoTools, objective, findings, opts, ctx.signal, active);
|
|
58
|
-
// Cost is otherwise invisible — the sub-tasks run on a separate runner, so the parent run's
|
|
59
|
-
// stats only count the lead. Surface the real (~Nx) cost three ways:
|
|
39
|
+
const converge = await runConvergence(subRunner, repoTools, objective, findings, opts, ctx.signal, active);
|
|
60
40
|
const totalTokens = lenses.reduce((s, l) => s + l.tokens, 0) + converge.tokens;
|
|
61
41
|
const totalTurns = lenses.reduce((s, l) => s + l.turns, 0) + converge.turns;
|
|
62
42
|
const tasks = active.length + (opts.debate ? active.length * (opts.rounds ?? 1) + 1 : 1);
|
|
63
|
-
// ① into the PARENT run's TaskResult.stats.nested (core 1.11 reportUsage):
|
|
64
43
|
ctx.reportUsage?.({ tokens: totalTokens, turns: totalTurns, tasks });
|
|
65
44
|
const mode = opts.debate ? "L1+L2+L3" : "L1+L3";
|
|
66
45
|
opts.metrics?.inc("council_runs_total", { mode });
|
|
67
|
-
opts.metrics?.inc("task_tokens_total", {}, totalTokens);
|
|
46
|
+
opts.metrics?.inc("task_tokens_total", {}, totalTokens);
|
|
68
47
|
opts.metrics?.observe("council_tokens", totalTokens);
|
|
69
48
|
opts.logger?.info("council_done", { mode, lenses: lenses.length, totalTokens, totalTurns });
|
|
70
49
|
return {
|
|
@@ -74,15 +53,10 @@ export function createCouncilTool(subRunner, repoTools, objective, opts = {}) {
|
|
|
74
53
|
},
|
|
75
54
|
};
|
|
76
55
|
}
|
|
77
|
-
/** L1 — one isolated, repo-tooled subagent per lens, run in parallel. A single lens that throws
|
|
78
|
-
* (gateway 5xx / timeout) must NOT collapse the whole council, so failures degrade to a noted
|
|
79
|
-
* empty lens and arbitration proceeds on the survivors. */
|
|
80
56
|
async function runLensReviews(subRunner, repoTools, objective, signal, lenses) {
|
|
81
57
|
const settled = await Promise.allSettled(lenses.map(async (lens) => {
|
|
82
58
|
const r = await subRunner.runTask({
|
|
83
59
|
objective: `${objective}\n\nReview ONLY through the ${lens.name} lens.`,
|
|
84
|
-
// Cost tiering (1.24): lenses run on the `subagent` role — cheap when MODEL_CHEAP_ID is set,
|
|
85
|
-
// else the main model. Scanning for leads doesn't need the strong model; the arbiter does.
|
|
86
60
|
modelRole: "subagent",
|
|
87
61
|
tools: repoTools,
|
|
88
62
|
systemPrompt: lensSystem(lens),
|
|
@@ -101,7 +75,6 @@ async function runLensReviews(subRunner, repoTools, objective, signal, lenses) {
|
|
|
101
75
|
turns: 0,
|
|
102
76
|
});
|
|
103
77
|
}
|
|
104
|
-
/** L2 (peer debate, tool-grounded) + L3 synthesis, or — when `debate` is off — L3 arbiter alone. */
|
|
105
78
|
async function runConvergence(subRunner, repoTools, objective, findings, opts, signal, lenses) {
|
|
106
79
|
if (opts.debate) {
|
|
107
80
|
const team = await (opts.teamFn ?? runTeamDiscussion)({
|
|
@@ -110,14 +83,12 @@ async function runConvergence(subRunner, repoTools, objective, findings, opts, s
|
|
|
110
83
|
members: lenses.map((l) => ({ role: l.name, systemPrompt: debateMemberSystem(l) })),
|
|
111
84
|
topic: debateTopic(objective, findings),
|
|
112
85
|
rounds: opts.rounds ?? 1,
|
|
113
|
-
tools: repoTools,
|
|
86
|
+
tools: repoTools,
|
|
114
87
|
maxTranscriptTokens: 8000,
|
|
115
88
|
synthesizer: { role: "arbiter", systemPrompt: ARBITER_SYSTEM },
|
|
116
89
|
limits: { maxWalltimeMs: 400_000 },
|
|
117
|
-
signal,
|
|
90
|
+
signal,
|
|
118
91
|
});
|
|
119
|
-
// 1.32: synthesizer 两次都失败时 `conclusion` 是 `[unavailable…]` 垃圾串,与真结论无法区分。别当结论
|
|
120
|
-
// 返回——退回未经仲裁的各 lens 原始发现(findings 在手),用户至少看到真实发现,而不是把垃圾当评审。
|
|
121
92
|
if (!team.conclusionValid) {
|
|
122
93
|
opts.logger?.warn("council_arbiter_failed", { failures: team.failures });
|
|
123
94
|
return {
|
|
@@ -128,18 +99,14 @@ async function runConvergence(subRunner, repoTools, objective, findings, opts, s
|
|
|
128
99
|
}
|
|
129
100
|
return { review: team.conclusion, tokens: team.stats.tokens, turns: team.stats.turns };
|
|
130
101
|
}
|
|
131
|
-
// L3 only — a single neutral arbiter (ground / dedup / bucket / rank). No new findings.
|
|
132
102
|
const arb = await subRunner.runTask({
|
|
133
103
|
objective: `Arbitrate these specialist findings into ONE final review:\n\n${findings}`,
|
|
134
|
-
// The arbiter grounds/dedups/ranks — keep it on the strong `synthesize` role (= main model).
|
|
135
104
|
modelRole: "synthesize",
|
|
136
105
|
systemPrompt: ARBITER_SYSTEM,
|
|
137
106
|
limits: { maxWalltimeMs: 240_000 },
|
|
138
107
|
enableBlockedReport: false,
|
|
139
108
|
signal,
|
|
140
109
|
});
|
|
141
|
-
// Mirror the debate path's fallback: an empty/failed arbiter result must not surface as an empty review —
|
|
142
|
-
// hand back the raw lens findings so the caller still sees real findings, not nothing.
|
|
143
110
|
const review = arb.result?.trim() || `${ARBITER_FALLBACK_HEADER}${findings}`;
|
|
144
111
|
return { review, tokens: arb.stats.tokens, turns: arb.stats.turns };
|
|
145
112
|
}
|
|
@@ -1,34 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* collab → named-workflow projection — 翻译层**切片 1.5**(design/140 统一解:
|
|
3
|
-
* 「模式=内置命名 workflow profile,一期零新引擎机制」;core 1.263.0 三件落地后的靶点切换)。
|
|
4
|
-
*
|
|
5
|
-
* 切片① 的 runTeamDiscussion 投影(collab-project.ts)已随本切片**整体替换**(同款纪律:别留双路径
|
|
6
|
-
* 降级)。新形态:每个可投影的 CollabTemplate 翻译成一条**命名 workflow 注册条目**——
|
|
7
|
-
*
|
|
8
|
-
* `Workflow({name: <collab id>})` ⇒ 执行体 = core 内置 `TEAM_DISCUSSION_SCRIPT`(pure script content,
|
|
9
|
-
* 零新机制)+ `defaultArgs` = 本模板的 slots/rounds/finalizer 翻译(args 合并链第二级:调用时 args >
|
|
10
|
-
* 本注册 defaults > 脚本内置兜底,core `mergeWorkflowArgs` 在 tool-resolve 时点快照)。center「只配模式
|
|
11
|
-
* 各 slot 的模型」的拍板意图恰好=defaultArgs 这一级;调用者仍可用 args.topic/members 覆盖。
|
|
12
|
-
*
|
|
13
|
-
* 可投影子集(团队讨论 profile 能忠实执行的语义;其余整条跳过+结构化上报,绝不静默降级):
|
|
14
|
-
* topology ∈ {ring, pair}(round-based 顺序发言=脚本真实形态;star/layered 等 core 后续 profile)∧
|
|
15
|
-
* finalizer.type = "summarize"(→脚本 finalizer;judge/vote/fuse/verify 裁决族=后续 profile)∧
|
|
16
|
-
* sharedContext = {transcript, session} ∧ 全 slot 无 tools(工具绑定=执行面后续)。
|
|
17
|
-
*
|
|
18
|
-
* 语义注记(投影成功但记录):脚本对 members cap 6 / rounds cap 5(确定性截断)——超界模板照投+note;
|
|
19
|
-
* CollabTemplate.budget=模板级预算无 per-name workflow 通道(WorkflowLimits 是部署级、per-child 强制轴
|
|
20
|
-
* 已有)→ 记 note,引擎 budget 硬顶+部署 maxTask* 闸兜底(与切片① 结论一致)。
|
|
21
|
-
*
|
|
22
|
-
* 纯函数投影 + 模块级可变注册表(registerTeams 同款单例姿势,applyEffective boot+refresh 热更);
|
|
23
|
-
* 消费点 = main.ts 的 composite WorkflowScriptStore(resolveName 先查这里——**同名 SHADOW core 内置**,
|
|
24
|
-
* design/140 §6 1c 契约)。
|
|
25
|
-
*/
|
|
26
1
|
import { TEAM_DISCUSSION_SCRIPT } from "@sema-agent/core";
|
|
27
2
|
export function projectCollabToWorkflows(templates) {
|
|
28
3
|
const out = { workflows: {}, skipped: [], notes: [] };
|
|
29
4
|
for (const t of templates ?? []) {
|
|
30
5
|
if (t.enabled === false)
|
|
31
|
-
continue;
|
|
6
|
+
continue;
|
|
32
7
|
if (t.topology !== "ring" && t.topology !== "pair") {
|
|
33
8
|
out.skipped.push({ id: t.id, reason: `topology "${t.topology}" awaits a dedicated profile (design/140 follow-on)` });
|
|
34
9
|
continue;
|
|
@@ -47,17 +22,11 @@ export function projectCollabToWorkflows(templates) {
|
|
|
47
22
|
out.skipped.push({ id: t.id, reason: "slot tools binding awaits the execution slice" });
|
|
48
23
|
continue;
|
|
49
24
|
}
|
|
50
|
-
// finalizer.slot → 脚本 finalizer(该席位退出讨论席)。slot **未配** ⇒ 脚本内置综合官兜底(合法形态);
|
|
51
|
-
// slot 配了但**悬空**(指向不存在的席位——拼错/编辑漂移)⇒ 整条跳过(静默回退默认综合官
|
|
52
|
-
// = 模板意图被悄悄改写,违「绝不静默降级」纪律;center zod 不做跨字段存在性校验,这里是唯一防线)。
|
|
53
25
|
const finSlot = t.finalizer.slot !== undefined ? t.slots.find((s) => s.id === t.finalizer.slot) : undefined;
|
|
54
26
|
if (t.finalizer.slot !== undefined && finSlot === undefined) {
|
|
55
27
|
out.skipped.push({ id: t.id, reason: `finalizer.slot "${t.finalizer.slot}" does not match any slot id (dangling reference)` });
|
|
56
28
|
continue;
|
|
57
29
|
}
|
|
58
|
-
// 对抗评审 2026-07-11(MED):finalizer slot 合法可为 cardinality-N 多成员(registry-core 只约束
|
|
59
|
-
// cardinality=1 ≤1 人),但 team-discussion 的 finalizer 是单席——members[1..] 无席可坐。不静默丢人:
|
|
60
|
-
// 首成员任综合官,其余 note 上报(与 cap 截断同款有损注记纪律)。
|
|
61
30
|
if ((finSlot?.members?.length ?? 0) > 1) {
|
|
62
31
|
out.notes.push({ id: t.id, note: `finalizer slot "${finSlot.id}" carries ${finSlot.members.length} members — only the first seats as the synthesizer (single-seat finalizer profile)` });
|
|
63
32
|
}
|
|
@@ -66,10 +35,6 @@ export function projectCollabToWorkflows(templates) {
|
|
|
66
35
|
const finalizer = finPrompt !== undefined || finModel !== undefined
|
|
67
36
|
? { ...(finPrompt !== undefined ? { prompt: finPrompt } : {}), ...(finModel !== undefined ? { model: finModel } : {}) }
|
|
68
37
|
: undefined;
|
|
69
|
-
// 讨论席展开(cardinality "N" 逐成员出席,role 序号唯一;member 镜头 > slot 镜头;T1 modelRef 缺省=
|
|
70
|
-
// 不设 model ⇒ 脚本/引擎跟随调用者当前模型,零特判)。members 为空的席位=slot 镜头即人设,一人出席。
|
|
71
|
-
// cardinality 声明与 members 实况分叉(=1 却配了多成员)不静默 flatten——全员照展开
|
|
72
|
-
// (丢成员=更糟的静默降级)但 note 上报,center 编辑面可据此标注修正。
|
|
73
38
|
const members = [];
|
|
74
39
|
for (const s of t.slots) {
|
|
75
40
|
if (s === finSlot)
|
|
@@ -94,8 +59,6 @@ export function projectCollabToWorkflows(templates) {
|
|
|
94
59
|
defaultArgs: { members, rounds: t.rounds.max, ...(finalizer ? { finalizer } : {}) },
|
|
95
60
|
listing: {
|
|
96
61
|
name: t.id,
|
|
97
|
-
// description=center 起的显示名+描述(工具卡人话);whenToUse 留给 center 未来字段——缺席时
|
|
98
|
-
// 工具卡回落 description(core workflowWhenToUseText 链)。
|
|
99
62
|
description: [t.name, t.description].filter(Boolean).join(" — ") || t.id,
|
|
100
63
|
},
|
|
101
64
|
};
|
|
@@ -112,21 +75,15 @@ export function projectCollabToWorkflows(templates) {
|
|
|
112
75
|
}
|
|
113
76
|
return out;
|
|
114
77
|
}
|
|
115
|
-
// ── 模块级注册表(registerTeams 同款可变单例;applyEffective boot+refresh 热更,非粘:整表替换)────────
|
|
116
78
|
let REGISTRY = {};
|
|
117
79
|
export function registerCollabWorkflows(workflows) {
|
|
118
80
|
REGISTRY = { ...workflows };
|
|
119
81
|
}
|
|
120
|
-
/** composite WorkflowScriptStore 的 resolveName 前段:collab 命中 ⇒ 内置 team-discussion 脚本+本模板
|
|
121
|
-
* defaultArgs(同名 SHADOW core 内置,design/140 §6 1c)。🔴 Object.hasOwn — `name` 是模型供给的
|
|
122
|
-
* (run-workflow-tool 原样传 rawName):裸索引会让 Object.prototype 成员名("constructor"/"toString"/
|
|
123
|
-
* "__proto__"…)假命中 ⇒ 零模板注册也能烧真讨论、且同名文件 store 条目被遮蔽(对抗评审 2026-07-11 MED)。 */
|
|
124
82
|
export function resolveCollabWorkflow(name) {
|
|
125
83
|
if (!Object.hasOwn(REGISTRY, name))
|
|
126
84
|
return undefined;
|
|
127
85
|
return { script: TEAM_DISCUSSION_SCRIPT, defaultArgs: REGISTRY[name].defaultArgs };
|
|
128
86
|
}
|
|
129
|
-
/** composite store 的 list() 段(同步——workflow 工具卡只吃同步 list,core 契约注释)。 */
|
|
130
87
|
export function listCollabWorkflows() {
|
|
131
88
|
return Object.values(REGISTRY).map((e) => e.listing);
|
|
132
89
|
}
|
|
@@ -1,30 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* #196 场景 hands lane —— 「要手的场景」与「无手的场景」在装配层分家。
|
|
3
|
-
*
|
|
4
|
-
* 病根(设计小票 §1,案源 [3208]/[3209]/[3212]):core 的手带工具面是 **per-Runner 表态**
|
|
5
|
-
* (`prepare-task`:`handsEnabled = ownedEnv || deps.executionEnv`,ownedEnv 只要挂了
|
|
6
|
-
* `executionEnvFactory` 就每任务必铸)。server 此前全场景共享一只 runner + 一只 subRunner,
|
|
7
|
-
* 于是任何 REMOTE_EXEC 部署里,声明 clone-free 的 `scan`、只有 `run_council` 的评审团、
|
|
8
|
-
* 零工具人格的 team 成员,最终 roster 都被并集进全量可写手带(Bash/Edit/Write/…)。
|
|
9
|
-
*
|
|
10
|
-
* 本模块提供三件:
|
|
11
|
-
* ① {@link ScenarioHands} 判别位 + {@link pickHandsRunner} 的**穷举** switch —— 新场景不表态 = 编译红,
|
|
12
|
-
* 不是静默继承 full(词表闭集纪律)。
|
|
13
|
-
* ② {@link HANDS_EXCLUSIVE_TOOL_NAMES} + {@link handsDenyPolicy} —— 纵深:hands=none 的任务即便被误接到
|
|
14
|
-
* 有手 Runner 上,手独占名单逐一 deny。**不是**主保证(主保证是根本不挂 factory ⇒ 工具面不可见)。
|
|
15
|
-
* ③ {@link createHandsLaneRegistry} —— resolveSpec 产出 spec 与执行点选 Runner 之间的 lane 传递。
|
|
16
|
-
*/
|
|
17
1
|
import { HAND_TOOL_EFFECTS, RETIRED_TOOL_NAMES, combinePolicies, createAllowDenyPolicy } from "@sema-agent/core";
|
|
18
|
-
/**
|
|
19
|
-
* 无手孪生 Runner 的 deps 构造:把 `executionEnvFactory` **摘键**(不是置 undefined)。
|
|
20
|
-
* 摘键让「这只 Runner 没有手」在 deps 字面量上自证;置 undefined 留下一个值为 undefined 的键,
|
|
21
|
-
* 与 core 现在的 `deps.executionEnvFactory ||` 判读结果相同,但把正确性寄托在真值判断上。
|
|
22
|
-
*/
|
|
23
2
|
export function withoutExecutionEnv(deps) {
|
|
24
3
|
const { executionEnvFactory: _handsDropped, ...rest } = deps;
|
|
25
4
|
return rest;
|
|
26
5
|
}
|
|
27
|
-
/** 按场景表态取 Runner。**穷举 switch**:`ScenarioHands` 加词而此处不改 = 编译错(无 default 臂)。 */
|
|
28
6
|
export function pickHandsRunner(hands, pair) {
|
|
29
7
|
switch (hands) {
|
|
30
8
|
case "full":
|
|
@@ -33,27 +11,6 @@ export function pickHandsRunner(hands, pair) {
|
|
|
33
11
|
return pair.handsless;
|
|
34
12
|
}
|
|
35
13
|
}
|
|
36
|
-
/**
|
|
37
|
-
* core 手带 band 的工具名**全集** —— 「挂 executionEnvFactory 才出现、不挂就消失」的那一批。
|
|
38
|
-
*
|
|
39
|
-
* 两段来源,都不是拍脑袋:
|
|
40
|
-
* · `HAND_TOOL_EFFECTS`(core 导出面,`tools/fs`)—— band 的 effect 表,11 名。
|
|
41
|
-
* · 下方钉死补集 —— `createHandsToolkit` / 手带块还会铸但**不在** effect 表里的 5 名(实测差集,见
|
|
42
|
-
* test/scenario-hands-lane.test.ts 的对表格:它用真 Runner 跑「有手 roster ∖ 无手 roster」,与本常量逐名对账,
|
|
43
|
-
* core 加/改 band 成员时红,防漂移)。
|
|
44
|
-
*
|
|
45
|
-
* ⚠️ 本全集是**观测口径**(用于防漂移对账),**不是** deny 名单 —— deny 用下面的
|
|
46
|
-
* {@link HANDS_EXCLUSIVE_TOOL_NAMES},理由见那里。
|
|
47
|
-
*
|
|
48
|
-
* 🚨 [3248] P0(2026-08-09):派生时必须过滤 core 的 `RETIRED_TOOL_NAMES` —— core 5.21.0 的
|
|
49
|
-
* `HAND_TOOL_EFFECTS` 里残留已退役的 `MultiEdit`,而 core `prepare-task` 的策略名审计见退役名
|
|
50
|
-
* **无条件 throw**(`config.legacy_tool_name`);不过滤,deny 名单一进 `spec.toolPolicy`,
|
|
51
|
-
* `hands: none` 三场景(scan/code-review/team)在**所有部署**上零 turn 全灭。core 5.21.1 已删
|
|
52
|
-
* 那条死条目([3249]),这道 filter 是结构性防御:将来 core 再退役任何 band 名都不会重演
|
|
53
|
-
* (test/scenario-hands-lane.test.ts 格7/格8 双钉:真 Runner 过审计 + 零交集门)。
|
|
54
|
-
* filter 打在**整表**(effect 表 + 钉死补集)之后 —— caret floor 下装置会解析到更新的 core,
|
|
55
|
-
* 补集名哪天被退役,只滤前半就是同一次故障换个名字(codex 复审 finding,2026-08-09)。
|
|
56
|
-
*/
|
|
57
14
|
export const HANDS_BAND_TOOL_NAMES = Object.freeze([
|
|
58
15
|
...Object.keys(HAND_TOOL_EFFECTS),
|
|
59
16
|
"SendMessage",
|
|
@@ -62,37 +19,15 @@ export const HANDS_BAND_TOOL_NAMES = Object.freeze([
|
|
|
62
19
|
"EnterWorktree",
|
|
63
20
|
"ExitWorktree",
|
|
64
21
|
].filter((n) => !RETIRED_TOOL_NAMES.has(n)));
|
|
65
|
-
/**
|
|
66
|
-
* band 里**只有手才可能出现**的那批(= deny 名单)。
|
|
67
|
-
*
|
|
68
|
-
* 🔴 codex 复审(2026-08-09 finding-3,亲验 core prepare-task):band 全集里有四件是**两用**的 ——
|
|
69
|
-
* `prepare-task` 的挂载条件是 `if (backgroundTaskToolsActive || workflowToolsActive)`,而
|
|
70
|
-
* `workflowToolsActive` 只要 `spec.selfOrchestration`(caller 可设,与场景正交)+ 部署的 workflow deps
|
|
71
|
-
* 就成立,**与手无关**。拿全集去 deny,会让「hands=none 场景 + selfOrchestration:true」的请求挂上
|
|
72
|
-
* `Workflow` 却读不到它的轮询/停止/消息/转录 —— 一个半瘫的工作流面,比不给还糟。
|
|
73
|
-
* 故 deny 名单 = 全集 ∖ 两用四件。Monitor 不在两用之列(core 的挂载条件是纯
|
|
74
|
-
* `if (backgroundTaskToolsActive)`,而它 = handsIncludeShell ∧ …,无手不成立)。
|
|
75
|
-
*/
|
|
76
22
|
export const HANDS_DUAL_USE_TOOL_NAMES = Object.freeze(["TaskOutput", "TaskStop", "SendMessage", "AgentTranscript"]);
|
|
77
23
|
export const HANDS_EXCLUSIVE_TOOL_NAMES = Object.freeze(HANDS_BAND_TOOL_NAMES.filter((n) => !HANDS_DUAL_USE_TOOL_NAMES.includes(n)));
|
|
78
|
-
/** 手独占名单的 deny 策略(纵深层)。名单是常量 ⇒ 每次调用产出等价策略,构造成本可忽略。 */
|
|
79
24
|
export function handsDenyPolicy() {
|
|
80
25
|
return createAllowDenyPolicy({ deny: [...HANDS_EXCLUSIVE_TOOL_NAMES] });
|
|
81
26
|
}
|
|
82
|
-
/**
|
|
83
|
-
* 把 band deny 叠到既有基线上 —— **tighten-only**。
|
|
84
|
-
*
|
|
85
|
-
* 🪤 TRAP #1(runtime-governance.ts 头注逐字):`TaskSpec.toolPolicy` 是**覆盖**而非合并
|
|
86
|
-
* (`spec.toolPolicy ?? deps.toolPolicy`),直接赋值会静默丢掉部署的 durable 审批基线 /
|
|
87
|
-
* 单用户 auto-accept 座。走 `combinePolicies(base, deny)`(deny 胜、ask 不被 allow 冲掉),
|
|
88
|
-
* 只会加 deny,永不放松。base 缺席时单挂 deny —— 该形下 band 本就不 mount,core 的
|
|
89
|
-
* "write-capable hand tools are present but UNGATED" 信号不受影响(它以 Write 在场为条件)。
|
|
90
|
-
*/
|
|
91
27
|
export function tightenWithHandsDeny(base) {
|
|
92
28
|
const deny = handsDenyPolicy();
|
|
93
29
|
return base ? combinePolicies(base, deny) : deny;
|
|
94
30
|
}
|
|
95
|
-
/** 装配点的取用形:`full` 原样放行基线,`none` 叠 deny。**穷举 switch**,无缺省臂。 */
|
|
96
31
|
export function toolPolicyForHands(hands, base) {
|
|
97
32
|
switch (hands) {
|
|
98
33
|
case "full":
|
|
@@ -1,54 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* #217(板 [3499]②/[3521]④ 两次点名的 server 接线半场)—— 零记忆面部署形的**持久记忆披露**。
|
|
3
|
-
*
|
|
4
|
-
* 病(core [3479] 实测,#148 立案):一台没有任何持久记忆面的部署,用户说「请记住 X」,模型回一句
|
|
5
|
-
* 「已经记住了」——落盘处并不存在。用户带着「这条事实已入库」的信念离开,下一次会话才发现是空的。
|
|
6
|
-
*
|
|
7
|
-
* core 5.26.0 的分工:引擎**能自证**只读的两态(engine 侧 `writeScope:null` / runner 侧 `handsReadOnly`)
|
|
8
|
-
* 由引擎自动挂 `MEMORY_READONLY_NOTICE`;而「整台部署根本没有记忆面」这一形 core 只导出文本
|
|
9
|
-
* (`NO_PERSISTENT_MEMORY_NOTICE`)、**不注入** —— 逐字原文:「A deployment that composes its own prompt
|
|
10
|
-
* should include this block exactly when no memory face is mounted」。组装归宿主,与 `MEMORY_SAFETY`
|
|
11
|
-
* 同姿势。本模块就是那半场。
|
|
12
|
-
*
|
|
13
|
-
* ⚠️ 两条边界,越界即双重注入/假话:
|
|
14
|
-
* · **engine 在场就不是我们的座位**。哪怕 `memoryWrite:false`(writeScope null)——那恰恰是引擎自己
|
|
15
|
-
* 挂只读披露的状态,server 再叠一句口径不同的「你没有持久记忆」= 同一件事两种说法同框。
|
|
16
|
-
* · **推断到「有落盘路」就闭嘴**。判别式与 core 的 `rosterCanPersist` 同口径(已知落盘路 = 挂载且未
|
|
17
|
-
* 排除的文件写工具 / 可写 shell)。⚠️ 名单确实要读(codex 复审 [medium] 之后加的 `excludeTools` 一位:
|
|
18
|
-
* roster 把落盘路**整批**卸掉时,手带在场也等于没有写通道),但负控仍然成立:必须**全部**已知落盘路
|
|
19
|
-
* 都不在才算断链 —— `excludeTools:["Write"]` 不算(Bash/Edit 还在),请求面摘一个工具名改不动结论。
|
|
20
|
-
*/
|
|
21
1
|
import { NO_PERSISTENT_MEMORY_NOTICE } from "@sema-agent/core";
|
|
22
2
|
import { hasConstitutionAnchors } from "../task-settings.js";
|
|
23
|
-
/**
|
|
24
|
-
* 「已知落盘路」的工具名闭集 —— 与 core 的 `rosterCanPersist` 同口径:**文件写工具**(Write/Edit/
|
|
25
|
-
* NotebookEdit)或**可写 shell**(Bash)。刻意**不是** `HAND_TOOL_EFFECTS` 里 effect=write 的全集:
|
|
26
|
-
* core 逐字裁过「a generic write-effect tool does NOT count — a mail sender's side effect is not a
|
|
27
|
-
* memory store」,`TaskStop` 就是那种(有写副作用、不是落盘路)。
|
|
28
|
-
*
|
|
29
|
-
* 名字会漂,所以配一道防漂移钉(test/no-persistent-memory-notice.test.ts):每个名字必须在 core 的
|
|
30
|
-
* `HAND_TOOL_EFFECTS` 里且 effect 为 `write` —— core 改名/改档位当场红,而不是让这里静默失配成
|
|
31
|
-
* 「没有一个写工具被排除」(fail-open 方向)。
|
|
32
|
-
*/
|
|
33
3
|
export const KNOWN_PERSISTENCE_TOOL_NAMES = ["Write", "Edit", "NotebookEdit", "Bash"];
|
|
34
|
-
/** 披露段在 `prompt.assembled` 清单里的段 id(`core/` 命名空间是 core 保留的,部署段一律自家前缀)。 */
|
|
35
4
|
export const NO_PERSISTENT_MEMORY_SECTION_ID = "sema/memory.no-persistent";
|
|
36
|
-
/** 排除后还剩不剩已知落盘路。空/缺席的排除名单 ⇒ 一定还剩(最常见的路径,提前短路)。 */
|
|
37
5
|
function anyPersistenceToolSurvives(excludeTools) {
|
|
38
6
|
if (excludeTools === undefined || excludeTools.length === 0)
|
|
39
7
|
return true;
|
|
40
8
|
const excluded = new Set(excludeTools);
|
|
41
9
|
return KNOWN_PERSISTENCE_TOOL_NAMES.some((name) => !excluded.has(name));
|
|
42
10
|
}
|
|
43
|
-
/**
|
|
44
|
-
* 该不该把 `NO_PERSISTENT_MEMORY_NOTICE` 组进本次任务的 system prompt。
|
|
45
|
-
*
|
|
46
|
-
* 优先序(每一条都有独立理由,不是同一条判据的三种写法):
|
|
47
|
-
* ① engine 在场 ⇒ **否**(引擎的座位,见文件头注);
|
|
48
|
-
* ② 部署显式声明 ⇒ 声明说了算(`true` 撤回 / `false` 强制)—— operator 的部署事实压过我们的推断,
|
|
49
|
-
* 与 core 对 `memoryPersistenceCapable` 的处置同向;
|
|
50
|
-
* ③ 否则推断:有已知落盘路(手带在场且不是只读)⇒ 否;没有 ⇒ 是。
|
|
51
|
-
*/
|
|
52
11
|
export function shouldDiscloseNoPersistentMemory(facts) {
|
|
53
12
|
if (facts.memory !== undefined)
|
|
54
13
|
return false;
|
|
@@ -56,46 +15,17 @@ export function shouldDiscloseNoPersistentMemory(facts) {
|
|
|
56
15
|
return !facts.declaredCapable;
|
|
57
16
|
if (facts.hands === "none" || facts.handsReadOnly)
|
|
58
17
|
return true;
|
|
59
|
-
// remote 执行环境:手带写的是沙箱盘(每任务即焚),够不着任何 host 侧持久面 —— core 的
|
|
60
|
-
// `rosterCanPersist` 在这一形下把四只写工具**全部**不算,这里逐字同口径。
|
|
61
18
|
if (facts.remoteExecutionEnv)
|
|
62
19
|
return true;
|
|
63
|
-
// 手带在场,但 roster 可能把落盘路整批卸掉了(`excludeTools` 是真卸载)。⚠️ 负控仍成立:排掉**一个**
|
|
64
|
-
// `Write` 不算无写通道(Bash/Edit 还在)—— 必须**全部**已知落盘路都不在,才算这条链断了。
|
|
65
20
|
return !anyPersistenceToolSurvives(facts.excludeTools);
|
|
66
21
|
}
|
|
67
|
-
/** 披露段作为独立 `behavior` 声明的形。**不能**用 `identity`:那个 slot 会替换 role base。 */
|
|
68
22
|
const NOTICE_BLOCK = { id: NO_PERSISTENT_MEMORY_SECTION_ID, slot: "behavior", text: NO_PERSISTENT_MEMORY_NOTICE };
|
|
69
|
-
/**
|
|
70
|
-
* 把披露段挂进一组 typed 声明。两条腿,分界线是 core 装配器会走哪条臂:
|
|
71
|
-
* · 普通形 ⇒ 追加一条 `behavior` 声明(装配器正常 compose,段落各就各位);
|
|
72
|
-
* · 声明里有**已组装 identity**(三锚齐全)⇒ 装配器走 pass-through 臂:`roleBase = 该 identity 的文本`,
|
|
73
|
-
* 其余声明**一条不挂**(core 只发一条「N 条声明未挂载」的告警)。此时追加 behavior 段等于什么都没做 ——
|
|
74
|
-
* 披露判为真、模型侧一个字都收不到,正是 #148 要消灭的那种沉默。所以这一形改成把披露段接在**该 identity
|
|
75
|
-
* 文本之后**(pass-through 臂原样把它当 `core/role.base` 发出去),文字真的进 prompt。
|
|
76
|
-
* ⚠️ `contentHash` 一并摘掉:文本被追加过就不再是 center 那份发布物的摘要,留着 = 一条对不上的对账锚
|
|
77
|
-
* (core 会为不匹配的摘要再发一条告警)。原文一个字节不改,只在后面接。
|
|
78
|
-
*/
|
|
79
23
|
function mountNotice(decls) {
|
|
80
24
|
const assembledIdentity = decls.find((d) => d.slot === "identity" && hasConstitutionAnchors(d.text));
|
|
81
25
|
if (!assembledIdentity)
|
|
82
26
|
return [...decls, NOTICE_BLOCK];
|
|
83
27
|
return decls.map((d) => (d === assembledIdentity ? { id: d.id, slot: d.slot, text: `${d.text}\n\n${NO_PERSISTENT_MEMORY_NOTICE}` } : d));
|
|
84
28
|
}
|
|
85
|
-
/**
|
|
86
|
-
* 把披露段组进一个 prompt provider,**按 provider 自己的钩子形分腿**(换形会改段身份与 append 座位):
|
|
87
|
-
* · typed(`stableBlocks`)⇒ {@link mountNotice}(普通形追加 behavior 声明;已组装 identity 形接在其文本后)。
|
|
88
|
-
* · string(`stableSystem`)⇒ 接在 role 层文本之后(落进 `core/role.base` 段)。
|
|
89
|
-
* · 两个钩子都没有(= core 会用 `defaultPromptProvider`)⇒ **只发一条 typed 声明**,role 层留给 core 自己铸。
|
|
90
|
-
*
|
|
91
|
-
* ⚠️ 最后一腿为什么不是「自铸 role 层」(2026-08-12 复扫 medium,已实测):自铸形
|
|
92
|
-
* `stableSystem: (ctx) => ${ctx.userSystemPrompt ?? DEFAULT_SYSTEM_PROMPT}\n\n${段落}` 把**调用方的**
|
|
93
|
-
* systemPrompt 逐字变成了 provider 的输出。调用方传一份已组装 prompt(集成方/center 的常见形)时,装配器的
|
|
94
|
-
* 迁移卫就在 provider 输出上探到三锚 ⇒ pass-through 臂 ⇒ 保留集无 `core/role.append` ⇒ 已被 append 门放行的
|
|
95
|
-
* `appendSystemPrompt`/`settings.outputStyle` 静默蒸发(门在包装**之前**按未包装的 provider 判,两边分家)。
|
|
96
|
-
* 走 typed 声明腿就没有这条耦合:role 层仍由 core 按 `userSystemPrompt ?? DEFAULT_SYSTEM_PROMPT` 自己铸,
|
|
97
|
-
* 我方只贡献一条 behavior 段,`providerDropsAppend` 的判决包装前后逐格相同。
|
|
98
|
-
*/
|
|
99
29
|
export function withNoPersistentMemoryNotice(provider) {
|
|
100
30
|
if (provider?.stableBlocks) {
|
|
101
31
|
const blocks = provider.stableBlocks.bind(provider);
|
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build a scenario's prompt provider from just its ROLE base, on core 1.243's 提示词主权 contract:
|
|
3
|
-
* `stableSystem` returns ONLY the role layer (base + the task's own systemPrompt) and **core appends
|
|
4
|
-
* the constitution structurally** — harness/safety blocks (Truth/CYBER_RISK/URL_SAFETY), mode blocks,
|
|
5
|
-
* AND the memory safety/hygiene guidance (`constitutionBlocks`), plus the volatile `<user_memory>`
|
|
6
|
-
* tail LAST (design/12 prefix-cache discipline; guarded in CI by `assertPromptCacheFriendly`).
|
|
7
|
-
*
|
|
8
|
-
* History: the pre-1.243 seam made this helper's whole-prompt replacement silently DROP
|
|
9
|
-
* core's constitution — oa/code-review/team ran with zero safety blocks. Same batch also moved
|
|
10
|
-
* MEMORY_SAFETY/MEMORY_HYGIENE into the constitution layer, so the hand-composition this helper used
|
|
11
|
-
* to do (core 1.62, design/41) would now DOUBLE-inject them — both removed; core owns the discipline
|
|
12
|
-
* (consolidation mutual-exclusion included). This stays a thin role-layer join so scenarios don't
|
|
13
|
-
* re-implement the same two-line body five times.
|
|
14
|
-
*/
|
|
15
1
|
export function stablePrompt(base) {
|
|
16
2
|
return {
|
|
17
3
|
stableSystem: ({ userSystemPrompt }) => [base, userSystemPrompt].filter(Boolean).join("\n\n"),
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Code-review council copy (bundle-data layer). Pure data — placeholders are `{name}`-style,
|
|
3
|
-
* filled by the consumer (code-review-council.ts fillPrompt). Guardrail rationale lives with the
|
|
4
|
-
* consumer's comments; this file is ONLY the words.
|
|
5
|
-
*/
|
|
6
|
-
/** The deployment-owned lens roster. Order = priority (security/correctness first = the bug-finders);
|
|
7
|
-
* the caller dials COUNT only (pickLenses), never a named subset. */
|
|
8
1
|
export const REVIEW_LENSES = [
|
|
9
2
|
{ name: "security", brief: "authz/ownership checks, input validation, injection (SQL/command/path), secrets, unsafe deserialization, SSRF, trust boundaries" },
|
|
10
3
|
{ name: "correctness", brief: "edge cases, off-by-one, race conditions, resource leaks, missing/incorrect error paths, unhandled rejections" },
|
|
@@ -13,8 +6,6 @@ export const REVIEW_LENSES = [
|
|
|
13
6
|
{ name: "tests", brief: "are the risky paths covered? do tests assert behavior (not implementation)? missing edge-case tests" },
|
|
14
7
|
{ name: "readability", brief: "naming, dead code, duplication, misleading comments, structure — these are [DESIGN], never [BUG]" },
|
|
15
8
|
];
|
|
16
|
-
/** Guardrails 2-5: evidence grounding (a CONFIDENCE signal, not a delete), requirement anchoring,
|
|
17
|
-
* bucketing, severity×confidence. */
|
|
18
9
|
export const GROUNDING = [
|
|
19
10
|
"RULES:",
|
|
20
11
|
"1. EVIDENCE drives CONFIDENCE (it does NOT delete a finding): cite an exact `path:line` and, whenever you can, **paste the verbatim code snippet** you are flagging. A finding WITH a pasted snippet may carry full confidence/severity; a finding with only a line reference is still allowed but MUST be tagged `[unverified: line-ref only]` and capped at minor severity / low confidence (never a blocker).",
|
|
@@ -22,21 +13,17 @@ export const GROUNDING = [
|
|
|
22
13
|
"3. BUCKET: label each finding [BUG] (provably wrong against the code), [DESIGN] (subjective preference), or [QUESTION]. A design preference is NEVER a [BUG].",
|
|
23
14
|
"4. RATE each: severity (blocker/major/minor) AND confidence (high/med/low).",
|
|
24
15
|
].join("\n");
|
|
25
|
-
/** L1 lens reviewer system prompt. Placeholders: {name} {brief} {grounding}. */
|
|
26
16
|
export const LENS_SYSTEM_TPL = "You are a {name} code reviewer. Stay strictly in your lane: {brief}.\n" +
|
|
27
17
|
"Read only the files you need — repo_tree to map, then repo_read_file (just-in-time).\n\n{grounding}\n\n" +
|
|
28
18
|
'List findings in your lens only. If you find nothing solid, say "no findings".';
|
|
29
|
-
/** L2 peer-debate persona (guardrails 5,6). Placeholders: {name} {brief}. */
|
|
30
19
|
export const DEBATE_MEMBER_TPL = "You are the {name} reviewer on a review panel ({brief}). Cross-examine the findings in " +
|
|
31
20
|
"the shared transcript: CORROBORATE or REBUT others' claims in your area (raising/lowering their " +
|
|
32
21
|
"confidence), and DEFEND or WITHDRAW your own if rebutted.\n" +
|
|
33
22
|
"You MAY call repo_read_file to VERIFY ONE specific DISPUTED finding (quote the exact path:line) — do " +
|
|
34
23
|
"NOT re-review the whole repo. A finding with no path:line + code quote is invalid. Be concise.";
|
|
35
|
-
/** L2 debate topic body. Placeholders: {objective} {grounding} {findings}. */
|
|
36
24
|
export const DEBATE_TOPIC_TPL = "Cross-examine these specialist code-review findings for: {objective}\n\n{grounding}\n" +
|
|
37
25
|
"5. CONFIDENCE: peer corroboration raises it; an unrebutted rebuttal lowers it; drop findings that " +
|
|
38
26
|
"collapse under scrutiny.\n\nFindings to debate:\n\n{findings}";
|
|
39
|
-
/** Guardrails 4,7: arbitration is not summary — no new findings, ground/dedup/bucket/rank only. */
|
|
40
27
|
export const ARBITER_SYSTEM = "You are the NEUTRAL ARBITER of a code-review council. You are given findings from independent " +
|
|
41
28
|
"specialist reviewers. You do NOT add new findings and do NOT re-review. Your only job:\n" +
|
|
42
29
|
"- TIER by grounding, do NOT silently drop real findings: a finding that PASTES the code keeps its " +
|
|
@@ -48,6 +35,5 @@ export const ARBITER_SYSTEM = "You are the NEUTRAL ARBITER of a code-review coun
|
|
|
48
35
|
"Output the final review: a 2-3 line summary, then findings grouped by bucket then severity, each as " +
|
|
49
36
|
"`path:line` — the problem — a concrete fix. Never invent files or symbols. If a whole lens reported " +
|
|
50
37
|
"nothing groundable, say so rather than inventing.";
|
|
51
|
-
/** No-arbiter fallback header ({findings} appended by the consumer). */
|
|
52
38
|
export const ARBITER_FALLBACK_HEADER = "[council 仲裁无输出——以下是未经仲裁的各 lens 原始发现]\n\n";
|
|
53
39
|
//# sourceMappingURL=code-review.js.map
|