@sema-agent/core 5.20.0 → 5.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/agents/agent-definition.d.ts +7 -0
- package/dist/agents/agent-transcript-tool.d.ts +30 -0
- package/dist/agents/builtin-agents.d.ts +60 -0
- package/dist/agents/cascade.d.ts +107 -0
- package/dist/agents/cumulative-stats.d.ts +56 -0
- package/dist/agents/observer.d.ts +162 -0
- package/dist/agents/peer-admission.d.ts +95 -0
- package/dist/agents/repair-loop.d.ts +226 -0
- package/dist/agents/retain-ledger.d.ts +141 -0
- package/dist/agents/roster-store.d.ts +105 -0
- package/dist/agents/send-message-tool.d.ts +92 -0
- package/dist/agents/session-util.d.ts +5 -0
- package/dist/agents/subagent-steps.d.ts +66 -0
- package/dist/agents/subagent.d.ts +600 -0
- package/dist/agents/suspend-guard.d.ts +29 -0
- package/dist/agents/teacher.d.ts +75 -0
- package/dist/agents/team.d.ts +120 -1
- package/dist/agents/tool-filter.d.ts +34 -0
- package/dist/agents/verify.d.ts +198 -0
- package/dist/bench/metrics.d.ts +455 -0
- package/dist/brain/anthropic.d.ts +30 -0
- package/dist/brain/circuit-breaker.d.ts +33 -0
- package/dist/brain/context-overflow.d.ts +60 -3
- package/dist/brain/degrading.d.ts +67 -0
- package/dist/brain/errors.d.ts +42 -0
- package/dist/brain/failover.d.ts +15 -0
- package/dist/brain/media-degrade.d.ts +39 -0
- package/dist/brain/model-presets.d.ts +31 -0
- package/dist/brain/open-responses.d.ts +19 -0
- package/dist/brain/openai.d.ts +46 -0
- package/dist/brain/reasoning.d.ts +106 -1
- package/dist/brain/repetition.d.ts +83 -0
- package/dist/brain/request-params.d.ts +56 -0
- package/dist/brain/retry.d.ts +46 -0
- package/dist/brain/routing.d.ts +12 -0
- package/dist/brain/status-sink.d.ts +30 -1
- package/dist/brain/stream-engine.d.ts +147 -0
- package/dist/brain/stream-shared.d.ts +34 -0
- package/dist/brain/terminal-cause.d.ts +31 -0
- package/dist/brain/timeout.d.ts +107 -0
- package/dist/brain/tool-call-id.d.ts +20 -0
- package/dist/brain/tool-call-repair.d.ts +13 -0
- package/dist/config/catalog.d.ts +47 -0
- package/dist/config/defaults.d.ts +33 -0
- package/dist/core/a2a-task-state.d.ts +53 -0
- package/dist/core/a2a.d.ts +51 -0
- package/dist/core/arg-summary.d.ts +62 -0
- package/dist/core/ask-question.d.ts +272 -2
- package/dist/core/auto-compaction.d.ts +467 -0
- package/dist/core/auto-compaction.js +20 -6
- package/dist/core/auto-mode-prompt-assets.d.ts +8 -0
- package/dist/core/auto-mode-prompt.d.ts +27 -0
- package/dist/core/auto-mode.d.ts +54 -3
- package/dist/core/auto-promote.d.ts +100 -0
- package/dist/core/background-agent-store.d.ts +292 -0
- package/dist/core/background-shell.d.ts +110 -0
- package/dist/core/cache-break-detector.d.ts +34 -0
- package/dist/core/canonical-json.d.ts +57 -0
- package/dist/core/checkpoint-store.d.ts +1574 -16
- package/dist/core/compliance.d.ts +30 -0
- package/dist/core/consolidate-scope.d.ts +75 -0
- package/dist/core/context-edit.d.ts +99 -0
- package/dist/core/context-guard.d.ts +46 -0
- package/dist/core/exec-gate.d.ts +44 -0
- package/dist/core/exec-output-tail.d.ts +61 -0
- package/dist/core/file-snapshot-store.d.ts +104 -0
- package/dist/core/fs-write-gate-policy.d.ts +36 -0
- package/dist/core/git-worktree-env.d.ts +31 -0
- package/dist/core/governance-codes.d.ts +19 -0
- package/dist/core/hooks.d.ts +608 -1
- package/dist/core/human-input-projection.d.ts +37 -0
- package/dist/core/human-input-projection.js +13 -0
- package/dist/core/image-downsample.d.ts +74 -0
- package/dist/core/locked-config.d.ts +37 -0
- package/dist/core/lsp-diagnostics.d.ts +77 -0
- package/dist/core/lsp-protocol.d.ts +29 -0
- package/dist/core/lsp-session.d.ts +60 -1
- package/dist/core/lsp.d.ts +150 -1
- package/dist/core/mailbox-store.d.ts +57 -0
- package/dist/core/mcp.d.ts +381 -0
- package/dist/core/media-byte-cap.d.ts +21 -0
- package/dist/core/memory-admission.d.ts +71 -0
- package/dist/core/memory-engine/content-origin.d.ts +64 -0
- package/dist/core/memory-engine/data-plane.d.ts +43 -0
- package/dist/core/memory-engine/dual-root.d.ts +24 -0
- package/dist/core/memory-engine/engine.d.ts +230 -0
- package/dist/core/memory-engine/engine.js +103 -35
- package/dist/core/memory-engine/file-backend.d.ts +155 -0
- package/dist/core/memory-engine/frontmatter.d.ts +16 -0
- package/dist/core/memory-engine/layout.d.ts +217 -0
- package/dist/core/memory-engine/memory-backend-contract.d.ts +12 -0
- package/dist/core/memory-engine/migrate.d.ts +9 -0
- package/dist/core/memory-engine/scan.d.ts +12 -0
- package/dist/core/memory-engine/scope-contract.d.ts +61 -1
- package/dist/core/memory-engine/sync-client.d.ts +87 -0
- package/dist/core/memory-engine/sync.d.ts +60 -0
- package/dist/core/memory-engine/tools.d.ts +41 -0
- package/dist/core/memory-engine/types.d.ts +188 -0
- package/dist/core/memory-recall.d.ts +141 -0
- package/dist/core/memory-vector.d.ts +20 -0
- package/dist/core/memory.d.ts +458 -0
- package/dist/core/message-utils.d.ts +6 -0
- package/dist/core/oracle-isolation.d.ts +69 -0
- package/dist/core/permission-rule-consent.d.ts +138 -0
- package/dist/core/permission-rule-model.d.ts +122 -0
- package/dist/core/permission-rule-store.d.ts +119 -3
- package/dist/core/permission-rules.d.ts +87 -1
- package/dist/core/present-plan-tool.d.ts +20 -0
- package/dist/core/pricing.d.ts +26 -0
- package/dist/core/property-harness.d.ts +86 -0
- package/dist/core/protocol-naming.d.ts +38 -0
- package/dist/core/protocol-table.d.ts +61 -0
- package/dist/core/push-queue.d.ts +1 -0
- package/dist/core/remote-env.d.ts +383 -1
- package/dist/core/retention-policy.d.ts +33 -0
- package/dist/core/retention.d.ts +51 -0
- package/dist/core/roles.d.ts +59 -0
- package/dist/core/runner/active-skill-scope.d.ts +34 -0
- package/dist/core/runner/assemble-result.d.ts +134 -0
- package/dist/core/runner/compaction-call-options.d.ts +97 -1
- package/dist/core/runner/grounding-signal.d.ts +10 -0
- package/dist/core/runner/image.d.ts +17 -0
- package/dist/core/runner/image.js +29 -15
- package/dist/core/runner/memory-consolidation.d.ts +60 -0
- package/dist/core/runner/prepare-memory.d.ts +59 -0
- package/dist/core/runner/prepare-task.d.ts +1011 -2
- package/dist/core/runner/prepare-task.js +12 -11
- package/dist/core/runner/prompt-suggestions.d.ts +7 -0
- package/dist/core/runner/runtask.d.ts +304 -3
- package/dist/core/runner/session-file-state-replay.d.ts +49 -0
- package/dist/core/runner/session-rule-policy.d.ts +58 -0
- package/dist/core/runner/strict-output-schema.d.ts +18 -3
- package/dist/core/runner/synthetic-tools.d.ts +113 -0
- package/dist/core/runner/teardown-bounded.d.ts +34 -0
- package/dist/core/runner/tool-disclosure.d.ts +227 -0
- package/dist/core/runner/tool-output-projection.d.ts +6 -0
- package/dist/core/runner/turn-attachments.d.ts +634 -0
- package/dist/core/runner/usage-accounting.d.ts +32 -0
- package/dist/core/runtime.d.ts +9 -0
- package/dist/core/safe-notify.d.ts +64 -0
- package/dist/core/safety-axis-vocab.d.ts +23 -0
- package/dist/core/safety-merge-corpus.d.ts +37 -0
- package/dist/core/scheduler.d.ts +121 -0
- package/dist/core/secret-env.d.ts +32 -0
- package/dist/core/select-model.d.ts +15 -0
- package/dist/core/sensitive-path-policy.d.ts +42 -0
- package/dist/core/session-policy-store.d.ts +94 -0
- package/dist/core/session-reconcile.d.ts +80 -0
- package/dist/core/session-store.d.ts +85 -0
- package/dist/core/session.d.ts +153 -0
- package/dist/core/shared-memory/contract.d.ts +22 -0
- package/dist/core/shared-memory/normalize.d.ts +123 -2
- package/dist/core/shared-memory/tools.d.ts +14 -0
- package/dist/core/shared-memory/types.d.ts +105 -0
- package/dist/core/shutdown-debug.d.ts +6 -0
- package/dist/core/side-query.d.ts +38 -0
- package/dist/core/side-query.js +6 -1
- package/dist/core/skill-tool-specifier.d.ts +72 -0
- package/dist/core/skills-directory.d.ts +100 -1
- package/dist/core/spec-contract.d.ts +89 -0
- package/dist/core/store-contracts/background-agent-store-contract.d.ts +31 -0
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +26 -0
- package/dist/core/store-contracts/contract-harness.d.ts +20 -0
- package/dist/core/store-contracts/contract-kit-version.d.ts +27 -0
- package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +8 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +42 -0
- package/dist/core/store-contracts/tool-result-store-contract.d.ts +13 -0
- package/dist/core/strategy-store.d.ts +37 -0
- package/dist/core/stub-env.d.ts +7 -0
- package/dist/core/surrogate-safe-slice.d.ts +35 -0
- package/dist/core/task-notification.d.ts +202 -0
- package/dist/core/task-outcome.d.ts +53 -0
- package/dist/core/task-registry-agent.d.ts +337 -1
- package/dist/core/task-registry-monitor.d.ts +12 -0
- package/dist/core/task-registry-shared.d.ts +540 -0
- package/dist/core/task-registry.d.ts +343 -0
- package/dist/core/task-registry.js +13 -2
- package/dist/core/task-tool-shape.d.ts +44 -0
- package/dist/core/tighten-task-spec.d.ts +21 -0
- package/dist/core/tool-detach.d.ts +21 -0
- package/dist/core/tool-errors.d.ts +131 -0
- package/dist/core/tool-errors.js +4 -0
- package/dist/core/tool-name-aliases.d.ts +27 -0
- package/dist/core/tool-policy.d.ts +555 -0
- package/dist/core/tool-result-budget.d.ts +32 -0
- package/dist/core/tool-result-store.d.ts +174 -1
- package/dist/core/tools.d.ts +45 -0
- package/dist/core/trace.d.ts +323 -0
- package/dist/core/types.d.ts +3859 -2
- package/dist/core/untrusted-egress.d.ts +8 -0
- package/dist/core/untrusted-text.d.ts +156 -0
- package/dist/core/usage-window-store.d.ts +95 -0
- package/dist/core/version.d.ts +1 -0
- package/dist/core/warm-resume.d.ts +17 -0
- package/dist/core/wiring-manifest.d.ts +169 -0
- package/dist/core/with-retry.d.ts +24 -0
- package/dist/core/workflow-journal-store.d.ts +160 -0
- package/dist/core/workflow-run-store-contract.d.ts +25 -0
- package/dist/core/workflow-run-store.d.ts +119 -0
- package/dist/engine/compaction/compaction.d.ts +256 -1
- package/dist/engine/compaction/utils.d.ts +94 -0
- package/dist/engine/execution-env/kill-tree.d.ts +29 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +94 -0
- package/dist/engine/harness/agent-harness.d.ts +116 -0
- package/dist/engine/harness/agent-harness.js +3 -14
- package/dist/engine/harness/messages.d.ts +15 -0
- package/dist/engine/harness/types.d.ts +464 -2
- package/dist/engine/llm/diagnostics.d.ts +4 -0
- package/dist/engine/llm/event-stream.d.ts +3 -0
- package/dist/engine/llm/index.d.ts +7 -0
- package/dist/engine/llm/types.d.ts +500 -3
- package/dist/engine/llm/validation.d.ts +3 -0
- package/dist/engine/loop/agent-loop.d.ts +87 -2
- package/dist/engine/loop/runtime-deps.d.ts +7 -0
- package/dist/engine/loop/types.d.ts +424 -0
- package/dist/engine/lsp/frame-decoder.d.ts +13 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +107 -0
- package/dist/engine/lsp/stdio-lsp-transport.d.ts +7 -0
- package/dist/engine/session/import-validate.d.ts +27 -0
- package/dist/engine/session/log-digest.d.ts +93 -0
- package/dist/engine/session/memory-repo.d.ts +6 -0
- package/dist/engine/session/memory-storage.d.ts +2 -0
- package/dist/engine/session/session.d.ts +75 -0
- package/dist/engine/session/storage-base.d.ts +8 -0
- package/dist/fixtures/index.d.ts +36 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.js +0 -1
- package/dist/internal/harness-types.d.ts +6 -0
- package/dist/internal/harness.d.ts +11 -0
- package/dist/internal/llm.d.ts +6 -0
- package/dist/orchestration/builtin-workflows.d.ts +53 -0
- package/dist/orchestration/dev-vm-script-runner.d.ts +19 -0
- package/dist/orchestration/goal.d.ts +57 -0
- package/dist/orchestration/goal.js +3 -0
- package/dist/orchestration/run-spec.d.ts +42 -0
- package/dist/orchestration/run-workflow-tool.d.ts +169 -0
- package/dist/orchestration/workflow-governance.d.ts +61 -0
- package/dist/orchestration/workflow-meta.d.ts +28 -0
- package/dist/orchestration/workflow-observe.d.ts +60 -0
- package/dist/orchestration/workflow-primitives.d.ts +23 -1
- package/dist/orchestration/workflow-sandbox-conformance.d.ts +38 -0
- package/dist/orchestration/workflow-script-runner.d.ts +88 -0
- package/dist/orchestration/workflow-script-store.d.ts +98 -0
- package/dist/orchestration/workflow-size-guideline.d.ts +67 -0
- package/dist/orchestration/workflow-types.d.ts +169 -2
- package/dist/orchestration/workflow.d.ts +358 -0
- package/dist/prompt-assembly/artifact-store.d.ts +33 -0
- package/dist/prompt-assembly/artifact.d.ts +25 -0
- package/dist/prompt-assembly/assemble.d.ts +20 -0
- package/dist/prompt-assembly/composer.d.ts +29 -0
- package/dist/prompt-assembly/epoch.d.ts +55 -1
- package/dist/prompt-assembly/event-registry.d.ts +35 -0
- package/dist/prompt-assembly/explain.d.ts +12 -0
- package/dist/prompt-assembly/tool-catalog.d.ts +38 -0
- package/dist/prompt-assembly/turn-snapshot.d.ts +40 -0
- package/dist/prompt-assembly/types.d.ts +115 -0
- package/dist/prompts/coordinator.d.ts +27 -0
- package/dist/prompts/default.d.ts +539 -0
- package/dist/prompts/simple-sections.d.ts +45 -0
- package/dist/prompts/supervisor.d.ts +66 -0
- package/dist/scenarios/env.d.ts +28 -0
- package/dist/scenarios/full-body.d.ts +50 -0
- package/dist/scenarios/scenario-registry.d.ts +60 -0
- package/dist/scenarios/teacher-quickstart.d.ts +27 -0
- package/dist/server/http.d.ts +17 -0
- package/dist/stores/cc/lockfile.d.ts +6 -0
- package/dist/stores/cc/mailbox-store.d.ts +8 -0
- package/dist/stores/cc/roster-adapter.d.ts +4 -0
- package/dist/stores/cc/sidecar-transcript.d.ts +66 -0
- package/dist/stores/file/background-agent-store.d.ts +24 -0
- package/dist/stores/file/checkpoint-store.d.ts +38 -0
- package/dist/stores/file/file-snapshot-store.d.ts +25 -0
- package/dist/stores/file/fs-atomic.d.ts +155 -0
- package/dist/stores/file/index.d.ts +89 -0
- package/dist/stores/file/mailbox-store.d.ts +36 -0
- package/dist/stores/file/memory-store.d.ts +82 -0
- package/dist/stores/file/permission-rule-store.d.ts +79 -0
- package/dist/stores/file/session-policy-store.d.ts +28 -0
- package/dist/stores/file/session-store.d.ts +40 -0
- package/dist/stores/file/shared-ledger.d.ts +83 -0
- package/dist/stores/file/tool-result-store.d.ts +11 -0
- package/dist/stores/file/usage-window-store.d.ts +18 -0
- package/dist/stores/file/workflow-journal-store.d.ts +100 -0
- package/dist/stores/file/workflow-run-store.d.ts +11 -0
- package/dist/tools/fs/bash-readonly-classifier.d.ts +282 -0
- package/dist/tools/fs/encoding.d.ts +60 -0
- package/dist/tools/fs/fs-bash.d.ts +133 -0
- package/dist/tools/fs/fs-pdf.d.ts +28 -0
- package/dist/tools/fs/fs-search-tools.d.ts +5 -0
- package/dist/tools/fs/fs-search-tools.js +0 -1
- package/dist/tools/fs/fs-shared.d.ts +360 -0
- package/dist/tools/fs/fs-write.d.ts +16 -0
- package/dist/tools/fs/gh-rate-limit.d.ts +22 -0
- package/dist/tools/fs/index.d.ts +79 -0
- package/dist/tools/fs/notebook.d.ts +56 -0
- package/dist/tools/fs/pdf.d.ts +70 -0
- package/dist/tools/fs/pdf.js +8 -2
- package/dist/tools/fs/repo-map.d.ts +10 -0
- package/dist/tools/fs/safety.d.ts +376 -0
- package/dist/tools/fs/search.d.ts +131 -0
- package/dist/tools/loop-tick.d.ts +24 -0
- package/dist/tools/monitor.d.ts +55 -0
- package/dist/tools/scheduler-tools.d.ts +51 -0
- package/dist/tools/sql-adapters.d.ts +18 -0
- package/dist/tools/sql.d.ts +25 -0
- package/dist/tools/task-list.d.ts +77 -0
- package/dist/tools/todo.d.ts +8 -0
- package/dist/tools/web.d.ts +184 -0
- package/dist/tools/worktree.d.ts +81 -0
- package/package.json +2 -2
- package/dist/tools/gitea-issue.d.ts +0 -13
- package/dist/tools/gitea-issue.js +0 -75
|
@@ -1,13 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RB-410 件1 — the Agent Skills (`SKILL.md`) directory loader.
|
|
3
|
+
*
|
|
4
|
+
* The open skills format (published at agentskills.io, reference implementation `anthropics/skills`) is
|
|
5
|
+
* a directory per skill: `skill-name/SKILL.md` holding a `---` frontmatter block plus a Markdown body,
|
|
6
|
+
* with optional `scripts/` / `references/` / `assets/` resource directories beside it. sema's
|
|
7
|
+
* {@link SkillSpec} is already the same shape — frontmatter → `name`/`description`, body → `content`,
|
|
8
|
+
* sibling resources → `files[]` — so the only missing piece was this reader. No engine mechanism
|
|
9
|
+
* changes: the output is an ordinary `SkillSpec[]` a deployment hands to `TaskSpec.skills`.
|
|
10
|
+
*
|
|
11
|
+
* **Deployment-half helper, called BEFORE a task starts.** It reads the filesystem synchronously and is
|
|
12
|
+
* NOT reachable from the run loop — the engine still never resolves a skill path at tool time, and never
|
|
13
|
+
* writes. An embedder serving skills from a remote/sandboxed filesystem should read through its own
|
|
14
|
+
* `ExecutionEnv` instead and construct `SkillSpec` objects directly; this helper is the local-disk case.
|
|
15
|
+
*
|
|
16
|
+
* **Trust contract is unchanged and is the caller's:** a skill IS instructions, so everything read here
|
|
17
|
+
* (body and attachments alike) enters the model's context as CALLER-TRUSTED material. Pointing this at a
|
|
18
|
+
* directory third parties can write to is the same as pasting their text into the system prompt. The
|
|
19
|
+
* loader validates SHAPE (spec conformance), never intent.
|
|
20
|
+
*
|
|
21
|
+
* **`allowed-tools` is mapped TIGHTEN-ONLY** — see {@link SkillsDirectoryOptions.deployedTools}.
|
|
22
|
+
*
|
|
23
|
+
* Frontmatter is parsed by a deliberately closed subset reader (no YAML dependency — the runtime
|
|
24
|
+
* dependency budget is a standing constraint): top-level `key: value` scalars, optional surrounding
|
|
25
|
+
* quotes, `#` comment lines, block scalars (`|` / `>` with their indentation + chomping indicators),
|
|
26
|
+
* flow sequences (`[a, b]`, including the multi-line form), and indented mapping bodies skipped
|
|
27
|
+
* wholesale. That covers every field the spec defines, and the same posture the memory-engine
|
|
28
|
+
* frontmatter reader already takes.
|
|
29
|
+
*/
|
|
1
30
|
import type { SkillSpec } from "./types.js";
|
|
2
|
-
|
|
31
|
+
/** Why one skill directory (or one of its parts) was not taken as-declared. */
|
|
32
|
+
export type SkillsDirectoryWarningCode =
|
|
33
|
+
/** The directory holds no `SKILL.md`. */
|
|
34
|
+
"no_skill_file"
|
|
35
|
+
/** `SKILL.md` has no well-formed `---` fenced frontmatter block. */
|
|
36
|
+
| "no_frontmatter"
|
|
37
|
+
/** Required `name` absent. */
|
|
38
|
+
| "missing_name"
|
|
39
|
+
/** `name` breaks the charset/length rule. */
|
|
40
|
+
| "invalid_name"
|
|
41
|
+
/** `name` disagrees with the directory name (the spec requires they match). */
|
|
42
|
+
| "name_mismatch"
|
|
43
|
+
/** Required `description` absent. */
|
|
44
|
+
| "missing_description"
|
|
45
|
+
/** RB-428-A: an `allowed-tools` entry carries a pattern specifier (`Bash(git:*)`) — the scope policy
|
|
46
|
+
* matches names, not patterns, so the entry cannot match and the tool is DISABLED in this skill
|
|
47
|
+
* frame. Disclosed loudly until pattern enforcement lands (the entry is deliberately NOT widened to
|
|
48
|
+
* its base name: that would turn "only git" into "all of Bash"). */
|
|
49
|
+
| "allowed_tool_pattern_unsupported"
|
|
50
|
+
/** `description` exceeds the spec cap. */
|
|
51
|
+
| "description_too_long"
|
|
52
|
+
/** An `allowed-tools` entry the deployment does not mount — dropped (tighten-only). */
|
|
53
|
+
| "allowed_tool_not_mounted"
|
|
54
|
+
/** A `disallowed-tools` declaration this mapping cannot carry — see {@link SkillsDirectoryOptions.deployedTools}. */
|
|
55
|
+
| "disallowed_tools_unenforced"
|
|
56
|
+
/** An attachment was left out (non-text bytes, over budget, unreadable, or resolving outside the skill). */
|
|
57
|
+
| "attachment_skipped"
|
|
58
|
+
/** A file or directory entry existed but could not be read/resolved. */
|
|
59
|
+
| "read_failed";
|
|
60
|
+
/** One non-fatal diagnostic from a load. Safe to log: no file contents, only names/reasons. */
|
|
3
61
|
export interface SkillsDirectoryWarning {
|
|
4
62
|
code: SkillsDirectoryWarningCode;
|
|
63
|
+
/** Directory name of the skill this concerns, relative to the scanned root. */
|
|
5
64
|
skill: string;
|
|
65
|
+
/** Human-readable detail (names the offending field/file and what was done about it). */
|
|
6
66
|
detail: string;
|
|
7
67
|
}
|
|
8
68
|
export interface SkillsDirectoryOptions {
|
|
69
|
+
/**
|
|
70
|
+
* The tool names this deployment actually mounts. When given, a skill's `allowed-tools` declaration is
|
|
71
|
+
* INTERSECTED with it and every name outside is dropped with an `allowed_tool_not_mounted` warning.
|
|
72
|
+
*
|
|
73
|
+
* 🔴 **Tighten-only, by ruling.** `allowed-tools` is a skill-authored capability claim and the format
|
|
74
|
+
* marks it experimental; sema's permission discipline is tighten-only, so it is mapped exclusively onto
|
|
75
|
+
* {@link SkillManifest} — a structure that can only SUBTRACT capability (the scope policy returns
|
|
76
|
+
* `allow`/`deny` and composes ahead of the task policy under a deny-short-circuit fold, so it can never
|
|
77
|
+
* re-grant what the task withheld). Consequences worth stating plainly:
|
|
78
|
+
* - a name outside `deployedTools` is dropped, NOT honored — a skill cannot pull in a tool the
|
|
79
|
+
* deployment never mounted;
|
|
80
|
+
* - when the intersection comes out EMPTY the manifest is still emitted with an empty `allowTools`
|
|
81
|
+
* (narrow to nothing while the skill's frame is active). Dropping the manifest instead would widen
|
|
82
|
+
* the run relative to what the skill asked for, which is the one direction this mapping may not take;
|
|
83
|
+
* - omitting `deployedTools` skips the filter. Still safe — an unmounted name simply never matches a
|
|
84
|
+
* call — but the warning is then unavailable, so a deployment that wants the audit trail should pass it.
|
|
85
|
+
*
|
|
86
|
+
* Names are compared in CANONICAL form on both sides (the same normalization the enforcing policy
|
|
87
|
+
* applies), so passing this option can never produce a stricter result than omitting it: a declared
|
|
88
|
+
* legacy alias and the mounted current name are one tool here exactly as they are at call time.
|
|
89
|
+
* A wildcard declaration (`allowed-tools: "*"`) claims the whole roster and therefore narrows by
|
|
90
|
+
* nothing — no manifest is emitted, leaving the task policy untouched.
|
|
91
|
+
*/
|
|
9
92
|
deployedTools?: readonly string[];
|
|
93
|
+
/** Sink for non-fatal diagnostics. Absent ⇒ warnings are dropped and the load still proceeds. */
|
|
10
94
|
onWarning?: (warning: SkillsDirectoryWarning) => void;
|
|
95
|
+
/**
|
|
96
|
+
* Total decoded-text budget for ONE skill's attachments, in bytes (default 256 KiB). Files are taken in
|
|
97
|
+
* path order until the budget is spent; the rest are skipped with a disclosed warning. Attachments also
|
|
98
|
+
* ride a separate delivery cap at invoke time, so a generous value here does not enlarge the prompt.
|
|
99
|
+
*/
|
|
11
100
|
maxAttachmentBytes?: number;
|
|
12
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Load every `SKILL.md`-bearing subdirectory of `dir` into a {@link SkillSpec}, ready for
|
|
104
|
+
* `TaskSpec.skills`. Results are ordered by directory name (deterministic across filesystems).
|
|
105
|
+
*
|
|
106
|
+
* Per-skill problems are NON-FATAL: a directory whose frontmatter breaks the spec (missing/invalid
|
|
107
|
+
* `name`, missing/over-long `description`, no fenced block, no `SKILL.md`) is SKIPPED and reported
|
|
108
|
+
* through {@link SkillsDirectoryOptions.onWarning}, so one malformed skill cannot take down a whole
|
|
109
|
+
* library. The root itself is different — an unreadable/non-directory root THROWS, because silently
|
|
110
|
+
* returning `[]` for a mistyped path would look exactly like "this deployment has no skills".
|
|
111
|
+
*/
|
|
13
112
|
export declare function createSkillsFromDirectory(dir: string, options?: SkillsDirectoryOptions): SkillSpec[];
|
|
@@ -1,57 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/125 — **SpecContract**:spec→Verifier 闭环的机器可读任务契约(make-real 两周实战纪律的
|
|
3
|
+
* 一等原语化)。本模块 = 纯 core 零件:契约类型 + 三值 oracle 执行器 + frozenPaths 校验/快照/恢复。
|
|
4
|
+
* 装配(policy 组合、stop 把关、outcome 发射)在 `orchestration/run-spec.ts`。
|
|
5
|
+
*
|
|
6
|
+
* 🔴 **信任声明(fable-M3)**:SpecContract 是 **CODE-tier** 输入 —— `oracle[].cmd` 会被亲跑(execFile,
|
|
7
|
+
* 任意命令)。它只能来自部署作者/可信代码路径;LLM 生成的 contract 直接喂 runSpec = 不受信输入获得
|
|
8
|
+
* 命令执行权(越红线),禁止。contract 里的 `spec` **文本**才是 DATA-tier(runSpec 恒围栏置入 objective)。
|
|
9
|
+
*
|
|
10
|
+
* 🔴 **oracle 三值(fable-M6)**:每门结果 ∈ {green, red, error} —— 判据不满足 = red;基础设施故障
|
|
11
|
+
* (ENOENT/timeout/maxBuffer/parse 解析不出)= **error 非 red**。假红防线:error 绝不冒充"曾经红过"
|
|
12
|
+
* (design/73 红线② 的机器化 —— `oracleHadRedRun` 只由真 red 观察置位)。
|
|
13
|
+
*/
|
|
14
|
+
/** Declarative green criteria for one oracle gate. Absent ⇒ `exitCode === 0`. All declared criteria AND. */
|
|
1
15
|
export interface OracleGreenSpec {
|
|
16
|
+
/** Expected exit code. Default 0 when no `parse` is declared; with `parse`, exit code is only
|
|
17
|
+
* checked when explicitly set here (test runners exit non-zero on failures the counts already judge). */
|
|
2
18
|
exitCode?: number;
|
|
19
|
+
/** Regex (source string) that MUST match the combined stdout+stderr. */
|
|
3
20
|
mustMatch?: string;
|
|
21
|
+
/** Regex (source string) that MUST NOT match the combined stdout+stderr. */
|
|
4
22
|
mustNotMatch?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Parsing criteria (fable-M5/B1 一体解): extract pass/fail counts from the output. Each regex's FIRST
|
|
25
|
+
* capture group is the integer count (e.g. `"ℹ pass (\\d+)"`). Either regex failing to match = the gate
|
|
26
|
+
* is **error** (解析不出 ≠ red — a runner that printed nothing proves nothing).
|
|
27
|
+
*/
|
|
5
28
|
parse?: {
|
|
6
29
|
passRe: string;
|
|
7
30
|
failRe: string;
|
|
8
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* Lower bound on the parsed pass count (requires `parse`). `"baseline"` = the pass+fail TOTAL this gate
|
|
34
|
+
* observed at preflight — the anti-「测试消失式走捷径」 gate (the model leaves tests untouched but makes
|
|
35
|
+
* them undiscovered; harness :114 实战门, fable-B1). Numeric default when absent: 1 (a zero-test green
|
|
36
|
+
* is vacuous).
|
|
37
|
+
*/
|
|
9
38
|
minPass?: number | "baseline";
|
|
10
39
|
}
|
|
40
|
+
/** One mechanical adjudicator: a command run via execFile (NO shell) + declarative green criteria. */
|
|
11
41
|
export interface OracleGateSpec {
|
|
42
|
+
/** Stable gate name (baseline capture and per-gate reporting key on it). */
|
|
12
43
|
name: string;
|
|
44
|
+
/** argv — `cmd[0]` is the executable, the rest are arguments. execFile, never a shell. */
|
|
13
45
|
cmd: string[];
|
|
46
|
+
/** Working directory, containment-checked against the runSpec root (same rule as frozenPaths). */
|
|
14
47
|
cwd?: string;
|
|
48
|
+
/** Per-gate timeout. Default 60s. */
|
|
15
49
|
timeoutMs?: number;
|
|
16
50
|
green?: OracleGreenSpec;
|
|
17
51
|
}
|
|
52
|
+
/** design/125 D1 — the machine-readable task contract (CODE-tier input; see module doc). */
|
|
18
53
|
export interface SpecContract {
|
|
54
|
+
/** Task spec text (or a file reference resolved against the runSpec root). runSpec owns the objective
|
|
55
|
+
* framing; the spec text itself is DATA-tier and is ALWAYS fenced before injection. */
|
|
19
56
|
spec: string | {
|
|
20
57
|
path: string;
|
|
21
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* Read-only specification surface. **Validation (fable-M2)**: absolute paths and `..` segments are
|
|
61
|
+
* rejected; paths resolve against the runSpec root with a containment check; policy matching uses the
|
|
62
|
+
* RESOLVED path. Exact paths, no globs (v1 收窄).
|
|
63
|
+
*/
|
|
22
64
|
frozenPaths: string[];
|
|
65
|
+
/** Mechanical adjudicators (serializable, checkpointable, service-boundary-safe, feed-recordable). */
|
|
23
66
|
oracle: OracleGateSpec[];
|
|
67
|
+
/**
|
|
68
|
+
* 双向验证: preflight runs the full oracle and REQUIRES red (proves the spec has substance), capturing
|
|
69
|
+
* baseline counts for `minPass:"baseline"` (fable-B1: the red gate and the baseline are two faces of the
|
|
70
|
+
* same preflight). Default **true** (the discipline is the default; opting out must be explicit).
|
|
71
|
+
* `{ exempt }` documents WHY this contract legitimately starts green (e.g. pure-refactor spec).
|
|
72
|
+
*/
|
|
24
73
|
requireRedStart?: boolean | {
|
|
25
74
|
exempt: string;
|
|
26
75
|
};
|
|
76
|
+
/** design/73 aggregation key. Default: `spec:<sha256(specText) first 16 hex>`. */
|
|
27
77
|
taskSignature?: string;
|
|
28
78
|
}
|
|
79
|
+
/** Three-value gate verdict — `error` = the adjudicator itself failed to run/parse (NEVER counts as red). */
|
|
29
80
|
export type OracleVerdict = "green" | "red" | "error";
|
|
30
81
|
export interface OracleGateResult {
|
|
31
82
|
name: string;
|
|
32
83
|
verdict: OracleVerdict;
|
|
84
|
+
/** Process exit code (null when the process did not run/complete — spawn error or timeout kill). */
|
|
33
85
|
exitCode: number | null;
|
|
86
|
+
/** Parsed counts when `green.parse` was declared and both regexes matched. */
|
|
34
87
|
pass?: number;
|
|
35
88
|
fail?: number;
|
|
89
|
+
/** Which criterion failed / what the infrastructure error was (first-party classification string). */
|
|
36
90
|
reason?: string;
|
|
91
|
+
/** Tail of the combined stdout+stderr (UNTRUSTED — the model can influence it via the code under test;
|
|
92
|
+
* fence with `delimitUntrusted` before any model-facing use). */
|
|
37
93
|
outputTail: string;
|
|
38
94
|
}
|
|
95
|
+
/** Per-gate preflight counts backing `minPass:"baseline"` (keyed by gate name). */
|
|
39
96
|
export type OracleBaseline = Record<string, {
|
|
40
97
|
pass: number;
|
|
41
98
|
fail: number;
|
|
42
99
|
}>;
|
|
43
100
|
export interface OracleRunReport {
|
|
101
|
+
/** Worst-across-gates: any `error` ⇒ error (fail-loud dominates); else any `red` ⇒ red; else green. */
|
|
44
102
|
verdict: OracleVerdict;
|
|
45
103
|
gates: OracleGateResult[];
|
|
46
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Run every gate of the contract's oracle (sequentially — gates commonly share a working tree) and fold
|
|
107
|
+
* the three-value verdicts: any `error` ⇒ `error` (fail-loud dominates; an unfalsifiable adjudication must
|
|
108
|
+
* never pass silently), else any `red` ⇒ `red`, else `green`.
|
|
109
|
+
*
|
|
110
|
+
* `cwdRoot` is the runSpec root: each gate's `cwd` resolves against it with the same containment rule as
|
|
111
|
+
* frozenPaths (a contract cannot point its adjudicator outside the workcopy).
|
|
112
|
+
*/
|
|
47
113
|
export declare function runOracle(gates: OracleGateSpec[], cwdRoot: string, opts?: {
|
|
48
114
|
baseline?: OracleBaseline;
|
|
49
115
|
signal?: AbortSignal;
|
|
50
116
|
}): Promise<OracleRunReport>;
|
|
117
|
+
/** Extract the per-gate baseline counts from a (preflight) report — only gates whose parse succeeded. */
|
|
51
118
|
export declare function captureBaseline(report: OracleRunReport): OracleBaseline;
|
|
119
|
+
/** A coded error (`config.*` / `spec.*` convention — same shape as goal.ts's reserved-name fail-fast). */
|
|
52
120
|
export declare function specError(code: string, message: string): Error & {
|
|
53
121
|
code: string;
|
|
54
122
|
};
|
|
123
|
+
/**
|
|
124
|
+
* Validate and resolve `frozenPaths` against the runSpec root (fable-M2): absolute paths and `..`
|
|
125
|
+
* segments are rejected outright (`spec.frozen_path_invalid`); the resolved path must stay inside the
|
|
126
|
+
* root. Returns resolved absolute paths (the ONLY form policy matching and snapshots use).
|
|
127
|
+
*/
|
|
55
128
|
export declare function resolveFrozenPaths(rootDir: string, frozenPaths: string[]): string[];
|
|
129
|
+
/**
|
|
130
|
+
* Byte-level snapshot of the frozen surface (fable-M1: a hash can only DETECT tampering — restoring needs
|
|
131
|
+
* the CONTENT, and the snapshot is the restore source; no external seed directory dependency). Missing
|
|
132
|
+
* file ⇒ `spec.frozen_missing` (a frozen path that doesn't exist can't be a specification).
|
|
133
|
+
*/
|
|
56
134
|
export declare function snapshotFrozenPaths(resolvedPaths: string[]): Map<string, Buffer>;
|
|
135
|
+
/**
|
|
136
|
+
* Restore any frozen file whose on-disk bytes differ from the snapshot (belt for `echo > test/x`-style
|
|
137
|
+
* bash writes the Write/Edit deny policy cannot see — fable-MIN2). Returns the number of files restored.
|
|
138
|
+
*
|
|
139
|
+
* Symlink-safe (codex 实现审 B2): a tampered entry that is no longer a regular file (the model swapped
|
|
140
|
+
* it for a symlink pointing outside the root) is REMOVED first — the snapshot bytes are then written to
|
|
141
|
+
* a fresh regular file, never THROUGH a link. When `rootDir` is given, the parent directory's physical
|
|
142
|
+
* path is containment-checked too (a symlinked PARENT dir would also carry the write outside); an entry
|
|
143
|
+
* whose parent escapes is skipped (counted) — the terminal oracle then adjudicates the missing spec
|
|
144
|
+
* files honestly (fail-safe direction) instead of runSpec writing outside its root.
|
|
145
|
+
*/
|
|
57
146
|
export declare function restoreFrozenPaths(snapshot: Map<string, Buffer>, rootDir?: string): number;
|
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
import { type BackgroundAgentStore } from "../background-agent-store.js";
|
|
2
2
|
import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
3
|
+
/**
|
|
4
|
+
* design/159 — the cross-backend {@link BackgroundAgentStore} contract kit (vitest-free; see
|
|
5
|
+
* `contract-harness.ts` for the runner seam and `contract-kit-version.ts` for version lockstep).
|
|
6
|
+
* `make()` must return a FRESH, empty store each call; a store a case creates is closed (`close?.()`)
|
|
7
|
+
* when the case ends, so a backend holding a file descriptor does not leak one per case.
|
|
8
|
+
*
|
|
9
|
+
* 为什么这个家族需要一份共跑资产:这个 store 的两个捆绑后端是逐方法手写的孪生实现,而本仓在它上面
|
|
10
|
+
* 已经连续吃过四次「一份修了、另一份没修」——RB-60 / RB-74 / RB-87 / RB-111,其中 RB-87 与 RB-111
|
|
11
|
+
* 是同一个 reap 重复计数缺陷在两个后端里分别被发现、相隔一个版本。REF-A3/REF-D18 之后共享形状收敛
|
|
12
|
+
* 到了单一构造点,但**语义**仍然只由每个后端各自的测试看住;第三方后端更是完全在射程之外。这份
|
|
13
|
+
* 试剂盒把语义变成全后端共跑的验收底线:任何后端在这里变红 = 该后端违约,**不许通过放宽契约让它
|
|
14
|
+
* 变绿**。
|
|
15
|
+
*
|
|
16
|
+
* 断言只描述已落地的行为(权威文本 = `src/core/background-agent-store.ts` 的接口契约段),不引入
|
|
17
|
+
* 任何新义务。
|
|
18
|
+
*
|
|
19
|
+
* 分层:
|
|
20
|
+
* - 核心层 {@link backgroundAgentStoreContract}:每个后端都必须过。
|
|
21
|
+
* - 可选能力层 {@link backgroundAgentStoreScopesContract}:只挂实现了可选方法 `listScopes` 的后端
|
|
22
|
+
* (接口把它标为可选——把它折进核心层就会变成「没实现的后端静默跳过」,而静默跳过正是假绿的
|
|
23
|
+
* 来源)。两个捆绑后端都实现了它,都挂。
|
|
24
|
+
*/
|
|
25
|
+
/** 契约统一用的租户 scope(核心层的多租户用例会另外显式构造第二个)。 */
|
|
3
26
|
export declare const BACKGROUND_AGENT_CONTRACT_SCOPE = "tenant-A";
|
|
27
|
+
/**
|
|
28
|
+
* 核心不变量层 —— 每个 {@link BackgroundAgentStore} 后端都必须过。
|
|
29
|
+
*/
|
|
4
30
|
export declare function backgroundAgentStoreContract(mk: () => BackgroundAgentStore, runAssertion?: ContractAssertionRunner): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* 可选能力层 —— 只挂实现了 {@link BackgroundAgentStore.listScopes} 的后端。接口把该方法标为可选
|
|
33
|
+
* (一个把租户清单记在别处的部署可以省略它),所以它不能进核心层:核心层里的「没实现就跳过」等于
|
|
34
|
+
* 给不合规后端发一张假绿通行证。两个捆绑后端都实现了它。
|
|
35
|
+
*/
|
|
5
36
|
export declare function backgroundAgentStoreScopesContract(mk: () => BackgroundAgentStore, runAssertion?: ContractAssertionRunner): Promise<void>;
|
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
import { type Checkpoint, type CheckpointStore, type ResumeOutcome } from "../checkpoint-store.js";
|
|
2
2
|
import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
3
|
+
/**
|
|
4
|
+
* design/159 S1 — the cross-backend {@link CheckpointStore} contract, extracted VERBATIM from
|
|
5
|
+
* `test/cross-backend-shared.ts` (design/87 §3 gap [cross-backend-enforce], the anti-drift guard
|
|
6
|
+
* born in design/80 §6.3) into a vitest-free kit a third-party backend implementor can import and
|
|
7
|
+
* run under any harness (or none — see {@link ContractAssertionRunner}).
|
|
8
|
+
*
|
|
9
|
+
* `make()` must return a FRESH, empty store each call. Core binds this to InMemory + File
|
|
10
|
+
* (`test/cross-backend-inmem-file.test.ts`) and Pg via pg-mem (`test/pg-cross-backend.test.ts`);
|
|
11
|
+
* a third-party durable backend passes its own factory.
|
|
12
|
+
*
|
|
13
|
+
* Version lockstep: see `contract-kit-version.ts` (`CONTRACT_KIT_ENGINE_VERSION`).
|
|
14
|
+
*/
|
|
15
|
+
/** Build a {@link Checkpoint} fixture. `createdAt` is FIXED (not wall-clock) so summary projections
|
|
16
|
+
* are deterministic and cross-backend byte-comparable; override via `over` for ordering tests. */
|
|
3
17
|
export declare function createCheckpointFixture(over?: Partial<Checkpoint>): Checkpoint;
|
|
18
|
+
/** The canonical `policy_ask allow` outcome the contract resolves with. Declared as the NARROW
|
|
19
|
+
* `policy_ask` arm — not the whole union — so field access and spread call sites need no
|
|
20
|
+
* re-assertion (RB-396-d: the wide declaration forced an `as Extract<…>` + a same-value
|
|
21
|
+
* `boundCallId` overwrite at one site — verbatim 移植残渣, both gone with this declaration). */
|
|
4
22
|
export declare const ALLOW: Extract<ResumeOutcome, {
|
|
5
23
|
gate: "policy_ask";
|
|
6
24
|
}>;
|
|
25
|
+
/**
|
|
26
|
+
* The full cross-backend contract for {@link CheckpointStore} — the SAME assertions for every
|
|
27
|
+
* backend. Entries are a 1:1 port of the vitest originals (assertion semantics unchanged).
|
|
28
|
+
*/
|
|
7
29
|
export declare function checkpointStoreContract(make: () => CheckpointStore, runAssertion?: ContractAssertionRunner): Promise<void>;
|
|
30
|
+
/** Seed the canonical listByScope fixture into `store` and return the sorted summaries. Compare the
|
|
31
|
+
* result against {@link EXPECTED_LISTBYSCOPE_SUMMARIES} (deep equality) to prove the backend's
|
|
32
|
+
* summary projection matches the reference — the caller owns the comparison (harness-specific). */
|
|
8
33
|
export declare function checkpointListByScopeSummaries(store: CheckpointStore): Promise<import("../checkpoint-store.js").CheckpointSummary[]>;
|
|
34
|
+
/** The canonical expected summary projection (what `summarizeCheckpoint` must yield for the fixture above). */
|
|
9
35
|
export declare const EXPECTED_LISTBYSCOPE_SUMMARIES: ({
|
|
10
36
|
token: string;
|
|
11
37
|
sessionId: string;
|
|
@@ -1,5 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/159 S1 — the shared runner seam every store-contract kit in this directory uses, extracted
|
|
3
|
+
* verbatim from the proven shape in `src/core/workflow-run-store-contract.ts` (the kit service
|
|
4
|
+
* already consumes in production). vitest-free BY CONTRACT: the kits run under any harness — a
|
|
5
|
+
* vitest binding passes `(name, fn) => { it(name, fn); }`, a bare script passes nothing and gets
|
|
6
|
+
* the sequential default — so a third-party store implementor needs NO test framework to verify
|
|
7
|
+
* their backend (cli [2081]: shell/client-core run self-written runners).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Labels + schedules one contract case. May return a promise (collected and awaited by the kit's
|
|
11
|
+
* final `Promise.all`) or register the case with a harness and return void (vitest `it`).
|
|
12
|
+
*
|
|
13
|
+
* ⚠️ Binding note (service [390], inherited from workflowRunStoreContract): cases are REGISTERED
|
|
14
|
+
* eagerly — an async runner that starts work immediately will interleave cases. Every case builds
|
|
15
|
+
* its own fresh store via `make()`, so interleaving is safe UNLESS your binding's stores share
|
|
16
|
+
* state (e.g. SQL twins on one table); such bindings must serialize inside `runAssertion`.
|
|
17
|
+
*/
|
|
1
18
|
export type ContractAssertionRunner = (name: string, fn: () => Promise<void>) => void | Promise<void>;
|
|
19
|
+
/** The no-harness default: run each case immediately in order, surfacing the first failure. */
|
|
2
20
|
export declare function defaultSequentialRunner(_name: string, fn: () => Promise<void>): Promise<void>;
|
|
21
|
+
/** The eager-register + collect-promises loop shared by every kit (same semantics as the inline
|
|
22
|
+
* original in workflow-run-store-contract.ts). Call `run` per case, then `await settle()`. */
|
|
3
23
|
export declare function beginContract(runAssertion?: ContractAssertionRunner): {
|
|
4
24
|
run: (name: string, fn: () => Promise<void>) => void;
|
|
5
25
|
settle: () => Promise<void>;
|
|
@@ -1 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/159 S1 — the contract kit's version-lockstep constant (server [2058] requirement ①).
|
|
3
|
+
*
|
|
4
|
+
* The store-contract kit ships INSIDE `@sema-agent/core` and evolves in lockstep with the engine —
|
|
5
|
+
* an assertion added because an engine release changed a store's semantics is only meaningful
|
|
6
|
+
* against THAT engine generation. Because kit and engine are one package, lockstep holds by
|
|
7
|
+
* construction and no entry point asserts a host version; this constant exists so an EXTERNAL
|
|
8
|
+
* consumer can make the pairing loud instead of silent:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { CONTRACT_KIT_ENGINE_VERSION } from "@sema-agent/core/…";
|
|
12
|
+
* if (CONTRACT_KIT_ENGINE_VERSION !== myPinnedEngineVersion) {
|
|
13
|
+
* throw new Error(`contract kit ${CONTRACT_KIT_ENGINE_VERSION} != engine ${myPinnedEngineVersion}`);
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* A third party running an old kit against a new engine (or the reverse) would otherwise get a
|
|
18
|
+
* silent false-green ([2021] A1 form) — e.g. a pre-2.2.0 kit has no idempotent-reopen entry, so a
|
|
19
|
+
* wiping SessionRepo passes it. Compare this constant against the `@sema-agent/core` version you
|
|
20
|
+
* actually resolved (read the installed package.json — the lock file can pin something older than
|
|
21
|
+
* what your manifest says).
|
|
22
|
+
*
|
|
23
|
+
* Same source as `package.json` `version`: resolved at runtime via {@link engineVersion} (the
|
|
24
|
+
* package's own package.json, memoized, "unknown" only under an exotic bundler that severed the
|
|
25
|
+
* module from its package root). A test pins it equal to the repo's package.json so the relative
|
|
26
|
+
* walk can never drift from the published value.
|
|
27
|
+
*/
|
|
1
28
|
export declare const CONTRACT_KIT_ENGINE_VERSION: string;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { FileSnapshotStore } from "../file-snapshot-store.js";
|
|
2
2
|
import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
3
3
|
export declare function fileSnapshotStoreContract(make: () => FileSnapshotStore, runAssertion?: ContractAssertionRunner, options?: {
|
|
4
|
+
/**
|
|
5
|
+
* How quickly unreferenced BLOB BYTES become unreadable after a reap. The MANIFEST key is a hard
|
|
6
|
+
* contract either way (invisible immediately). `"immediate"` (default — the in-memory and file
|
|
7
|
+
* reference backends): `getBlob` of a just-unreferenced hash is `undefined` right after `reap`
|
|
8
|
+
* returns. `"eventual"`: a durable/object-storage backend that hands byte GC to an asynchronous
|
|
9
|
+
* sweeper (so a reap on the request path is never held hostage by external-storage latency) —
|
|
10
|
+
* the immediate-unreadability assertion is skipped; the backend owns proving its sweeper.
|
|
11
|
+
*/
|
|
4
12
|
blobGc?: "immediate" | "eventual";
|
|
5
13
|
}): Promise<void>;
|
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
import type { MailboxStore } from "../mailbox-store.js";
|
|
2
2
|
import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
3
|
+
/**
|
|
4
|
+
* design/159 S1 — the cross-backend {@link MailboxStore} contract, extracted VERBATIM from
|
|
5
|
+
* `test/mailbox-contract.ts` (design/157 A11's two-layer form) into a vitest-free kit (see
|
|
6
|
+
* `contract-harness.ts` for the runner seam and `contract-kit-version.ts` for version lockstep).
|
|
7
|
+
*
|
|
8
|
+
* 为什么这个家族有契约(结构性复发机制,两次实证):契约 harness 此前只喂 InMemory + File 两个
|
|
9
|
+
* 后端,于是没进 harness 的那个后端反复独立漂移 ——
|
|
10
|
+
* - RB-86:`stores/cc/mailbox-store.ts` 注释自陈 "the contract both bundled backends already
|
|
11
|
+
* honor, missing only here"(空箱 claimLease 不返回 null,还装上幽灵租约);
|
|
12
|
+
* - MB1(黑板 [1937]):CC 后端的 `ack` 根本不查 lease 表,注释自陈 "worse than the other two
|
|
13
|
+
* backends' pre-fix bug"。
|
|
14
|
+
* 两次漏的都是同一个后端。修法不是再补一次点,而是把契约本身变成全后端共跑的资产 —— design/159
|
|
15
|
+
* 再进一步:第三方后端也拿得到同一份资产。
|
|
16
|
+
*
|
|
17
|
+
* 分层(与 test/mailbox-contract.ts 的挂载对应):
|
|
18
|
+
* - T1 核心不变量层 = {@link mailboxStoreContract} + {@link mailboxAckOwnershipContract}:每个后端
|
|
19
|
+
* 都必须过。任何后端在这一层变红 = 该后端违约,**不许通过放宽契约让它变绿**。核心层一律用
|
|
20
|
+
* `scope: "default"`({@link MAILBOX_CONTRACT_SCOPE}),这样租户轴受限的后端(CC inbox 文件)
|
|
21
|
+
* 也跑同一段代码。
|
|
22
|
+
* - T2 可选能力层 = {@link mailboxBundledOnlyContract}:多租户隔离 + 键注入性,只挂具备租户轴/
|
|
23
|
+
* 自有键空间的后端(core 的两个捆绑后端;CC 按 D-3 边界豁免,豁免明细在
|
|
24
|
+
* `src/stores/cc/mailbox-store.ts` 模块头)。
|
|
25
|
+
*
|
|
26
|
+
* `make()` must return a FRESH, empty store each call. Stores a contract case creates are closed
|
|
27
|
+
* (`close?.()`) when the case ends — the file backend's append fd is refcounted, so a harness that
|
|
28
|
+
* runs many cases would otherwise hold descriptors until process exit.
|
|
29
|
+
*/
|
|
30
|
+
/** 核心层统一用的 scope —— 每个后端都必须服务它(租户轴受限的后端只服务它)。 */
|
|
3
31
|
export declare const MAILBOX_CONTRACT_SCOPE = "default";
|
|
32
|
+
/**
|
|
33
|
+
* T1 核心不变量层 —— 每个后端都跑。用例出处见每条内联注释(`src/core/mailbox-store.ts` 的接口
|
|
34
|
+
* 契约段是权威文本)。
|
|
35
|
+
*/
|
|
4
36
|
export declare function mailboxStoreContract(mk: () => MailboxStore, runAssertion?: ContractAssertionRunner): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* T1 核心不变量层(MB1 分册)—— ack 的 owner 围栏,与 {@link mailboxStoreContract} 同层同权重,
|
|
39
|
+
* 单独成函数只是为了让 MB1 的出处叙述留在它自己的挂载文件里
|
|
40
|
+
* (`test/mb1-mailbox-ack-ownership.test.ts`)。
|
|
41
|
+
*/
|
|
5
42
|
export declare function mailboxAckOwnershipContract(mk: () => MailboxStore, runAssertion?: ContractAssertionRunner): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* T2 可选能力层 —— 只挂具备租户轴 + 自有键空间的后端(core 的两个捆绑后端)。CC 后端按其形态
|
|
45
|
+
* 明文豁免(豁免明细在 `src/stores/cc/mailbox-store.ts` 模块头,D-3 裁定),不是「没做到所以
|
|
46
|
+
* 放宽」:核心层没有一条为了任何后端而弱化。第三方后端若有租户轴,应当也挂这一层。
|
|
47
|
+
*/
|
|
6
48
|
export declare function mailboxBundledOnlyContract(mk: () => MailboxStore, runAssertion?: ContractAssertionRunner): Promise<void>;
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import type { ToolResultStore } from "../tool-result-store.js";
|
|
2
2
|
import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
3
|
+
/**
|
|
4
|
+
* design/159 S1 — the cross-backend {@link ToolResultStore} contract, extracted VERBATIM from
|
|
5
|
+
* `test/cross-backend-shared.ts` into a vitest-free kit (see `contract-harness.ts` for the runner
|
|
6
|
+
* seam and `contract-kit-version.ts` for version lockstep). `make()` must return a FRESH, empty
|
|
7
|
+
* store each call.
|
|
8
|
+
*
|
|
9
|
+
* Semantics since @sema-agent/core 2.1.0 (RB-266 + RB-273): ref safety is UNIFORM across backends —
|
|
10
|
+
* the write face rejects the intersection-unsafe ref set on EVERY backend (`assertSafeToolResultRef`
|
|
11
|
+
* is the shared floor) and a ref the contract accepts must round-trip on EVERY backend (a backend
|
|
12
|
+
* with a narrower native key space owns an injective encoding, not a rejection). Before 2.1.0 the
|
|
13
|
+
* bundled backends genuinely diverged on both halves (dev-green / deployment-red), so running this
|
|
14
|
+
* kit against a pre-2.1.0-modeled backend is expected to go red on those two entries.
|
|
15
|
+
*/
|
|
3
16
|
export declare function toolResultStoreContract(make: () => ToolResultStore, runAssertion?: ContractAssertionRunner): Promise<void>;
|
|
@@ -1,18 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Teacher-mode strategy repository (design/14). Stores the *generalized* strategies a teacher gave
|
|
3
|
+
* that actually worked, so a later similar problem can be solved without re-consulting the teacher
|
|
4
|
+
* (Inter-Cascade cross-session reuse). Retrieval is deliberately **high-precision / low-recall**: a
|
|
5
|
+
* wrong strategy injected into a student costs wasted turns + a likely escalation (net negative),
|
|
6
|
+
* while a missed strategy just falls back to asking the teacher (baseline). `scope` is a **mandatory
|
|
7
|
+
* isolation boundary** (multi-tenant: one user's strategies must never leak to another).
|
|
8
|
+
*/
|
|
1
9
|
export interface StoredStrategy {
|
|
10
|
+
/** Stable id. */
|
|
2
11
|
id: string;
|
|
12
|
+
/** The raw task objective that triggered the teacher's help — matched against future objectives. */
|
|
3
13
|
problem: string;
|
|
14
|
+
/** The teacher's generalized approach (1-2 sentences). */
|
|
4
15
|
strategy: string;
|
|
16
|
+
/** The teacher's confidence (0-3) when it gave this. */
|
|
5
17
|
confidence: number;
|
|
18
|
+
/** Tenant/isolation scope (e.g. "user:42"). Strategies are only ever retrieved within their scope. */
|
|
6
19
|
scope: string;
|
|
20
|
+
/** ISO timestamp stored. */
|
|
7
21
|
ts: string;
|
|
22
|
+
/** Teacher model id, for future staleness handling. */
|
|
8
23
|
teacherModel?: string;
|
|
24
|
+
/** Reserved for a future generalized signature (v3 semantic matching). */
|
|
9
25
|
signature?: string;
|
|
10
26
|
}
|
|
11
27
|
export interface StrategyStore {
|
|
28
|
+
/** Persist a strategy (implementations may merge an exact near-duplicate and cap per-scope size). */
|
|
12
29
|
save(s: StoredStrategy): Promise<void> | void;
|
|
30
|
+
/**
|
|
31
|
+
* The most relevant strategies for `query`, within `scope`, at most `limit`.
|
|
32
|
+
*
|
|
33
|
+
* `limit` must be a non-negative integer, or `Infinity` for the explicit "no cap" (return every
|
|
34
|
+
* match). Any other value — NaN, `-Infinity`, negative, fractional — is refused rather than folded
|
|
35
|
+
* into some nearby number (ruled 2026-08-04): a retrieval cap that silently becomes 0 turns "give me
|
|
36
|
+
* everything" into "give me nothing", and the caller sees only an empty result it cannot distinguish
|
|
37
|
+
* from "no strategies stored".
|
|
38
|
+
*/
|
|
13
39
|
find(scope: string, query: string, limit: number): Promise<StoredStrategy[]> | StoredStrategy[];
|
|
40
|
+
/**
|
|
41
|
+
* Optional: trim a scope to `maxSize` (evicting the least useful). `maxSize` must be a non-negative
|
|
42
|
+
* integer; 0 is a legal "empty the scope". Unlike {@link find}'s `limit`, `Infinity` is REFUSED here
|
|
43
|
+
* (ruled 2026-08-04): this is a capacity cap, and a capacity cap can be widened but never turned off.
|
|
44
|
+
*/
|
|
14
45
|
prune?(scope: string, maxSize: number): Promise<void> | void;
|
|
15
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Default in-memory store. Retrieval: a stored problem must contain **every significant** query token
|
|
49
|
+
* (and there must be ≥1) — near-exact on the meaningful words, ignoring stopword noise. High precision
|
|
50
|
+
* by design. Ranked by `confidence × recency`. Per-scope capacity cap with eviction on save.
|
|
51
|
+
*/
|
|
16
52
|
export declare class InMemoryStrategyStore implements StrategyStore {
|
|
17
53
|
private byScope;
|
|
18
54
|
private readonly maxPerScope;
|
|
@@ -20,5 +56,6 @@ export declare class InMemoryStrategyStore implements StrategyStore {
|
|
|
20
56
|
save(s: StoredStrategy): void;
|
|
21
57
|
find(scope: string, query: string, limit: number): StoredStrategy[];
|
|
22
58
|
prune(scope: string, maxSize: number): void;
|
|
59
|
+
/** Total stored strategies (across scopes); for tests/observability. */
|
|
23
60
|
get size(): number;
|
|
24
61
|
}
|
package/dist/core/stub-env.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { type ExecResult, type ExecutionEnv, ExecutionError, FileError, type FileInfo, type Result } from "../internal/harness.js";
|
|
2
|
+
/**
|
|
3
|
+
* A no-op ExecutionEnv for tool/MCP-only deployments (no shell, no filesystem).
|
|
4
|
+
*
|
|
5
|
+
* AgentHarness requires an `env`, but the normal tools+MCP code path never touches it.
|
|
6
|
+
* Every filesystem op returns a `not_supported` FileError; `exec` returns `shell_unavailable`.
|
|
7
|
+
* If a task genuinely needs shell/fs, supply a real ExecutionEnv instead (e.g. a Node or SSH one).
|
|
8
|
+
*/
|
|
2
9
|
export declare class StubExecutionEnv implements ExecutionEnv {
|
|
3
10
|
cwd: string;
|
|
4
11
|
constructor(cwd?: string);
|
|
@@ -1,4 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code-point-boundary-safe head/tail slicing — the one arithmetic every head+tail-with-marker truncator in
|
|
3
|
+
* this repo needs (`truncateError`, `clipWithFilePointer`, `truncateMcpErrorText`, `boundedString`,
|
|
4
|
+
* `truncateForSummary`).
|
|
5
|
+
*
|
|
6
|
+
* Why this exists as its own module: cutting a string at a UTF-16 code-unit index can land BETWEEN the two
|
|
7
|
+
* halves of an astral code point, and the result is a lone surrogate — a string that still satisfies the
|
|
8
|
+
* length bound but can no longer round-trip through UTF-8 (JSON frames, log files, prompt assembly). The
|
|
9
|
+
* same defect has been found and fixed one site at a time (RB-122 in `clipWithFilePointer`, then
|
|
10
|
+
* `truncateError`, then the three siblings above), which is exactly the shape a shared primitive prevents.
|
|
11
|
+
*
|
|
12
|
+
* Anchored on CC 2.1.220 `A7e`'s helpers `ma` (head) / `_W` (tail): drop the straddling code point WHOLE
|
|
13
|
+
* rather than emit half of it. Zero imports, so any module in the repo may depend on it without risking an
|
|
14
|
+
* import cycle.
|
|
15
|
+
*
|
|
16
|
+
* NOTE for whoever next touches `src/core/tool-errors.ts`: that file still declares a byte-identical private
|
|
17
|
+
* pair (`sliceHeadSafe`/`sliceTailSafe`, added by the earlier car in this class). Collapsing it onto this
|
|
18
|
+
* module — delete the two private copies plus `isHighSurrogate`/`isLowSurrogate` and import from here — is
|
|
19
|
+
* the remaining step to "one construction point"; it is outside this car's edit surface and is reported
|
|
20
|
+
* rather than done here.
|
|
21
|
+
*/
|
|
22
|
+
/** High half of a surrogate pair (U+D800–U+DBFF): valid only when immediately FOLLOWED by a low half. */
|
|
1
23
|
export declare const isHighSurrogate: (c: number) => boolean;
|
|
24
|
+
/** Low half of a surrogate pair (U+DC00–U+DFFF): valid only when immediately PRECEDED by a high half. */
|
|
2
25
|
export declare const isLowSurrogate: (c: number) => boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Head-keep of at most `keep` code UNITS that never ends on a lone high surrogate — a code point straddling
|
|
28
|
+
* the cut is dropped whole (CC 2.1.220 `ma`).
|
|
29
|
+
*
|
|
30
|
+
* Callers must derive any "how much was dropped" count from the RETURNED length, never from `keep`: when
|
|
31
|
+
* the rollback fires the result is one unit SHORTER than the budget, and a count computed from `keep`
|
|
32
|
+
* under-reports by that unit.
|
|
33
|
+
*/
|
|
3
34
|
export declare function sliceHeadSafe(s: string, keep: number): string;
|
|
35
|
+
/**
|
|
36
|
+
* Tail-keep counterpart: at most `keep` code units, never STARTING on a lone low surrogate (CC 2.1.220
|
|
37
|
+
* `_W`). Same rule for the caller's dropped-count arithmetic — read it off the returned length.
|
|
38
|
+
*/
|
|
4
39
|
export declare function sliceTailSafe(s: string, keep: number): string;
|