{
  "repo": "core",
  "version": "7.40.0",
  "from": "22e5cf13b7bb519f5b50c74e9b6035693cc0e6d1",
  "to": "bb53e9641e80586def0084e6a9ffdbc1dafa5c91",
  "added": [],
  "removed": [],
  "changed": [],
  "narrowed": [
    {
      "id": "F2",
      "source": "behaviorFlips.after",
      "text": "one card per such call, the Read tool's card (`askClass: \"ask_rule\"`, the same `message`), in `default` and `bypassPermissions`; `dontAsk` refuses; answered no ⇒ nothing of the search reaches the model; answered yes ⇒ the search runs and the next search of that path asks again. A search rooted ABOVE the asked path (no `path`, a relative Glob pattern) is not asked and its results are not filtered (KL-1291-a). The deny is unchanged. WHO IS HURT: a deployment or script that wrote a `Read(<path>)` ask rule and searched that path without a card (now asked; headless ⇒ refused). COMPENSATION: narrow the ask rule's pattern, or use the persisted `Read(//dir/**)` directory row for reads that need no person. IF UNCHANGED: those searches stop running without a person's answer."
    },
    {
      "id": "F3",
      "source": "behaviorFlips.after",
      "text": "one card per such call, the Edit tool's card (`askClass: \"ask_rule\"`), in `default` and `bypassPermissions`; answered no ⇒ nothing is written. A Read under the asked path raises no card (read face untouched); a Write outside it raises none. The deny column is unchanged. WHO IS HURT: a deployment or script that wrote an `Edit(<path>)` ask rule and wrote under that path with Write / NotebookEdit without a card (now asked; headless ⇒ refused). COMPENSATION: narrow the rule's pattern or drop it for paths that need no person. IF UNCHANGED: those writes stop running without a person's answer."
    }
  ],
  "closedSetMembers": [
    {
      "set": "ASK_CLASSES",
      "at": [
        "src/core/ask-origin.ts:583"
      ],
      "newSet": false,
      "added": [
        "unstated"
      ],
      "removed": [],
      "breaking": false,
      "criteriaCovered": false
    },
    {
      "set": "AgentTool.permissionSeat",
      "at": [
        "src/engine/loop/types.ts:849"
      ],
      "newSet": true,
      "added": [
        "passthrough"
      ],
      "removed": [],
      "breaking": false,
      "criteriaCovered": false
    },
    {
      "set": "AskOriginFacts.tightened",
      "at": [
        "src/core/ask-origin.ts:115"
      ],
      "newSet": false,
      "added": [
        "unstated"
      ],
      "removed": [],
      "breaking": false,
      "criteriaCovered": false
    },
    {
      "set": "ModePolicy.unstated",
      "at": [
        "src/core/mode-policy.ts:56"
      ],
      "newSet": true,
      "added": [
        "ask",
        "none"
      ],
      "removed": [],
      "breaking": false,
      "criteriaCovered": false
    },
    {
      "set": "ToolGateInput.permissionSeat",
      "at": [
        "src/core/hooks.ts:1804"
      ],
      "newSet": true,
      "added": [
        "passthrough"
      ],
      "removed": [],
      "breaking": false,
      "criteriaCovered": false
    },
    {
      "set": "ToolSpec.permissionSeat",
      "at": [
        "src/core/tool-spec.ts:283"
      ],
      "newSet": true,
      "added": [
        "passthrough"
      ],
      "removed": [],
      "breaking": false,
      "criteriaCovered": false
    }
  ],
  "closedSetsUnreadable": [],
  "typeKeys": [
    {
      "type": "AgentTool",
      "at": [
        "src/engine/loop/types.ts:768"
      ],
      "via": "A2aRefreshResult.tools",
      "added": [
        "permissionSeat"
      ],
      "addedDetail": [
        {
          "key": "permissionSeat",
          "optional": true
        }
      ],
      "addedRequired": [],
      "removed": [],
      "breaking": false,
      "criteriaCovered": false
    },
    {
      "type": "HandsBandOptions",
      "at": [
        "src/core/hands-band.ts:106"
      ],
      "added": [],
      "addedDetail": [],
      "addedRequired": [],
      "removed": [
        "readCyberReminder"
      ],
      "breaking": true,
      "criteriaCovered": false
    },
    {
      "type": "ModePolicy",
      "at": [
        "src/core/mode-policy.ts:51"
      ],
      "added": [
        "unstated"
      ],
      "addedDetail": [
        {
          "key": "unstated",
          "optional": false
        }
      ],
      "addedRequired": [
        "unstated"
      ],
      "removed": [],
      "breaking": true,
      "criteriaCovered": false
    },
    {
      "type": "ToolGateInput",
      "at": [
        "src/core/hooks.ts:1467"
      ],
      "via": "runToolGate.ToolGateInput",
      "added": [
        "permissionSeat"
      ],
      "addedDetail": [
        {
          "key": "permissionSeat",
          "optional": true
        }
      ],
      "addedRequired": [],
      "removed": [],
      "breaking": false,
      "criteriaCovered": false
    },
    {
      "type": "ToolSpec",
      "at": [
        "src/core/tool-spec.ts:131"
      ],
      "added": [
        "permissionSeat"
      ],
      "addedDetail": [
        {
          "key": "permissionSeat",
          "optional": true
        }
      ],
      "addedRequired": [],
      "removed": [],
      "breaking": false,
      "criteriaCovered": false
    }
  ],
  "typeKeysUnreadableArms": [],
  "typeKeysFlattenedCount": 220,
  "signatures": [
    {
      "name": "adjudicatePersistedPathRules",
      "at": [
        "src/core/permission-rule-model.ts:2309"
      ],
      "from": [
        "(rules: readonly PersistedRule[], call: { tool: string; cwd: string | undefined; sessionId?: string; }, targets: { readonly tighten?: PathTargetReading; readonly allow?: PathTargetReading; }, bases: PathRuleBases): PersistedRuleVerdict | undefined"
      ],
      "to": [
        "(rules: readonly PersistedRule[], call: { tool: string; cwd: string | undefined; sessionId?: string; face?: DenyFace | undefined; }, targets: { readonly tighten?: PathTargetReading; readonly allow?: PathTargetReading; }, bases: PathRuleBases): PersistedRuleVerdict | undefined"
      ],
      "changes": [
        {
          "aspect": "param",
          "detail": "param 2 `call` type widened: …ed; sessionId?: string; [ -> face?: DenyFace | undefined; ]}",
          "breaking": false
        }
      ],
      "breaking": false,
      "criteriaCovered": false
    },
    {
      "name": "createAllowDenyPolicy",
      "at": [
        "src/core/tool-policy.ts:1299"
      ],
      "from": [
        "(opts: { allow?: string[]; deny?: string[]; onInvalidName?: \"throw\" | \"skip\"; onInvalidNameIssue?: (issue: { entry: string; list: \"allow\" | \"deny\"; message: string; }) => void; }): NamedToolPolicy"
      ],
      "to": [
        "(opts: { allow?: string[]; deny?: string[]; onInvalidName?: \"throw\" | \"skip\"; onInvalidNameIssue?: (issue: { entry: string; list: \"allow\" | \"deny\"; message: string; }) => void; scope?: \"grant\" | \"narrowing\"; }): NamedToolPolicy"
      ],
      "changes": [
        {
          "aspect": "param",
          "detail": "param 1 `opts` type widened: …ge: string; }) => void; [ -> scope?: \"grant\" | \"narrowing\"; ]}",
          "breaking": false
        }
      ],
      "breaking": false,
      "criteriaCovered": false
    }
  ],
  "declarationMoves": [],
  "mintMoves": [],
  "criteriaObserves": [
    {
      "kind": "taskEventField",
      "name": "tool_end.errorCode",
      "assertions": [
        "G7.f"
      ]
    },
    {
      "kind": "taskEventField",
      "name": "tool_end.gate",
      "assertions": [
        "G1.b",
        "G3.a",
        "G7.b",
        "G7.c",
        "G7.e",
        "G8.b",
        "G8.d"
      ]
    },
    {
      "kind": "taskEventField",
      "name": "tool_end.output",
      "assertions": [
        "G9.a",
        "G9.b"
      ]
    },
    {
      "kind": "typeMember",
      "name": "AskRequest.askClass",
      "assertions": [
        "G7.a",
        "G8.a"
      ]
    },
    {
      "kind": "typeMember",
      "name": "AskRequest.classes",
      "assertions": [
        "G1.a",
        "G2.a",
        "G2.b",
        "G3.b",
        "G5.a",
        "G5.b",
        "G6.a",
        "G7.a"
      ]
    },
    {
      "kind": "typeMember",
      "name": "AskRequest.message",
      "assertions": [
        "G7.a"
      ]
    },
    {
      "kind": "typeMember",
      "name": "AskRequest.origin",
      "assertions": [
        "G1.a"
      ]
    },
    {
      "kind": "typeMember",
      "name": "AskRequest.toolName",
      "assertions": [
        "G7.a",
        "G7.c",
        "G7.d",
        "G7.e",
        "G7.f",
        "G8.a",
        "G8.c",
        "G8.d"
      ]
    },
    {
      "kind": "typeMember",
      "name": "Context.systemPrompt",
      "assertions": [
        "G9.d"
      ]
    },
    {
      "kind": "typeMember",
      "name": "HandsBandOptions.readCyberReminder",
      "assertions": [
        "G9.c"
      ]
    },
    {
      "kind": "typeMember",
      "name": "PendingAction.classes",
      "assertions": [
        "G4.a",
        "G4.b"
      ]
    }
  ],
  "consumersHint": {
    "cli": [
      "ASK_CLASSES",
      "AgentTool",
      "AskOriginFacts",
      "ModePolicy",
      "ToolGateInput",
      "ToolSpec",
      "createAllowDenyPolicy"
    ],
    "server": [
      "ASK_CLASSES",
      "AgentTool",
      "ToolGateInput",
      "ToolSpec",
      "createAllowDenyPolicy"
    ],
    "sdk": [
      "ASK_CLASSES"
    ],
    "note": "scanned cli@1c57a121 server@79de35f8 sdk@8ce1faa — 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: 3 name(s) matched ONLY in bookkeeping files and were set aside (HandsBandOptions, ModePolicy, adjudicatePersistedPathRules)"
  },
  "breakingCount": 2,
  "breakingItems": [
    "type gained required keys: ModePolicy +unstated",
    "type lost keys: HandsBandOptions -readCyberReminder"
  ]
}
