@sema-agent/core 5.19.0 → 5.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +102 -4
- 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/roster-store.js +3 -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/circuit-breaker.js +14 -3
- 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 +108 -0
- package/dist/brain/timeout.js +11 -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 +293 -0
- package/dist/core/background-agent-store.js +5 -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 +609 -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/mailbox-store.js +2 -0
- package/dist/core/mcp.d.ts +385 -0
- package/dist/core/mcp.js +58 -11
- 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 +40 -0
- package/dist/core/retention-policy.js +21 -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 +51 -14
- package/dist/core/runner/prompt-suggestions.d.ts +7 -0
- package/dist/core/runner/runtask.d.ts +304 -3
- package/dist/core/runner/runtask.js +17 -2
- 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-agent.js +2 -0
- 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-policy.js +3 -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/core/workflow-run-store.js +2 -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 +17 -2
- package/dist/index.js +1 -2
- 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-spec.js +4 -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/orchestration/workflow.js +13 -2
- 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/background-agent-store.js +2 -1
- 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/mailbox-store.js +2 -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/stores/file/workflow-run-store.js +2 -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-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/web.js +32 -5
- 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,25 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured header fields of one memory entry (the CC frontmatter shape: `name`/`description`/
|
|
3
|
+
* `metadata.type`). `extra` preserves any additional frontmatter lines VERBATIM (round-trip safety:
|
|
4
|
+
* the engine must never destroy model-authored frontmatter it doesn't understand — same posture as
|
|
5
|
+
* the file store's unknown-op replay skip).
|
|
6
|
+
*/
|
|
1
7
|
export interface MemoryEntryFrontmatter {
|
|
8
|
+
/** Short kebab-case slug (CC `name:`). Defaults to the file slug when the model omits it. */
|
|
2
9
|
name?: string;
|
|
10
|
+
/** One-line summary used for recall relevance (CC `description:`). */
|
|
3
11
|
description?: string;
|
|
12
|
+
/** CC `metadata.type`: user | feedback | project | reference (unknown strings degrade, design/65). */
|
|
4
13
|
type?: string;
|
|
14
|
+
/** design/138 §2.4 删除防线 — the EXPLICIT tombstone. A file that merely disappears is NEVER a
|
|
15
|
+
* delete; only `deleted: true` in frontmatter produces a delete patch. */
|
|
5
16
|
deleted?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* design-A C-5 (AGENTS.md×ingest, [A1]) — TYPED provenance for entries an INGEST producer minted
|
|
19
|
+
* from a repo file (project instruction files: AGENTS.md/CLAUDE.md — the file-name policy lives
|
|
20
|
+
* in the deployment; this type never names files). `path` is repo-relative; `contentHash` covers
|
|
21
|
+
* the raw pre-cap source bytes (opaque to the engine — equality comparison only); `ingestedAt`
|
|
22
|
+
* is ms epoch. Closed kind on purpose: `"repo_file"` is the only provenance the trust gates
|
|
23
|
+
* reason about (I-2 below); a malformed/unknown provenance block in a file round-trips through
|
|
24
|
+
* `extra` verbatim instead (never destroyed, never trusted).
|
|
25
|
+
*/
|
|
6
26
|
provenance?: {
|
|
7
27
|
kind: "repo_file";
|
|
8
28
|
path: string;
|
|
9
29
|
contentHash: string;
|
|
10
30
|
ingestedAt: number;
|
|
11
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* design-A C-5/I-2 — the trust marker for repo-originated content: once `"untrusted"`, it can
|
|
34
|
+
* never be whitewashed. Enforcement is STRUCTURAL, not conventional: the backend contract
|
|
35
|
+
* (memory-backend-contract.ts) refuses any update patch that strips `trust`/`provenance` from an
|
|
36
|
+
* entry whose committed state carries `provenance.kind === "repo_file"` (malformed-refusal seat,
|
|
37
|
+
* same family as the `entry.id !== patch.id` clause). Single-value union on purpose — there is
|
|
38
|
+
* no `"trusted"` spelling to escalate to.
|
|
39
|
+
*/
|
|
12
40
|
trust?: "untrusted";
|
|
41
|
+
/** Unknown frontmatter lines preserved verbatim (order kept), re-serialized on projection. */
|
|
13
42
|
extra?: string[];
|
|
14
43
|
}
|
|
44
|
+
/** design/138 §2.1 — one memory entry (the unit the backend stores and the engine projects to a file). */
|
|
15
45
|
export interface MemoryEntry {
|
|
46
|
+
/** IMMUTABLE uuid — survives slug renames (consolidation cursors/vectors/dedup all key on it).
|
|
47
|
+
* Hidden in the file's frontmatter as `id:`; minted at harvest for id-less new files. */
|
|
16
48
|
id: string;
|
|
49
|
+
/** File-name identity (the path relative to its scope dir, without `.md`) — model-visible, renameable. */
|
|
17
50
|
slug: string;
|
|
18
51
|
frontmatter: MemoryEntryFrontmatter;
|
|
52
|
+
/** The markdown body (everything after the frontmatter block). */
|
|
19
53
|
body: string;
|
|
54
|
+
/** CAS baseline — a content hash over (id, frontmatter, body). See {@link computeEntryRev}. */
|
|
20
55
|
rev: string;
|
|
56
|
+
/** Owning scope (tenant/layer key, same vocabulary as `TaskSpec.memory.scopes`). */
|
|
21
57
|
scope: string;
|
|
22
58
|
}
|
|
59
|
+
/** Manifest-level header: enough to judge relevance / build the derived index, never the body. */
|
|
23
60
|
export interface MemoryEntryHeader {
|
|
24
61
|
id: string;
|
|
25
62
|
slug: string;
|
|
@@ -27,20 +64,45 @@ export interface MemoryEntryHeader {
|
|
|
27
64
|
name?: string;
|
|
28
65
|
description?: string;
|
|
29
66
|
type?: string;
|
|
67
|
+
/** Last content change (ms epoch) — drives the natural-language age rendering in the derived index. */
|
|
30
68
|
mtimeMs: number;
|
|
31
69
|
rev: string;
|
|
70
|
+
/** Approximate stored size (bytes of body+frontmatter) — drives the per-scope materialization budget. */
|
|
32
71
|
sizeBytes: number;
|
|
33
72
|
}
|
|
73
|
+
/** A scored search hit (FileBackend = lexical floor; PgBackend = design/81 vector rungs, S3). */
|
|
34
74
|
export interface ScoredMemoryEntry extends MemoryEntryHeader {
|
|
75
|
+
/** Cosine-DISTANCE ∈ [0,2], 0 = identical (same contract as {@link import("../memory.js").ScoredMemory}). */
|
|
35
76
|
score: number;
|
|
36
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* design/138 §2.1 — one entry transaction. `add`/`delete` are naturally commutative; `update` carries
|
|
80
|
+
* a per-id CAS baseline (`baseRev`): when the backend's current rev differs, the patch is reported as a
|
|
81
|
+
* CONFLICT (never blind-written) and the next task re-materializes fresh state (§2.4 并发).
|
|
82
|
+
*/
|
|
37
83
|
export interface NotePatch {
|
|
38
84
|
op: "add" | "update" | "delete";
|
|
85
|
+
/** The immutable entry id this patch addresses. */
|
|
39
86
|
id: string;
|
|
87
|
+
/** The full new entry state (`add`/`update`). Absent for `delete`. */
|
|
40
88
|
entry?: MemoryEntry;
|
|
89
|
+
/** CAS baseline for `update`/`delete`: the rev this patch was computed against. Absent (a brand-new
|
|
90
|
+
* add) ⇒ no CAS. */
|
|
41
91
|
baseRev?: string;
|
|
92
|
+
/** ADD-ONLY guard (design/142 S2.5, E-02). Meaningful only on `op: "add"`:
|
|
93
|
+
* - `"absent"` ⇒ add-if-absent: if the target id already exists, the backend compares revs —
|
|
94
|
+
* same rev AND same projection (scope+slug) = idempotent apply; DIFFERENT rev, or same rev at a
|
|
95
|
+
* DIFFERENT projection (三轮复查: rev hashes id/frontmatter/body, not slug/scope — a same-content
|
|
96
|
+
* copy at another slug/scope is no no-op, "applying" it would mint a duplicate file for the id) =
|
|
97
|
+
* a REPORTED conflict (`add_guard_absent_conflict`, carrying `currentRev`), NEVER a blind
|
|
98
|
+
* overwrite or a duplicate. This is for sync's first-round pull adds, where a concurrent local
|
|
99
|
+
* create during the RTT must not be clobbered.
|
|
100
|
+
* A plain add WITHOUT this guard keeps its existing idempotent-overwrite semantics (the
|
|
101
|
+
* `same-scope re-add of an existing id is the idempotent overwrite` contract clause is unchanged).
|
|
102
|
+
* Ignored on `update`/`delete`. */
|
|
42
103
|
guard?: "absent";
|
|
43
104
|
}
|
|
105
|
+
/** Result of {@link MemoryBackend.applyPatches} — applied ops + per-id CAS conflicts (reported, not thrown). */
|
|
44
106
|
export interface PatchReport {
|
|
45
107
|
applied: Array<{
|
|
46
108
|
op: NotePatch["op"];
|
|
@@ -55,81 +117,207 @@ export interface PatchReport {
|
|
|
55
117
|
currentRev?: string;
|
|
56
118
|
}>;
|
|
57
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* design/138 §2.1 — the storage seam under the MemoryEngine. NOT a MemoryStore replacement shim: this
|
|
122
|
+
* is the S1 new-architecture surface (the legacy `MemoryStore` path is untouched and switched off it).
|
|
123
|
+
*/
|
|
58
124
|
export interface MemoryBackend {
|
|
125
|
+
/** Headers for every entry in the given scopes (manifest surface — bodies excluded). */
|
|
59
126
|
listHeaders(scopes: readonly string[]): Promise<MemoryEntryHeader[]>;
|
|
127
|
+
/** Full entries for the selected ids (unknown ids silently skipped). */
|
|
60
128
|
getByIds(ids: readonly string[]): Promise<MemoryEntry[]>;
|
|
129
|
+
/** Scored retrieval (FileBackend = lexical floor; vector rungs live in the S3 PgBackend). */
|
|
61
130
|
search(query: string, scopes: readonly string[], opts?: {
|
|
62
131
|
limit?: number;
|
|
63
132
|
}): Promise<ScoredMemoryEntry[]>;
|
|
133
|
+
/**
|
|
134
|
+
* Apply entry transactions (add/update/delete) against the backend's CURRENT state (per-id CAS).
|
|
135
|
+
*
|
|
136
|
+
* Behavior clauses a conforming implementation MUST honor (ext-dogfood F1 — each is asserted by
|
|
137
|
+
* `memoryBackendContract`, listed here so a third party doesn't have to discover them case by case):
|
|
138
|
+
* - a repeated id WITHIN one batch: first op wins, later ones conflict with reason matching
|
|
139
|
+
* /duplicate id in batch/;
|
|
140
|
+
* - `entry.id !== patch.id` (either op) is refused with reason matching /malformed patch refused/
|
|
141
|
+
* — never silently rekeyed;
|
|
142
|
+
* - an `add` whose slug is taken by a DIFFERENT id in the same scope gets a deterministic `-n`
|
|
143
|
+
* suffix (`taken` → `taken-2`); the id stays the identity anchor;
|
|
144
|
+
* - SAME-SCOPE re-`add` of an existing id is the idempotent overwrite — not a conflict. An add of
|
|
145
|
+
* an id living in ANOTHER scope is REFUSED with reason matching /cross-scope add refused/ (2026-07-12
|
|
146
|
+
* 裁定, all three backends agree — the Pg/TiDB twins always pre-checked this; File now matches).
|
|
147
|
+
* The one spelling of a cross-scope MOVE is `update` (next clause) — an add can never relocate an id;
|
|
148
|
+
* - an `add` carrying `guard: "absent"` is add-if-absent: onto a MISSING id it is a plain add;
|
|
149
|
+
* onto an EXISTING id it is idempotent when the rev AND the projection (scope+slug) match, else a
|
|
150
|
+
* REPORTED conflict with reason matching /add_guard_absent_conflict/ carrying `currentRev` —
|
|
151
|
+
* NEVER a blind overwrite, never a second file for one id (E-02 + 三轮复查投影校验);
|
|
152
|
+
* - `update` MAY move an entry across scopes; a stale `baseRev` is a REPORTED conflict, never
|
|
153
|
+
* thrown, never blind-written;
|
|
154
|
+
* - design-A I-2 洗白拒收 ([A1]): when the entry's CURRENT committed state carries
|
|
155
|
+
* `frontmatter.provenance.kind === "repo_file"`, an `update` whose new frontmatter drops
|
|
156
|
+
* `provenance`, or drops a present `trust` marker, is refused with reason matching
|
|
157
|
+
* /malformed patch refused/ (same seat as the id-mismatch clause) — repo-originated content
|
|
158
|
+
* can never be whitewashed into an unmarked (implicitly trusted) entry. A conforming update of
|
|
159
|
+
* such an entry (the ingest producer's own re-ingest) always carries both fields forward;
|
|
160
|
+
* - conflicts are per-patch and non-fatal: the rest of the batch still applies.
|
|
161
|
+
*/
|
|
64
162
|
applyPatches(patches: readonly NotePatch[]): Promise<PatchReport>;
|
|
163
|
+
/** design/84 Seam B cursor pair, migrated verbatim onto the entry-id plane (S2 rewires consolidation). */
|
|
65
164
|
getConsolidationCursor(scope: string): Promise<string | undefined>;
|
|
66
165
|
setConsolidationCursor(scope: string, cursor: string): Promise<void>;
|
|
67
166
|
}
|
|
167
|
+
/** One file the engine materialized into the session memory directory. */
|
|
68
168
|
export interface MaterializedFile {
|
|
169
|
+
/** Absolute canonical path of the projected file. */
|
|
69
170
|
path: string;
|
|
171
|
+
/** Path relative to the memory dir root (the link target used in the derived MEMORY.md index). */
|
|
70
172
|
relPath: string;
|
|
71
173
|
scope: string;
|
|
72
174
|
id: string;
|
|
73
175
|
slug: string;
|
|
176
|
+
/** Rev of the ON-DISK content at materialize time (for a stub: the stub content's rev). */
|
|
74
177
|
rev: string;
|
|
178
|
+
/** True when this file is a budget stub (frontmatter+description only, body archived — §2.3). */
|
|
75
179
|
stub: boolean;
|
|
180
|
+
/** True when the file belongs to a read-only inherited layer (chmod-protected, never harvested as a write). */
|
|
76
181
|
readonly: boolean;
|
|
77
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* design/138 §2.2 — the session handle `materialize` returns and `harvest`/`rebaseline` consume.
|
|
185
|
+
* `materialized` IS the harvest diff domain (plus session-new files under `writableRoot`): an entry
|
|
186
|
+
* that was never materialized can never be deleted by its absence (镜头 G).
|
|
187
|
+
*/
|
|
78
188
|
export interface MemorySessionHandle {
|
|
189
|
+
/** The memory directory root. PURE CONFIG (§2.7 r2.1): a project scope may live IN-REPO
|
|
190
|
+
* (git-tracked `memory/`), a user/personal scope OUTSIDE — the engine never asserts either.
|
|
191
|
+
* TODO(S1b): per-scope PHYSICAL roots (project scope in-repo + user scope in the home mount in ONE
|
|
192
|
+
* session) — `fileToScope` already keys absolute paths, so only the layout mapping needs the split. */
|
|
79
193
|
memoryDir: string;
|
|
194
|
+
/** The single directory the model may write memory into (the writeScope's home). Equals `memoryDir`
|
|
195
|
+
* when the writeScope owns the root (the standard TOC layout). */
|
|
80
196
|
writableRoot: string;
|
|
81
197
|
writeScope: string | null;
|
|
82
198
|
scopes: string[];
|
|
199
|
+
/** The materialized manifest = the harvest diff domain. */
|
|
83
200
|
materialized: MaterializedFile[];
|
|
201
|
+
/** Absolute file path → owning scope. */
|
|
84
202
|
fileToScope: Map<string, string>;
|
|
203
|
+
/** Absolute file path → materialize-time rev (the per-id CAS baseline harvest sends with updates). */
|
|
85
204
|
baseRevs: Map<string, string>;
|
|
205
|
+
/** Absolute file path → entry id at materialize time (rename/id-restore bookkeeping). */
|
|
86
206
|
baseIds: Map<string, string>;
|
|
207
|
+
/** design-A C-6 ([A3]) — ingest 条目不投影: entry id → repo-relative `provenance.path` for the
|
|
208
|
+
* repo-ingested entries (`frontmatter.provenance.kind === "repo_file"`) materialize did NOT
|
|
209
|
+
* project into the writable memory dir (copy-out mode only — the true body lives in the repo;
|
|
210
|
+
* a projection would be a duplicate the model can edit into a forgery, I-3). The derived-index
|
|
211
|
+
* rebuild links these entries to the recorded repo path instead of a projection file. Absent /
|
|
212
|
+
* empty when the session has no such entries (projection behavior byte-identical, pinned). */
|
|
87
213
|
repoIndexTargets?: Map<string, string>;
|
|
214
|
+
/** Lines of the derived MEMORY.md at materialize time (the index-cleared fuse baseline). */
|
|
88
215
|
indexBaselineLines: number;
|
|
216
|
+
/** 评审 M6 — the derived index TEXT as of materialize. `inject` reads THIS when no on-disk
|
|
217
|
+
* MEMORY.md exists (a read-only layering never writes one), so first-session read-only injection
|
|
218
|
+
* works without a disk round-trip. */
|
|
89
219
|
indexText: string;
|
|
220
|
+
/** Set when the index gate fired AND its containment did not complete — the on-disk MEMORY.md
|
|
221
|
+
* still holds the rejected bytes (a clear can be refused: a non-file index path, an unwritable
|
|
222
|
+
* one). `inject` then reads {@link indexText} instead of the live file, and offers no index seed:
|
|
223
|
+
* the gate's whole purpose is keeping those bytes out of the prompt, so a refused clear must not
|
|
224
|
+
* leave the injection path reading them anyway. Absent ⇒ the normal "live file wins" behavior. */
|
|
225
|
+
indexOnDiskUntrusted?: boolean;
|
|
90
226
|
}
|
|
227
|
+
/** Stable rejection codes a harvest gate can produce (model-visible gate events — 镜头 I). */
|
|
91
228
|
export type HarvestRejectionCode = "outside_root" | "symlink" | "secret" | "injection" | "filename" | "too_large" | "file_cap" | "readonly_layer" | "stub_modified" | "nested_too_deep" | "quarantine_failed" | "unreadable" | "polluted" | "invalid";
|
|
229
|
+
/** One rejected file: path (relative to the memory dir), stable code, and a model-readable reason. */
|
|
92
230
|
export interface HarvestRejection {
|
|
93
231
|
path: string;
|
|
94
232
|
code: HarvestRejectionCode;
|
|
95
233
|
reason: string;
|
|
96
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* design/138 S2-C — one finding from the shared write-time/harvest scan rule set
|
|
237
|
+
* (`scan.ts` `scanMemoryWrite`/`scanMemoryFileName`; ONE rule set, TWO mount points).
|
|
238
|
+
*/
|
|
97
239
|
export interface ScanFinding {
|
|
240
|
+
/** The subset of {@link HarvestRejectionCode} the scan can produce. */
|
|
98
241
|
code: "secret" | "injection" | "filename" | "too_large";
|
|
242
|
+
/** Engine-composed, model-readable reason fragment (for `secret`: the pattern LABEL, never the value). */
|
|
99
243
|
reason: string;
|
|
100
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* design/138 S2-B — one queued memory-change announcement, drained into the NEXT session's first
|
|
247
|
+
* injection (时机① only; there is no in-run delivery lane — O-F2/C-F4 裁撤). Queued via the
|
|
248
|
+
* journaled control-plane queue ({@link import("./layout.js").enqueueMemoryAnnouncement}) so
|
|
249
|
+
* concurrent writers never overwrite each other (O-F6/C-F5).
|
|
250
|
+
*/
|
|
101
251
|
export interface MemoryAnnouncement {
|
|
252
|
+
/** `gate` = engine gate/harvest events (rejections, quarantine, incidents, restores, conflicts,
|
|
253
|
+
* degradation, applied-patch summary); `external` = out-of-session changes the backend's read-side
|
|
254
|
+
* detected (disk rev ≠ ledger: adopted external edits + inbound-gate rejects). */
|
|
102
255
|
kind: "gate" | "external";
|
|
256
|
+
/** ms epoch at enqueue. */
|
|
103
257
|
at: number;
|
|
258
|
+
/** Optional producing-session id (repo-level event stream — Q-G: no worktree attribution in S2). */
|
|
104
259
|
sessionId?: string;
|
|
260
|
+
/** Engine-composed single-line items. O-F1/C-F8: every model/collaborator-controllable identifier
|
|
261
|
+
* (path/slug/name/description) is neutralized (inlineUntrusted) AND JSON-quoted at ENQUEUE time —
|
|
262
|
+
* the stored strings are already render-safe; the render step only adds the trusted lead/frame. */
|
|
105
263
|
items: string[];
|
|
106
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* design/138 §2.4 — the harvest outcome. Rejections are MODEL-VISIBLE gate events: S1 delivers the
|
|
267
|
+
* structure; the runner's boundary-announcement wiring (attachments member) lands in S2 (TODO(S2)).
|
|
268
|
+
*/
|
|
107
269
|
export interface HarvestReport {
|
|
270
|
+
/** False ⇔ the whole harvest was refused (deletion fuse / missing dir / corrupt sidecar incident). */
|
|
108
271
|
ok: boolean;
|
|
272
|
+
/** Set when a fuse tripped (§2.4 删除防线 / B3 fail-closed): the harvest is refused wholesale, NO
|
|
273
|
+
* patches (especially no deletes) are produced, and the report is surfaced as an alert. */
|
|
109
274
|
incident?: {
|
|
110
275
|
kind: "mass_deletion" | "index_cleared" | "dir_missing" | "sidecar_corrupt";
|
|
111
276
|
detail: string;
|
|
112
277
|
};
|
|
278
|
+
/** Patch counts actually APPLIED by the backend. */
|
|
113
279
|
patches: {
|
|
114
280
|
add: number;
|
|
115
281
|
update: number;
|
|
116
282
|
delete: number;
|
|
117
283
|
};
|
|
284
|
+
/** Per-id CAS conflicts from the backend (reported, never blind-written). */
|
|
118
285
|
conflicts: PatchReport["conflicts"];
|
|
119
286
|
rejections: HarvestRejection[];
|
|
287
|
+
/** Non-`.md` / non-structural files found in the diff domain — listed, never persisted (they stay
|
|
288
|
+
* on disk: they may be the model's working files). Files REMOVED from the model-visible plane go
|
|
289
|
+
* in {@link movedToQuarantine}. */
|
|
120
290
|
quarantined: string[];
|
|
291
|
+
/** Gate-rejected files physically MOVED into the control plane's `quarantine/` (out of the scan
|
|
292
|
+
* domain and off the model-visible disk — B2/验收 L4: secret-bearing files never linger). */
|
|
121
293
|
movedToQuarantine: string[];
|
|
294
|
+
/** C-F9 (S2-0) — quarantine escalations: any deviation from the clean capture+remove path is
|
|
295
|
+
* REPORT-VISIBLE here (never a debug-only downgrade). `contained` = the suspect content no longer
|
|
296
|
+
* sits raw on the model-visible plane (deleted / cleared in place / overwritten with the committed
|
|
297
|
+
* copy); `contained: false` is the worst case — residue remains and a human/runner must act. */
|
|
122
298
|
quarantineFailures?: Array<{
|
|
123
299
|
path: string;
|
|
124
300
|
contained: boolean;
|
|
125
301
|
detail: string;
|
|
126
302
|
}>;
|
|
303
|
+
/** Materialized files absent at harvest. NOT deletes (§2.4: 文件缺失≠删除). Files whose entry id
|
|
304
|
+
* re-appears at another path (a RENAME) are NOT counted here (验收 M1 — a rename is an id-keyed
|
|
305
|
+
* update, never a missing file, and never feeds the deletion fuse). */
|
|
127
306
|
missing: string[];
|
|
307
|
+
/** B1 committed-shadow recovery: missing (non-tombstoned) files RESTORED onto disk from the
|
|
308
|
+
* committed copy (backend/shadow). Disclosed here (the restore is an engine action, never silent).
|
|
309
|
+
* Restored paths also appear in {@link missing} (the honest record of what vanished). */
|
|
128
310
|
restored: string[];
|
|
311
|
+
/** Index self-heal notes (L8): suspected-duplicate index lines kept-with-warning, cleared orphans. */
|
|
129
312
|
warnings: string[];
|
|
313
|
+
/** M7 harvest budget: set when the deadline/file budget cut the harvest short. `pending` files were
|
|
314
|
+
* NOT processed this round (no patches, still on disk) — the next boundary harvest picks them up. */
|
|
130
315
|
degraded?: {
|
|
131
316
|
reason: "deadline" | "file_budget";
|
|
132
317
|
pending: string[];
|
|
133
318
|
};
|
|
319
|
+
/** B2 §2.7 r2.1 inbound gate: findings from scanning changes that did NOT originate in this session
|
|
320
|
+
* (e.g. a git-pull-borne edit of an in-repo memory dir — a write channel that bypasses the harvest
|
|
321
|
+
* gate). Populated by the backend's read-side sync gate and drained into the report at harvest. */
|
|
134
322
|
inboundFindings?: HarvestRejection[];
|
|
135
323
|
}
|
|
@@ -1,14 +1,70 @@
|
|
|
1
1
|
import type { MemoryNoteHeader, MemoryNoteRecord, MemoryStore } from "./memory.js";
|
|
2
|
+
/**
|
|
3
|
+
* Selective memory recall (design/65 §2.2 — port of CC `findRelevantMemories`). For a LARGE memory scope,
|
|
4
|
+
* instead of injecting the whole `<user_memory>` block (inject-all), we inject a compact **manifest** (one
|
|
5
|
+
* header line per note) + a side-query that picks the ≤K relevant note ids + only those bodies. Small
|
|
6
|
+
* scopes keep inject-all (the common case after consolidation) — this path is threshold-gated, so most
|
|
7
|
+
* tasks pay nothing.
|
|
8
|
+
*
|
|
9
|
+
* ⚠️ WHAT IS ACTUALLY IN THIS FILE (RB-446, corrected 2026-07-31 — the text below used to describe a
|
|
10
|
+
* DRIVER that no longer exists here, in the present tense). The 2.0.0 B19 export sweep removed the
|
|
11
|
+
* function that ran the pipeline; what remains, and what the rest of core consumes, is the set of PURE
|
|
12
|
+
* HELPERS plus the declared shape of that pipeline:
|
|
13
|
+
* · helpers, all live and in use: {@link formatMemoryAge}, {@link RECALL_CAVEAT},
|
|
14
|
+
* {@link buildManifestText}, {@link validateSelectedIds}, {@link resolveLinkedIds},
|
|
15
|
+
* {@link composeSelectiveBody}, {@link encodeSurfacedKey};
|
|
16
|
+
* · seam DECLARATIONS with no in-tree caller: {@link MemorySelector} /
|
|
17
|
+
* {@link SelectiveRecallOptions} / {@link SelectiveRecallResult} / {@link LayeredRecallOptions} /
|
|
18
|
+
* {@link LayeredRecallResult}. They stay exported because they are the published contract a
|
|
19
|
+
* deployment implements its own driver against — the helpers above are exactly the pieces such a
|
|
20
|
+
* driver assembles — but nothing under `src/` calls them today. Read them as a specification, not
|
|
21
|
+
* as a description of code that runs.
|
|
22
|
+
*
|
|
23
|
+
* The pipeline those declarations specify: pure + deterministic given a selector — validate the returned
|
|
24
|
+
* ids against the manifest (reject hallucinated ids, council #5), cap at K, apply a hard timeout
|
|
25
|
+
* (council #12), and on ANY selector failure/timeout DEGRADE to inject-all (council #4 — never silently
|
|
26
|
+
* drop knowledge). Output goes in the variable tail (manifest + selected bodies are per-user/volatile,
|
|
27
|
+
* like the current memory block). `validateSelectedIds` is the one rung of it that IS implemented here.
|
|
28
|
+
*/
|
|
29
|
+
/** Default max notes the side-query may select (CC `findRelevantMemories` ≤5). */
|
|
2
30
|
export declare const DEFAULT_MAX_SELECTED = 5;
|
|
31
|
+
/** Default max 1-hop link-followed notes appended after the selected ones (design/65 P3). */
|
|
3
32
|
export declare const DEFAULT_MAX_LINKED = 3;
|
|
33
|
+
/** Default side-query hard timeout (ms) — council #12; on timeout we degrade to inject-all. */
|
|
4
34
|
export declare const DEFAULT_SELECT_TIMEOUT_MS = 5000;
|
|
35
|
+
/**
|
|
36
|
+
* Render a memory note's age as a natural-language phrase (CC-parity P0-1, design/65). CC's eval found
|
|
37
|
+
* models reason about memory age much better from natural language ("3 days ago") than from a boolean
|
|
38
|
+
* "older note" flag (verify-claims 0/2 → 3/3 once the age was spelled out), because the model can weigh
|
|
39
|
+
* staleness proportionally instead of as a single cliff. This is the relative phrase only; the
|
|
40
|
+
* point-in-time / verify-before-trust discipline still lives in {@link RECALL_CAVEAT} + the per-note
|
|
41
|
+
* "verify it's still current" hint (the age is ADDITIONAL signal, not a replacement).
|
|
42
|
+
*
|
|
43
|
+
* Buckets (each chooses the coarsest unit that's ≥1): `today` (<1 day, incl. future mtime / clock skew →
|
|
44
|
+
* clamped to today, never a negative age), `yesterday` (1–2 days), `N days ago` (2–7 days),
|
|
45
|
+
* `N weeks ago` (1 week – ~1 month), `N months ago` (≥ ~1 month). N is floored to the whole unit.
|
|
46
|
+
*/
|
|
5
47
|
export declare function formatMemoryAge(ageMs: number): string;
|
|
48
|
+
/**
|
|
49
|
+
* Read-side recall caveat (design/65 §8#2 / §9#1 — ported from CC's MEMORY_DRIFT_CAVEAT +
|
|
50
|
+
* TRUSTING_RECALL_SECTION). The council found CC's two-section form is **eval-validated** (verify-claims
|
|
51
|
+
* 0/2→3/3) and that the structure carries the effect: the precise decision-point heading
|
|
52
|
+
* "## Before recommending from memory" scored 3/3 while an abstract heading or a buried bullet scored 0/3.
|
|
53
|
+
* So this is deliberately TWO sections — a drift bullet + a titled action section with the frame-shift
|
|
54
|
+
* sentence and concrete verify actions — NOT one merged paragraph (same semantics, 3× worse eval).
|
|
55
|
+
* MEMORY_SAFETY already carries the authority hierarchy; this adds the point-in-time / verify-before-trust
|
|
56
|
+
* discipline selective recall specifically needs.
|
|
57
|
+
*/
|
|
6
58
|
export declare const RECALL_CAVEAT: string;
|
|
7
59
|
export interface MemorySelectRequest {
|
|
60
|
+
/** The task objective the recall is for. */
|
|
8
61
|
objective: string;
|
|
62
|
+
/** The manifest the selector chooses from (id + description [+ type]). */
|
|
9
63
|
manifest: MemoryNoteHeader[];
|
|
64
|
+
/** Tools the task will use — for these, keep gotchas/warnings, skip pure usage notes (design/65 §2.2). */
|
|
10
65
|
recentTools?: string[];
|
|
11
66
|
}
|
|
67
|
+
/** The side-query seam: pick the relevant note ids from the manifest. MUST be fail-fast (throw → degrade). */
|
|
12
68
|
export type MemorySelector = (req: MemorySelectRequest, signal?: AbortSignal) => Promise<string[]>;
|
|
13
69
|
export interface SelectiveRecallOptions {
|
|
14
70
|
store: MemoryStore;
|
|
@@ -16,13 +72,54 @@ export interface SelectiveRecallOptions {
|
|
|
16
72
|
objective: string;
|
|
17
73
|
selector: MemorySelector;
|
|
18
74
|
recentTools?: string[];
|
|
75
|
+
/** Absolute time for the freshness caveat (default Date.now()). */
|
|
19
76
|
nowMs?: number;
|
|
20
77
|
maxSelected?: number;
|
|
78
|
+
/** Max 1-hop `[[name]]` link-followed notes appended after the selected ones (design/65 P3).
|
|
79
|
+
* `0` disables link-following. Default {@link DEFAULT_MAX_LINKED}. */
|
|
21
80
|
maxLinked?: number;
|
|
22
81
|
timeoutMs?: number;
|
|
23
82
|
signal?: AbortSignal;
|
|
83
|
+
/**
|
|
84
|
+
* CC-parity P1 (durable cross-worker recall de-dup). Note ids ALREADY surfaced to this logical
|
|
85
|
+
* conversation in earlier turns/runs (CC's in-process `alreadySurfaced`/readFileState filter, lifted
|
|
86
|
+
* to a **durable, caller-owned** set so it survives task hops, resume, and multi-worker fan-out). When
|
|
87
|
+
* provided, these ids are **filtered out of the manifest BEFORE the selector sees it** — the selector
|
|
88
|
+
* never sees an already-shown note, so it cannot re-select it, so a long/resumed/multi-worker session
|
|
89
|
+
* does not re-inject the same bodies. core does NOT store this set (like {@link CheckpointStore}, the
|
|
90
|
+
* durable store is the caller's): the caller persists {@link surfacedIds} from one call and feeds it
|
|
91
|
+
* back here as `priorSurfacedIds` on the next. Omitted ⇒ no filtering (the prior, non-de-duped behavior).
|
|
92
|
+
*/
|
|
24
93
|
priorSurfacedIds?: ReadonlySet<string>;
|
|
25
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Result of a single-scope selective-recall pass. `surfacedIds` (CC-parity P1) is the set of note ids whose
|
|
97
|
+
* BODIES this call injected into the prompt — the caller appends them to its durable surfaced-set and
|
|
98
|
+
* feeds that back as {@link SelectiveRecallOptions.priorSurfacedIds} next time, so a long/resumed/
|
|
99
|
+
* multi-worker session does not re-inject the same notes. THREE shapes (all carry `surfacedIds`):
|
|
100
|
+
*
|
|
101
|
+
* - **block branch** (`{ block: string }`): a selective-recall block was rendered. `surfacedIds` = the
|
|
102
|
+
* validated selection + the 1-hop linked notes (everything whose body was rendered). The caller injects
|
|
103
|
+
* `block` verbatim.
|
|
104
|
+
*
|
|
105
|
+
* - **no-new branch** (`{ block: undefined }`): a SUCCESS, NOT a degrade. Every selectable candidate was
|
|
106
|
+
* already surfaced earlier (filtered out by {@link SelectiveRecallOptions.priorSurfacedIds}), so there is
|
|
107
|
+
* NOTHING NEW to inject. The caller injects NOTHING (no block) — it must NOT fall back to inject-all,
|
|
108
|
+
* because inject-all would re-dump the WHOLE scope including the already-shown notes, defeating the
|
|
109
|
+
* de-dup. `surfacedIds` is `[]` (this call added no new note to the durable set; the prior ids are
|
|
110
|
+
* already in the caller's store). Distinguished from `degrade` precisely so the caller does not
|
|
111
|
+
* re-inject (the bug this branch fixes). `"block" in result` is TRUE here (the key is present, value
|
|
112
|
+
* `undefined`), so the caller's `"degrade" in result` narrow routes this to the non-degrade path.
|
|
113
|
+
*
|
|
114
|
+
* - **degrade branch** (`{ degrade: true }`): a true FALLBACK — the store can't do selective recall
|
|
115
|
+
* (missing manifest/getByIds), the scope is empty, OR the selector failed/timed out. The caller falls
|
|
116
|
+
* back to inject-all (never drops knowledge, council #4), a best-effort FULL DUMP that
|
|
117
|
+
* `composeMemoryBlock` hard-truncates to a head slice (so it does NOT reliably render every body), and
|
|
118
|
+
* the caller already holds the prior surfaced ids. Degrade is therefore not a precise per-id surface that
|
|
119
|
+
* can be de-duped: `surfacedIds` is ALWAYS `[]` and degrade does **not** advance the durable surfaced-set.
|
|
120
|
+
* (Reporting the full header id list here would over-claim the truncated tail as surfaced → permanent
|
|
121
|
+
* silent under-recall on the next turn.)
|
|
122
|
+
*/
|
|
26
123
|
export type SelectiveRecallResult = {
|
|
27
124
|
block: string;
|
|
28
125
|
surfacedIds: string[];
|
|
@@ -34,18 +131,57 @@ export type SelectiveRecallResult = {
|
|
|
34
131
|
surfacedIds: string[];
|
|
35
132
|
};
|
|
36
133
|
export declare function resolveLinkedIds(headers: MemoryNoteHeader[], selected: MemoryNoteRecord[], max: number): string[];
|
|
134
|
+
/** Render the manifest as compact lines, double-capped (council #7). One line per note, guaranteed. */
|
|
37
135
|
export declare function buildManifestText(headers: MemoryNoteHeader[]): string;
|
|
136
|
+
/** Keep only ids present in the manifest (reject hallucinated, council #5), de-duped, capped at `max`. */
|
|
38
137
|
export declare function validateSelectedIds(headers: MemoryNoteHeader[], ids: string[], max: number): string[];
|
|
138
|
+
/**
|
|
139
|
+
* Render the BODY of a selective-recall block: the optional `recall` manifest index + the selected note
|
|
140
|
+
* bodies (+ 1-hop linked notes), WITHOUT the outer `<user_memory>` wrapper and WITHOUT {@link RECALL_CAVEAT}.
|
|
141
|
+
* The wrapper + caveat are the caller's job — a single-scope caller places ONE caveat
|
|
142
|
+
* inside ONE `<user_memory scope=… mode="selective">`, and the layered renderer places ONE caveat inside ONE
|
|
143
|
+
* `<user_memory mode="selective">` ahead of N `<scope>` subsections (MAJOR fix: no nested fences, no per-scope
|
|
144
|
+
* caveat duplication).
|
|
145
|
+
*
|
|
146
|
+
* `recallable` controls the "Memory index — load in full …" affordance (MAJOR fix): the on-demand recall
|
|
147
|
+
* tool is bound to a SINGLE scope, so the "load in full" instruction is only TRUE for that scope. Pass
|
|
148
|
+
* `false` for non-recallable layers — the selected bodies are already rendered inline, so the index is just a
|
|
149
|
+
* false affordance that wastes a tool call (model searches the wrong scope → "No memory matches").
|
|
150
|
+
*
|
|
151
|
+
* `recallToolName` (#181-F1, additive) is the WIRE name of the host-mounted recall tool the affordance
|
|
152
|
+
* teaches. Core mounts no such tool ("Recall" is a RETIRED name — tool-name-aliases.ts), so a hard-coded
|
|
153
|
+
* name here can only ever be stale; the host that mounted the tool passes the name it mounted it under.
|
|
154
|
+
* Omitted ⇒ a name-free "search the memory-recall tool" wording (honest without inventing a name).
|
|
155
|
+
*
|
|
156
|
+
* Notes are tagged with their natural-language age (CC-parity P0-1, design/65; >1-day-old ones keep the
|
|
157
|
+
* "verify it's still current" hint, council #8). `linked` (design/65 P3) are 1-hop `[[name]]`-followed notes,
|
|
158
|
+
* rendered in their own clearly-labeled subsection AFTER the selected ones — expanded as DATA under the same
|
|
159
|
+
* fence/sanitize/byte-cap discipline (design/65 §8#9: a followed link must not become markup or escalate authority).
|
|
160
|
+
*/
|
|
39
161
|
export declare function composeSelectiveBody(manifestText: string, selected: MemoryNoteRecord[], nowMs: number, linked?: MemoryNoteRecord[], recallable?: boolean, recallToolName?: string): string;
|
|
162
|
+
/** A `(scope, id)` composite key for the multi-scope durable de-dup (design/84 Seam A decision 5). Note ids
|
|
163
|
+
* are only unique WITHIN a scope, so the cross-scope `priorSurfacedKeys`/`surfacedKeys` set MUST be keyed on
|
|
164
|
+
* both. Core owns the FORMAT so a caller can't drift the wire format (decision 7) — the encoding is OPAQUE
|
|
165
|
+
* and length-prefixes the scope so a scope/id containing the separator cannot forge a collision.
|
|
166
|
+
*
|
|
167
|
+
* ONE-WAY by design (codex MINOR (d)): the key is only ever PRODUCED here (`surfacedKeys`) and compared by
|
|
168
|
+
* STRING EQUALITY against the caller's persisted set ({@link LayeredRecallOptions.priorSurfacedKeys}, applied
|
|
169
|
+
* at memory-recall.ts via `priorSurfacedKeys.has(encodeSurfacedKey(h.scope, h.id))`). Nothing ever needs the
|
|
170
|
+
* `(scope, id)` BACK out of a key, so there is intentionally NO `decodeSurfacedKey` — adding a decode would
|
|
171
|
+
* widen the public surface (and invite callers to parse the opaque format) for zero consumer. Treat the key
|
|
172
|
+
* as an opaque token: persist it, feed it back, compare for equality — never split it. */
|
|
40
173
|
export declare function encodeSurfacedKey(scope: string, id: string): string;
|
|
174
|
+
/** A manifest header tagged with the scope it came from (design/84 Seam A decision 5). */
|
|
41
175
|
export interface ScopedNoteHeader extends MemoryNoteHeader {
|
|
42
176
|
scope: string;
|
|
43
177
|
}
|
|
178
|
+
/** A full record tagged with its scope (for cross-scope getByIds). */
|
|
44
179
|
export interface ScopedNoteRecord extends MemoryNoteRecord {
|
|
45
180
|
scope: string;
|
|
46
181
|
}
|
|
47
182
|
export interface LayeredRecallOptions {
|
|
48
183
|
store: MemoryStore;
|
|
184
|
+
/** Ordered scopes (design/84 Seam A): list order = priority; the last is highest. */
|
|
49
185
|
scopes: ReadonlyArray<string>;
|
|
50
186
|
objective: string;
|
|
51
187
|
selector: MemorySelector;
|
|
@@ -55,8 +191,13 @@ export interface LayeredRecallOptions {
|
|
|
55
191
|
maxLinked?: number;
|
|
56
192
|
timeoutMs?: number;
|
|
57
193
|
signal?: AbortSignal;
|
|
194
|
+
/** CC-parity P1, multi-scope: `(scope,id)` composite keys ({@link encodeSurfacedKey}) already surfaced to
|
|
195
|
+
* this logical conversation. Filtered out of the merged manifest BEFORE the selector sees it. */
|
|
58
196
|
priorSurfacedKeys?: ReadonlySet<string>;
|
|
59
197
|
}
|
|
198
|
+
/** Result of a multi-scope (layered) selective-recall pass. `surfacedKeys` are `(scope,id)` composite keys
|
|
199
|
+
* ({@link encodeSurfacedKey}) — the caller appends them to its durable set and feeds them back as
|
|
200
|
+
* {@link LayeredRecallOptions.priorSurfacedKeys}. Mirrors {@link SelectiveRecallResult}'s three shapes. */
|
|
60
201
|
export type LayeredRecallResult = {
|
|
61
202
|
block: string;
|
|
62
203
|
surfacedKeys: string[];
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/81 Slice 5 — the shared distance primitives for the consolidation `searchScored` retrieval, extracted
|
|
3
|
+
* BYTE-IDENTICAL from the original PgMemoryStore implementation so the File (portable/TOC) and Pg (native/TOB)
|
|
4
|
+
* backends rank on ONE source of truth and can't drift. The `{@link import("./runner/memory-consolidation.js")}`
|
|
5
|
+
* band `{0.05, 0.3}` is defined on this cosine-distance scale; the lexical `1 - Jaccard ∈ [0,1] ⊂ [0,2]` is the
|
|
6
|
+
* same-zero-point stand-in used when no embedding vector is present (fail-open per row).
|
|
7
|
+
*
|
|
8
|
+
* The capability LADDER a store reports via {@link import("./memory.js").MemoryStore.vectorMode}:
|
|
9
|
+
* - `lexical` — no embedder: `1 - Jaccard(terms)` everywhere.
|
|
10
|
+
* - `portable` — embedder + IN-PROCESS cosine over stored vectors (File jsonl / Pg jsonb / MySQL JSON — ANY
|
|
11
|
+
* backend that can store a float array; O(n) over the scope, no index).
|
|
12
|
+
* - `native` — embedder + a backend index/operator (pgvector `<=>` / TiDB `VEC_COSINE_DISTANCE`).
|
|
13
|
+
* MySQL is NOT "can't support vectors" — it is `portable`-capable (JSON column + in-process cosine), just not
|
|
14
|
+
* `native`. A deployment injects an embedder (config-driven); the store then reports the achieved rung.
|
|
15
|
+
*/
|
|
16
|
+
/** Lower-cased alphanumeric term set of a string (for the lexical stand-in distance). */
|
|
1
17
|
export declare function termSet(s: string): Set<string>;
|
|
18
|
+
/** Lexical stand-in distance: `1 - Jaccard(terms)` ∈ [0,1] ⊂ [0,2]; `null` = no overlap (not a candidate). */
|
|
2
19
|
export declare function jaccardDistance(query: Set<string>, text: string): number | null;
|
|
20
|
+
/** Cosine distance ∈ [0,2] (0 = identical), the {@link import("./memory.js").ScoredMemory} contract. Uses
|
|
21
|
+
* `Math.min(a.length,b.length)` — a store MUST only call this on dimension-matched vectors (the row-level
|
|
22
|
+
* dimension guard lives at the caller; a mismatch falls open to {@link jaccardDistance}). */
|
|
3
23
|
export declare function cosineDistance(a: number[], b: number[]): number;
|