{
  "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"
}
