@sema-agent/core
Version:
Stateless, task-oriented AI agent core
706 lines (705 loc) • 23.2 kB
JSON
{
"repo": "core",
"version": "7.31.0",
"from": "dd49f2638b0c29a0ff735b8870b1534dce4e0485",
"to": "v7.31.0",
"added": [
{
"name": "MEMORY_PROJECT_KEY_ABSENT_REASONS",
"kind": "variable",
"tier": "advanced",
"at": [
"src/core/memory.ts:1091",
"src/index.ts:1984"
],
"criteriaCovered": false,
"breaking": false
},
{
"name": "MemoryProjectKey",
"kind": "type",
"tier": "advanced",
"at": [
"src/core/memory.ts:1103",
"src/index.ts:1986"
],
"criteriaCovered": true,
"breaking": false
},
{
"name": "MemoryProjectKeyAbsentReason",
"kind": "type",
"tier": "advanced",
"at": [
"src/core/memory.ts:1092",
"src/index.ts:1985"
],
"criteriaCovered": false,
"breaking": false
}
],
"removed": [],
"changed": [],
"narrowed": [
{
"id": "F3",
"source": "behaviorFlips.summary",
"text": "Additive deployment switch + one NARROWING (#1050; +1 `RunnerDeps` word, +1 config code; two refusal texts reworded, codes unchanged; +0 exports). (a) `RunnerDeps.fileHistoryCapture?: \"off\"` beside a real store: no run records (no first-touch, no boundary, no fork carry, no advisory; the leg's `wiring_manifest.fileHistory` reads `\"disabled\"`), and the store stays the restore seat — `restoreFiles` / `rewindFilesTo` converge to boundaries already in it. Every other value, and `\"off\"` with no real store (key omitted, or `fileHistoryStore: \"disabled\"`), refuses prepare `config.invalid_file_history_capture` before any store call. (b) `rewind.store_unconfigured` names its arm — an omitted store keeps `… this deployment wired no RunnerDeps.fileHistoryStore …`, a `\"disabled\"` seat says `… this deployment declared file history disabled (RunnerDeps.fileHistoryStore: \"disabled\") …` — and `rewind_snapshot.unresolvable`'s second sentence says boundaries exist only for turns that recorded history (KL-1047a closed). (c) NARROWING: `resumeAt` + `resumeAtMode: \"before\"` + `restoreFiles` converges to the target entry's OWN boundary or refuses `rewind_snapshot.unresolvable` with the files untouched (`entry \"<id>\" has no file-history boundary … never crosses into an earlier turn`); the fallback to the nearest boundary-carrying ancestor — which also reverted edits the kept conversation still shows — is removed (`rewindFilesTo` and `\"at\"` mode never walked). WHO IS HURT: a consumer matching the two refusal texts (switch on the code), a deployment writing `\"off\"` with no store, a consumer pinning the `config.*` code set, a caller sending a before-restore at a steer / follow-up entry or at a turn that recorded nothing. ORDER: core first. Residual KL-1050a."
},
{
"id": "F4",
"source": "behaviorFlips.summary",
"text": "Behaviour NARROWING (#1074; +0 exports, +0 wire keys): a stop ends the leg. A leg whose abort has fired issues no prompt — read at each leg's prompt door after everything that can fire it: the durable classifier denial-limit stop (inside the resume leg's decision application), a cancel landing while the approved call runs on a resume, while a parked steer is screened, or while the objective's image is fetched. `AgentHarness.prompt` mints its run controller before its own startup awaits, so a cancel landing while a prompt starts up reaches the loop, and a run aborted before its first turn ends `run aborted` (not `invalid_state`). After the durable stop: 0 model calls, 0 tool frames, one `done` carrying `classifier.denial_limit` and the notice's sentence, whatever limits are declared; a cancel before the prompt ends `failed` / `run aborted` with no model call. A continuation not sent stays owed: a steer parked on the consumed row is announced (`task.user_steer_undrained`), a review decision it would have delivered reopens its row, the objective leg publishes no `human_input` \"applied\" account, the suspended batch's unanswered siblings close \"never executed\". WHO IS HURT: a host or test that counted the post-stop turns or read a `limits.*` code off a stopped durable leg. Residuals KL-1074a–c."
},
{
"id": "F6",
"source": "behaviorFlips.summary",
"text": "Behaviour NARROWING (#1076b, #1080; +0 exports; +2 optional `MemorySessionHandle` keys `layerBaseline`, `accountLeg`; +0 wire keys; +1 incident code `memory.observation_settlement_unavailable`): bytes that appear in a read-only memory layer during a session are never adopted. A session's harvest compares each layer it holds read-only with a census taken at its materialize; every file whose bytes changed in that window and that no commit backs is recorded in the control plane (`layer-observations.json`). Every door through which uncommitted disk state enters the committed account consults it — the adopting read's edit / new-file / move arms, the lock-free retrieval face, a writer's harvest: a recorded divergence is NOT adopted — the committed copy is served, the file is left as found, and every session that meets it is told (`change NOT adopted: …` / `file NOT adopted: …`). A divergence nobody recorded (a git pull between sessions) is adopted as before; a commit that moves an entry's rev retires every record made against the old rev. While a transaction journal is pending the question is undecidable: the change is recorded UNDECIDED (never adopted meanwhile; `change NOT adopted yet …`); the first session that may write settles each undecided row after its preflight recovered the journal — a commit backing the bytes at their seat drops that row, a readable committed face that does not back them pins the row to the rev it read (an ordinary row from then on), an unreadable one keeps it undecided. A zero-copy backend without the committed-snapshot face (`committedSnapshotOf` — e.g. a wrapper that does not pass it through) records every such change undecided and never settles it; the engine states that ONCE per engine at materialize (`memory.observation_settlement_unavailable` on `MemoryEngineOptions.onIncident`). Writer presence (#1080): a writing session does not restore a read-only layer file while a session that writes that layer is live — liveness is the session-account row's leg (`terminatedAt` absent), never `closedAt` — it warns instead. WHO IS HURT: a legitimate write landing inside a session's window in a layer that session holds read-only (a git pull during it) is recorded and not adopted until a commit moves its rev or its bytes change (KL-1076b-a); a host relying on a zero-copy mount rewriting a hand-edited entry file into canonical bytes. Residuals KL-1076b-b – KL-1076b-o."
},
{
"id": "F7",
"source": "behaviorFlips.summary",
"text": "BREAKING (type: the optional `ResolvedCrossSessionInboundSetting.deprecatedLayers` is removed) + behaviour NARROWING (#1078; +0 exports): `crossSessionInbound`'s retired spelling `accept` reads exactly like any other unrecognized value — the layer is reported in `invalidLayers` with `decidedBy: \"invalid\"`, and the existing fail-closed rule forces `hold` whenever the standing value is looser (the drain holds each record with the `invalid-setting` cause, disclosed as `peer.inbound_disposition` with `disposition: \"held\"`); the per-leg spelling announcement and the module-local `CROSS_SESSION_INBOUND_DEPRECATED_SPELLINGS` (never exported) are gone. THREE SENTENCES — WHO IS HURT: a settings layer (managed / user / repo) still spelling `accept`, silently migrated to `next-turn` with one warning per leg on 7.30.x, now holds every cross-session message it would have delivered; a reader of `deprecatedLayers` gets a type error. COMPENSATION: settings-schema 6.0.0 already rejects `accept` at the schema door, so no currently valid settings file carries it, and the hold is announced through the same invalid-setting arm a typo takes. UPGRADE: write `next-turn` in every layer that says `accept`, and drop reads of `deprecatedLayers`."
},
{
"id": "F8",
"source": "behaviorFlips.summary",
"text": "Additive (#1079; +0 exports; +2 optional type keys; no checkpoint-version bump) + one NARROWING (#1088, tightening only). (a) The durable park row carries the mandate twin: `PendingAction` (`tool_approval` arm) `.mandated?: true` and `CheckpointSummary.mandated?: true` — present ⇔ no persisted allow rule and no standing answer may retire the parked question; `true` only, never `false`; minted from the SAME clearance-facts object the row's rule-offer factory reads, through the derivation the live card's `AskRequest.mandated` comes from; the summary screens it to the literal `true`. Three independent facts now ride a parked card: `requiresRealApproval` (only a person — implies the mandate), `mandated` (no rule), `ruleOffersAbsence` (what the offer lane has to give). Display metadata: no gate, CAS or resume path reads it; a row minted before it reads absent (unreported). (b) #1088: when a JSON-fidelity checkpoint backend's projection moves the parked value and the deployment's policy re-judges the stored shape, the re-judgment's ask JOINS the gate's facts, tightening only — its `requiresRealApproval` makes the park `irreversible_ask` with `gate.realApproval` (worded by the parked ask's own origin) and the row's `requiresRealApproval`; its mandate and an explicit ask-rule match join the clearance facts. A demand the first judgment already made is kept; a re-judgment that allows or asks plainly changes nothing. WHO IS HURT: (#1088) a budget resolver that auto-approved such a park (`human` → `irreversible_ask`) no longer may; a custom `CheckpointStore` must round-trip `mandated` (the store-contract kit now fails a whitelisting serializer)."
}
],
"closedSetMembers": [
{
"set": "ENGINE_NOTICE_CODES",
"at": [
"src/core/governance-codes.ts:317"
],
"newSet": false,
"added": [
"config.secret_env_scrubbed"
],
"removed": [],
"breaking": false,
"criteriaCovered": true
},
{
"set": "SessionAccountWrite",
"at": [
"src/core/memory-engine/delegation-settlement.ts:680"
],
"newSet": true,
"added": [
"absent",
"stale",
"written"
],
"removed": [],
"breaking": false,
"criteriaCovered": false
}
],
"closedSetsUnreadable": [],
"typeKeys": [
{
"type": "CheckpointSummary",
"at": [
"src/core/checkpoint-store.ts:2090"
],
"added": [
"mandated"
],
"addedDetail": [
{
"key": "mandated",
"optional": true
}
],
"addedRequired": [],
"removed": [],
"breaking": false,
"criteriaCovered": true
},
{
"type": "MemorySessionHandle",
"at": [
"src/core/memory-engine/types.ts:403"
],
"added": [
"accountLeg",
"layerBaseline"
],
"addedDetail": [
{
"key": "accountLeg",
"optional": true
},
{
"key": "layerBaseline",
"optional": true
}
],
"addedRequired": [],
"removed": [],
"breaking": false,
"criteriaCovered": true
},
{
"type": "NodeLspManagerOptions",
"at": [
"src/engine/lsp/node-lsp-manager.ts:77"
],
"added": [
"onNotice"
],
"addedDetail": [
{
"key": "onNotice",
"optional": true
}
],
"addedRequired": [],
"removed": [],
"breaking": false,
"criteriaCovered": true
},
{
"type": "ParentSpecSeat",
"at": [
"src/core/parent-spec-seat.ts:67"
],
"added": [
"fileHistory"
],
"addedDetail": [
{
"key": "fileHistory",
"optional": true
}
],
"addedRequired": [],
"removed": [],
"breaking": false,
"criteriaCovered": false
},
{
"type": "PendingAction",
"at": [
"src/core/checkpoint-store.ts:962"
],
"added": [
"tool_approval.mandated"
],
"addedDetail": [
{
"key": "tool_approval.mandated",
"optional": true
}
],
"addedRequired": [],
"removed": [],
"breaking": false,
"criteriaCovered": false
},
{
"type": "ResolvedCrossSessionInboundSetting",
"at": [
"src/agents/cross-session-judge.ts:54"
],
"added": [],
"addedDetail": [],
"addedRequired": [],
"removed": [
"deprecatedLayers"
],
"breaking": true,
"criteriaCovered": false
},
{
"type": "RunnerDeps",
"at": [
"src/core/runner-deps.ts:105"
],
"added": [
"fileHistoryCapture"
],
"addedDetail": [
{
"key": "fileHistoryCapture",
"optional": true
}
],
"addedRequired": [],
"removed": [],
"breaking": false,
"criteriaCovered": true
},
{
"type": "TaskSpec",
"at": [
"src/core/task-spec.ts:55"
],
"added": [
"fileHistory"
],
"addedDetail": [
{
"key": "fileHistory",
"optional": true
}
],
"addedRequired": [],
"removed": [],
"breaking": false,
"criteriaCovered": true
},
{
"type": "WiringFacts",
"at": [
"src/core/wiring-manifest.ts:431"
],
"added": [
"fileHistory"
],
"addedDetail": [
{
"key": "fileHistory",
"optional": true
}
],
"addedRequired": [],
"removed": [],
"breaking": false,
"criteriaCovered": false
},
{
"type": "WiringManifest",
"at": [
"src/core/wiring-manifest.ts:183"
],
"added": [
"fileHistory"
],
"addedDetail": [
{
"key": "fileHistory",
"optional": true
}
],
"addedRequired": [],
"removed": [],
"breaking": false,
"criteriaCovered": true
}
],
"typeKeysUnreadableArms": [],
"typeKeysFlattenedCount": 214,
"declarationMoves": [
{
"name": "DEFAULT_MAX_ENTRY_DEPTH",
"kind": "variable",
"onSurface": true,
"from": [
"src/core/memory-engine/file-backend.ts",
"src/core/memory-engine/index.ts",
"src/index.ts"
],
"to": [
"src/core/memory-engine/entry-scan.ts",
"src/core/memory-engine/file-backend.ts",
"src/core/memory-engine/index.ts",
"src/index.ts"
]
},
{
"name": "MEMORY_INDEX_FILENAME",
"kind": "variable",
"onSurface": true,
"from": [
"src/core/memory-engine/file-backend.ts",
"src/core/memory-engine/index.ts",
"src/index.ts"
],
"to": [
"src/core/memory-engine/entry-scan.ts",
"src/core/memory-engine/file-backend.ts",
"src/core/memory-engine/index.ts",
"src/index.ts"
]
},
{
"name": "MEMORY_PROJECT_KEY_ABSENT_REASONS",
"kind": "variable",
"onSurface": true,
"from": [
"src/core/memory.ts"
],
"to": [
"src/core/memory.ts",
"src/index.ts"
]
},
{
"name": "MemoryProjectKey",
"kind": "type",
"onSurface": true,
"from": [
"src/core/memory.ts"
],
"to": [
"src/core/memory.ts",
"src/index.ts"
]
},
{
"name": "MemoryProjectKeyAbsentReason",
"kind": "type",
"onSurface": true,
"from": [
"src/core/memory.ts"
],
"to": [
"src/core/memory.ts",
"src/index.ts"
]
},
{
"name": "ScannedEntryFile",
"kind": "interface",
"onSurface": true,
"from": [
"src/core/memory-engine/file-backend.ts",
"src/core/memory-engine/index.ts",
"src/index.ts"
],
"to": [
"src/core/memory-engine/entry-scan.ts",
"src/core/memory-engine/file-backend.ts",
"src/core/memory-engine/index.ts",
"src/index.ts"
]
},
{
"name": "scanEntryFiles",
"kind": "function",
"onSurface": true,
"from": [
"src/core/memory-engine/file-backend.ts",
"src/core/memory-engine/index.ts",
"src/index.ts"
],
"to": [
"src/core/memory-engine/entry-scan.ts",
"src/core/memory-engine/file-backend.ts",
"src/core/memory-engine/index.ts",
"src/index.ts"
]
}
],
"mintMoves": [],
"criteriaObserves": [
{
"kind": "engineNoticeCode",
"name": "classifier.denial_limit",
"assertions": [
"G4.a"
]
},
{
"kind": "engineNoticeCode",
"name": "config.secret_env_scrubbed",
"assertions": [
"G9.a"
]
},
{
"kind": "engineNoticeCode",
"name": "peer.inbound_disposition",
"assertions": [
"G7.a"
]
},
{
"kind": "taskEventField",
"name": "done.result",
"assertions": [
"G4.a"
]
},
{
"kind": "taskEventField",
"name": "steering_injected.preview",
"assertions": [
"G1.a"
]
},
{
"kind": "taskEventField",
"name": "steering_injected.source",
"assertions": [
"G1.a"
]
},
{
"kind": "taskEventField",
"name": "tool_end.isError",
"assertions": [
"G5.a"
]
},
{
"kind": "taskEventField",
"name": "tool_end.output",
"assertions": [
"G5.a"
]
},
{
"kind": "taskEventField",
"name": "tool_start.toolCallId",
"assertions": [
"G4.a"
]
},
{
"kind": "typeMember",
"name": "Checkpoint.gate.realApproval",
"assertions": [
"G8.a"
]
},
{
"kind": "typeMember",
"name": "CheckpointSummary.gateKind",
"assertions": [
"G8.a"
]
},
{
"kind": "typeMember",
"name": "CheckpointSummary.mandated",
"assertions": [
"G8.a"
]
},
{
"kind": "typeMember",
"name": "EngineNotice.detail",
"assertions": [
"G7.a",
"G9.a"
]
},
{
"kind": "typeMember",
"name": "HarvestReport.rejections",
"assertions": [
"G6.a"
]
},
{
"kind": "typeMember",
"name": "HarvestReport.restored",
"assertions": [
"G6.a"
]
},
{
"kind": "typeMember",
"name": "HarvestReport.warnings",
"assertions": [
"G5.a",
"G6.a",
"G6.b"
]
},
{
"kind": "typeMember",
"name": "MemoryEngine.eraseMemoryEntries",
"assertions": [
"G5.a"
]
},
{
"kind": "typeMember",
"name": "MemoryEngineOptions.onIncident",
"assertions": [
"G6.b"
]
},
{
"kind": "typeMember",
"name": "MemoryProjectKey.absent",
"assertions": [
"G10.a"
]
},
{
"kind": "typeMember",
"name": "MemoryProjectKey.scope",
"assertions": [
"G10.a"
]
},
{
"kind": "typeMember",
"name": "MemorySessionHandle.layerBaseline",
"assertions": [
"G6.a"
]
},
{
"kind": "typeMember",
"name": "MemorySessionHandle.materialized",
"assertions": [
"G5.a",
"G6.a",
"G6.b"
]
},
{
"kind": "typeMember",
"name": "NodeLspManagerOptions.onNotice",
"assertions": [
"G9.a"
]
},
{
"kind": "typeMember",
"name": "PendingAction.mandated",
"assertions": [
"G8.a"
]
},
{
"kind": "typeMember",
"name": "PendingAction.requiresRealApproval",
"assertions": [
"G8.a"
]
},
{
"kind": "typeMember",
"name": "ResolvedCrossSessionInboundSetting.decidedBy",
"assertions": [
"G7.a"
]
},
{
"kind": "typeMember",
"name": "ResolvedCrossSessionInboundSetting.invalidLayers",
"assertions": [
"G7.a"
]
},
{
"kind": "typeMember",
"name": "ResolvedCrossSessionInboundSetting.value",
"assertions": [
"G7.a"
]
},
{
"kind": "typeMember",
"name": "RunnerDeps.fileHistoryCapture",
"assertions": [
"G3.a"
]
},
{
"kind": "typeMember",
"name": "TaskResult.terminal.code",
"assertions": [
"G2.a",
"G3.a",
"G3.b",
"G4.a"
]
},
{
"kind": "typeMember",
"name": "TaskResult.terminal.message",
"assertions": [
"G3.a",
"G3.b"
]
},
{
"kind": "typeMember",
"name": "TaskSpec.fileHistory",
"assertions": [
"G2.a"
]
},
{
"kind": "typeMember",
"name": "TaskSpec.memory.projectKey",
"assertions": [
"G10.a"
]
},
{
"kind": "typeMember",
"name": "TaskSpec.restoreFiles",
"assertions": [
"G3.b"
]
},
{
"kind": "typeMember",
"name": "TaskSpec.resumeAtMode",
"assertions": [
"G3.b"
]
},
{
"kind": "typeMember",
"name": "WiringManifest.fileHistory",
"assertions": [
"G2.a",
"G3.a"
]
}
],
"consumersHint": {
"cli": [
"CheckpointSummary",
"ENGINE_NOTICE_CODES",
"MEMORY_PROJECT_KEY_ABSENT_REASONS",
"MemoryProjectKeyAbsentReason",
"MemorySessionHandle",
"ParentSpecSeat",
"PendingAction",
"RunnerDeps",
"TaskSpec",
"WiringFacts",
"WiringManifest"
],
"server": [
"CheckpointSummary",
"ENGINE_NOTICE_CODES",
"MEMORY_PROJECT_KEY_ABSENT_REASONS",
"MemoryProjectKey",
"MemorySessionHandle",
"NodeLspManagerOptions",
"ParentSpecSeat",
"PendingAction",
"RunnerDeps",
"TaskSpec",
"WiringFacts",
"WiringManifest"
],
"sdk": [
"CheckpointSummary",
"ENGINE_NOTICE_CODES",
"PendingAction",
"RunnerDeps",
"TaskSpec",
"WiringManifest"
],
"note": "scanned cli@4e593722 server@57709419 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 (ResolvedCrossSessionInboundSetting)"
},
"breakingCount": 1,
"breakingItems": [
"type lost keys: ResolvedCrossSessionInboundSetting -deprecatedLayers"
],
"toResolvedAt": "3f6c68b65cc5b8f778b01c42cf4e838babf97be1"
}