UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

190 lines (189 loc) • 8.17 kB
{ "repo": "core", "version": "7.31.1", "from": "289b2d1998a3e890f6a8659ffc4397074ddd720a", "to": "v7.31.1", "added": [], "removed": [], "changed": [], "narrowed": [ { "id": "F1", "source": "behaviorFlips.summary", "text": "NARROWING (#1094, memory store; +1 error code `memory.target_outside_store`, registered in `NON_GOVERNANCE_MEMORY_CODES`; +0 exports, +0 wire keys): an act at a memory store path is judged by where it LANDS, not by how it is spelled. One verdict — the target's DIRECTORY, resolved through every link on its existing prefix, must be the store root's physical form or inside it (the final component is not judged: the backend's `rm` removes a link standing there and `rename` replaces it, the engine's in-place writes refuse it with `ELOOP` — none follows it) — gates `FileMemoryEngineBackend.applyPatches` (per op at staging, the whole batch at the commit point, per op at each act), erasure (`MemoryEngine.eraseMemoryEntries`: commit point and act), journal replay (the whole journal before its first act, each op again at its act), and the engine's own writes at store paths: the copy-out projection, the harvest's missing-file restore, the read-only layer restore and the `MEMORY.md` index writes. The backend takes its root's physical form when it opens the store and re-checks it at the head of every face; the engine takes its memory dir's physical form at its first mount and a later mount that resolves elsewhere is refused. Separately, the engine's in-place write refuses a file with more than one name (a hard link), before anything is truncated. A refused `applyPatches` / erasure throws a plain `Error` whose `.code` is the new code — before the commit marker nothing is written and no journal is left, after it the journal is kept and replays once the path resolves inside again; a refused mount throws the code; a refused restore or index write is not performed and is reported on `HarvestReport.warnings` (or `incident.detail`) with the code, a hard-link refusal names the file. WHO IS HURT: a deployment whose store holds a directory link under its root, or a hard-linked memory file — the act that used to follow it is refused until it is removed. Known limits KL-1094-a … i." }, { "id": "F2", "source": "behaviorFlips.summary", "text": "NARROWING (#1099, spawned-environment scrub; `SecretEnvFindingKind` +1 member `namespace-rule`, confidence `medium`; +0 exports, +0 wire keys): inside the host shell's `SEMA_` namespace, and only there, a credential word as ANY `_`-separated segment makes the name a credential (`SEMA_NAMESPACE_SECRET_RE`, over the one `CREDENTIAL_WORD` alternation the suffix rule reads, the count-word reading of `TOKENS` included) — so `SEMA_MODEL_KEY_<ENTRY>`, `SEMA_WEBSEARCH_KEY_<PROVIDER>` and `SEMA_REGISTRY_TOKEN_FILE` no longer reach a tool's child shell or a language server, and the one `config.secret_env_scrubbed` notice lists them in `detail.names`. The rule is consulted after the two exact-name lists and the suffix rule, so no existing finding changes kind, and every name outside `SEMA_` keeps its v7.31.0 verdict and kind. WHO IS HURT: a `SEMA_` name with a credential-word segment that a child needed (`SEMA_REGISTRY_TOKEN_FILE`, `SEMA_LLM_KEY_DB`, six `SEMA_CODE_*` knobs a nested `sema` reads); an `inheritEnv` allowlist, `shellEnv` / a per-exec env and a host-supplied LSP `env` still pass a name verbatim." }, { "id": "F3", "source": "behaviorFlips.summary", "text": "NARROWING (#1100, shell read boundary; tightening only — no verdict loosens against 7.31.0; +0 exports, +0 wire keys; supersedes #1004's no-opener ruling for tilde values): three rules on one mechanism, the declared-home deny floor. (1) The opener condition leaves the assignment-value reading: an environment value with a leading tilde is placed against the declared home whether or not a program opens it, so `F=~/<deny row>; cat \"$F\"` meets the deny judge exactly as its `$HOME` and literal spellings already did. (2) A LITERAL tilde (quoted, escaped, after an option's `=`) — a relative `./~…` path to bash, but a program such as npm expands it itself — also carries its declared-home spelling as a deny-only view: refused on a deny row, never a containment question. (3) Each member of a `:` list meets the deny rows (a tilde member placed against the home); the whole value is still no containment candidate. Where no deny row is hit nothing changes. WHO IS HURT: a text whose value or literal-tilde operand names a deny row under the declared home and is never read that way is refused, as its `$HOME` and literal spellings already were (KL-1100a / KL-1100b)." } ], "closedSetMembers": [ { "set": "SecretEnvFindingKind", "at": [ "src/core/secret-env.ts:181" ], "newSet": false, "added": [ "namespace-rule" ], "removed": [], "breaking": false, "criteriaCovered": false } ], "closedSetsUnreadable": [], "typeKeys": [], "typeKeysUnreadableArms": [], "typeKeysFlattenedCount": 216, "declarationMoves": [], "mintMoves": [], "criteriaObserves": [ { "kind": "engineNoticeCode", "name": "config.secret_env_scrubbed", "assertions": [ "G2.a" ] }, { "kind": "typeMember", "name": "AskRequest.mandated", "assertions": [ "G3.a", "G3.b" ] }, { "kind": "typeMember", "name": "EngineNotice.detail", "assertions": [ "G2.a" ] }, { "kind": "typeMember", "name": "FileMemoryEngineBackend.applyPatches", "assertions": [ "G1.a" ] }, { "kind": "typeMember", "name": "HarvestReport.incident", "assertions": [ "G1.a" ] }, { "kind": "typeMember", "name": "HarvestReport.ok", "assertions": [ "G1.b" ] }, { "kind": "typeMember", "name": "HarvestReport.restored", "assertions": [ "G1.a", "G1.b" ] }, { "kind": "typeMember", "name": "HarvestReport.warnings", "assertions": [ "G1.a" ] }, { "kind": "typeMember", "name": "MemoryEngine.eraseMemoryEntries", "assertions": [ "G1.a" ] }, { "kind": "typeMember", "name": "MemoryEngine.materialize", "assertions": [ "G1.a" ] }, { "kind": "typeMember", "name": "MemoryErasureAttestation.status", "assertions": [ "G1.b" ] }, { "kind": "typeMember", "name": "PatchReport.applied", "assertions": [ "G1.b" ] }, { "kind": "typeMember", "name": "SecretEnvFinding.confidence", "assertions": [ "G2.a" ] }, { "kind": "typeMember", "name": "SecretEnvFinding.key", "assertions": [ "G2.b" ] }, { "kind": "typeMember", "name": "SecretEnvFinding.kind", "assertions": [ "G2.a", "G2.b" ] }, { "kind": "typeMember", "name": "ShellReadVerdict.disposition", "assertions": [ "G3.a", "G3.b" ] }, { "kind": "typeMember", "name": "ShellReadVerdict.finding", "assertions": [ "G3.a", "G3.b" ] }, { "kind": "typeMember", "name": "ShellReadVerdict.readRootCandidate", "assertions": [ "G3.b" ] } ], "consumersHint": { "cli": [], "server": [], "sdk": [], "note": "scanned cli@4e593722 server@c60beebe sdk@a9440f2 — a name listed is MENTIONED there today, which is evidence of consumption, not proof of it. Ledger files (**/docs/core-consumption/**, **/docs/wire-consumption/**, **/*LEDGER*.json) are not evidence of use — server: 1 name(s) matched ONLY in bookkeeping files and were set aside (SecretEnvFindingKind)" }, "breakingCount": 0, "breakingItems": [], "toResolvedAt": "c7c5484e2ab1b4abcba1297de62424e71306e66c" }