Uploaded using `kernel-builder`.

#2
by kernels-bot - opened
README.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: kernels
3
+ license: mit
4
+ ---
5
+
6
+ This is the repository card of ggml-org/ggml-attn that has been pushed on the Hub. It was built to be used with the [`kernels` library](https://github.com/huggingface/kernels). This card was automatically generated.
7
+
8
+ ## How to use
9
+
10
+ ```python
11
+ # make sure `kernels` is installed: `pip install -U kernels`
12
+ from kernels import get_kernel
13
+
14
+ kernel_module = get_kernel("ggml-org/ggml-attn", version=1)
15
+ flash_attn = kernel_module.flash_attn
16
+
17
+ flash_attn(...)
18
+ ```
19
+
20
+ ## Available functions
21
+ - `flash_attn`
22
+ - `supports_flash_attn`
23
+ - `flash_attn_forward`
24
+
25
+ ## Benchmarks
26
+
27
+ No benchmark available yet.
build/torch213-metal-aarch64-darwin/__init__.py CHANGED
@@ -29,27 +29,34 @@ def flash_attn(
29
  v: torch.Tensor,
30
  mask: torch.Tensor | None = None,
31
  scale: float | None = None,
 
 
32
  ) -> torch.Tensor:
33
  """Flash attention through ggml's vector kernel — the path upstream picks for decode.
34
 
35
  Args:
36
  q: `(n_seqs, n_heads, n_q, head_dim)`.
37
  k, v: `(n_seqs, n_heads_kv, n_kv, head_dim)`. Grouped-query attention is native, so do **not**
38
- expand them to `n_heads` first — that copy is exactly what this avoids.
 
39
  mask: `(n_seqs, 1, n_q, n_kv)` additive mask, or None. Cast to f16 internally, as the kernel
40
  requires. **A None mask means attend to everything**: ggml has no `is_causal` argument, so
41
  causality has to arrive as a mask. `flash_attn_forward` builds one when it must.
42
  scale: softmax scale; defaults to `head_dim ** -0.5`.
 
 
 
 
43
 
44
  Returns:
45
- `(n_seqs, n_q, n_heads, head_dim)` — tokens before heads, which is what SDPA gives after its
46
  own `.transpose(1, 2)`, so a caller usually wants precisely this and no further permute.
47
 
48
  Ask `supports_flash_attn` first: it answers for whichever of upstream's two paths the shape selects.
49
  """
50
  if scale is None:
51
  scale = q.shape[-1] ** -0.5
52
- return ops.flash_attn(q, k, v, mask, scale)
53
 
54
 
55
  def supports_flash_attn(n_q: int, head_dim_k: int, head_dim_v: int) -> bool:
@@ -62,7 +69,7 @@ def supports_flash_attn(n_q: int, head_dim_k: int, head_dim_v: int) -> bool:
62
 
63
 
64
  @torch.library.register_fake(add_op_namespace_prefix("flash_attn"))
65
- def _(q, k, v, mask, scale):
66
  n_seqs, n_heads, n_q, _ = q.shape
67
  return q.new_empty((n_seqs, n_q, n_heads, v.shape[-1]))
68
 
@@ -142,4 +149,8 @@ def flash_attn_forward(
142
  mask = torch.zeros_like(mask, dtype=query.dtype).masked_fill_(~mask, float("-inf"))
143
  elif mask is None and n_q > 1:
144
  mask = _causal_mask(query, key.shape[2])
145
- return flash_attn(query, key, value, mask, scaling), None
 
 
 
 
 
29
  v: torch.Tensor,
30
  mask: torch.Tensor | None = None,
31
  scale: float | None = None,
32
+ sinks: torch.Tensor | None = None,
33
+ softcap: float = 0.0,
34
  ) -> torch.Tensor:
35
  """Flash attention through ggml's vector kernel — the path upstream picks for decode.
36
 
37
  Args:
38
  q: `(n_seqs, n_heads, n_q, head_dim)`.
39
  k, v: `(n_seqs, n_heads_kv, n_kv, head_dim)`. Grouped-query attention is native, so do **not**
40
+ expand them to `n_heads` first — that copy is exactly what this avoids. An f16 cache is read
41
+ as f16, as llama.cpp reads its default cache; other dtypes are read as f32.
42
  mask: `(n_seqs, 1, n_q, n_kv)` additive mask, or None. Cast to f16 internally, as the kernel
43
  requires. **A None mask means attend to everything**: ggml has no `is_causal` argument, so
44
  causality has to arrive as a mask. `flash_attn_forward` builds one when it must.
45
  scale: softmax scale; defaults to `head_dim ** -0.5`.
46
+ sinks: attention sinks, one logit per query head that joins each row's softmax and takes no
47
+ value (gpt-oss's `s_aux`); upstream's `ggml_flash_attn_ext_add_sinks`.
48
+ softcap: logit softcapping, `softcap * tanh(scores / softcap)` before the softmax (Gemma 2's
49
+ `attn_logit_softcapping`); 0 for none.
50
 
51
  Returns:
52
+ `(n_seqs, n_q, n_heads, head_dim)` f32 — tokens before heads, which is what SDPA gives after its
53
  own `.transpose(1, 2)`, so a caller usually wants precisely this and no further permute.
54
 
55
  Ask `supports_flash_attn` first: it answers for whichever of upstream's two paths the shape selects.
56
  """
57
  if scale is None:
58
  scale = q.shape[-1] ** -0.5
59
+ return ops.flash_attn(q, k, v, mask, scale, sinks, softcap)
60
 
61
 
62
  def supports_flash_attn(n_q: int, head_dim_k: int, head_dim_v: int) -> bool:
 
69
 
70
 
71
  @torch.library.register_fake(add_op_namespace_prefix("flash_attn"))
72
+ def _(q, k, v, mask, scale, sinks=None, softcap=0.0):
73
  n_seqs, n_heads, n_q, _ = q.shape
74
  return q.new_empty((n_seqs, n_q, n_heads, v.shape[-1]))
75
 
 
149
  mask = torch.zeros_like(mask, dtype=query.dtype).masked_fill_(~mask, float("-inf"))
150
  elif mask is None and n_q > 1:
151
  mask = _causal_mask(query, key.shape[2])
152
+ # transformers passes gpt-oss's sinks as `s_aux` and Gemma 2's softcapping as `softcap`
153
+ sinks = kwargs.get("s_aux")
154
+ softcap = kwargs.get("softcap") or 0.0
155
+ # ggml writes f32; hand the model back the dtype it computes in
156
+ return flash_attn(query, key, value, mask, scaling, sinks, softcap).to(query.dtype), None
build/torch213-metal-aarch64-darwin/{_ggml_attn_metal_38609dd.abi3.so → _ggml_attn_metal_5d7b6e7.abi3.so} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c923b96bb4fa61c94f9a2ff9cc8f71c637066f7292324507180cfaa189cb6120
3
- size 9099744
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e017d9f0d620e99020649f14d2cc6bb6523a3825384591309d2db0d8515505e1
3
+ size 9578960
build/torch213-metal-aarch64-darwin/_ops.py CHANGED
@@ -1,9 +1,9 @@
1
  import torch
2
- from . import _ggml_attn_metal_38609dd
3
- ops = torch.ops._ggml_attn_metal_38609dd
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
- return f"_ggml_attn_metal_38609dd::{op_name}"
 
1
  import torch
2
+ from . import _ggml_attn_metal_5d7b6e7
3
+ ops = torch.ops._ggml_attn_metal_5d7b6e7
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
+ return f"_ggml_attn_metal_5d7b6e7::{op_name}"
build/torch213-metal-aarch64-darwin/metadata.json CHANGED
@@ -1,28 +1,30 @@
1
  {
2
  "name": "ggml-attn",
3
- "id": "_ggml_attn_metal_38609dd",
4
  "version": 1,
 
5
  "license": "MIT",
6
  "python-depends": [],
 
7
  "backend": {
8
  "type": "metal"
9
  },
10
  "digest": {
11
  "algorithm": "sha256",
12
  "files": {
13
- "__init__.py": "Kt6HQYYMCjXZQD9j6zl+Lv9BK3JjRnUTdkfDugWYFcM=",
14
- "_ggml_attn_metal_38609dd.abi3.so": "ySO5a7T6YclPmi/5zI9xxjcGb3KSMkUHGAz6oYnLYSA=",
15
- "_ops.py": "/og8Es6zlSiSgMluZVuY2km9Bn54E27bJPEwx+6vj1s="
16
  }
17
  },
18
  "provenance": {
19
  "kernel-builder": {
20
  "version": "0.17.0-dev0",
21
- "sha": "81f55ea30fd8f819dcf93a3c934dd584c895bd2f",
22
  "dirty": false
23
  },
24
  "kernel": {
25
- "sha": "38609dd548a351e062a5810b4d5c50111a95e588",
26
  "dirty": false
27
  }
28
  }
 
1
  {
2
  "name": "ggml-attn",
3
+ "id": "_ggml_attn_metal_5d7b6e7",
4
  "version": 1,
5
+ "kernels-minver": "0.14.0",
6
  "license": "MIT",
7
  "python-depends": [],
8
+ "kernel-depends": [],
9
  "backend": {
10
  "type": "metal"
11
  },
12
  "digest": {
13
  "algorithm": "sha256",
14
  "files": {
15
+ "__init__.py": "2zbEFDRRtbDKJLS22KAG0/SEWEJycxEgVfkBR2gpo+s=",
16
+ "_ggml_attn_metal_5d7b6e7.abi3.so": "4BfZ8NYg6ZAgZJ8U0sxrtlI6OCU4RZEwnS2w2FFVBeE=",
17
+ "_ops.py": "YynNnQ4xi51MpqejOgt86BWJgohmwvhxWXeoS5ptgcM="
18
  }
19
  },
20
  "provenance": {
21
  "kernel-builder": {
22
  "version": "0.17.0-dev0",
23
+ "commit": "a7f0afdb29a6a3372b1d47180cc0c182454c5e3b",
24
  "dirty": false
25
  },
26
  "kernel": {
27
+ "commit": "5d7b6e7e86f54333d0428c714dd419a668e6297d",
28
  "dirty": false
29
  }
30
  }
build/torch213-metal-aarch64-darwin/metadata.json.sigstore CHANGED
@@ -1 +1 @@
1
- {"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json","verificationMaterial":{"certificate":{"rawBytes":"MIIHYTCCBuigAwIBAgIUfxixqHAcoVzE4ykpKb5XOU/s69EwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwOTAyMTIxNzMwWhcNMjYwOTAyMTIyNzMwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENxNqFb2hcJnURu3lipTXwyoErhjg2h81PPq4y9XIkHbk+lcQHBr7CYG1tYcwmI1+vyLsn8T6G2ev7zI/uU+yxKOCBgcwggYDMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUrTEzyN6AKuXfyYu8VQzVVVdoZVswHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLW1hYy55YW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDM4NjA5ZGQ1NDhhMzUxZTA2MmE1ODEwYjRkNWM1MDExMWE5NWU1ODgwGwYKKwYBBAGDvzABBAQNQnVpbGQgKG1hY09TKTArBgorBgEEAYO/MAEFBB1odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eTAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMHEGCisGAQQBg78wAQkEYwxhaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLW1hYy55YW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAEKBCoMKDM4NjA5ZGQ1NDhhMzUxZTA2MmE1ODEwYjRkNWM1MDExMWE5NWU1ODgwHQYKKwYBBAGDvzABCwQPDA1naXRodWItaG9zdGVkMEAGCisGAQQBg78wAQwEMgwwaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MDgGCisGAQQBg78wAQ0EKgwoMzg2MDlkZDU0OGEzNTFlMDYyYTU4MTBiNGQ1YzUwMTExYTk1ZTU4ODAfBgorBgEEAYO/MAEOBBEMD3JlZnMvaGVhZHMvbWFpbjAaBgorBgEEAYO/MAEPBAwMCjEwNzE0NzU1MjkwLgYKKwYBBAGDvzABEAQgDB5odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2UwGAYKKwYBBAGDvzABEQQKDAgyNTcyMDc0MzBxBgorBgEEAYO/MAESBGMMYWh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS8uZ2l0aHViL3dvcmtmbG93cy9idWlsZC1tYWMueWFtbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABEwQqDCgzODYwOWRkNTQ4YTM1MWUwNjJhNTgxMGI0ZDVjNTAxMTFhOTVlNTg4MCEGCisGAQQBg78wARQEEwwRd29ya2Zsb3dfZGlzcGF0Y2gwZAYKKwYBBAGDvzABFQRWDFRodHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkvYWN0aW9ucy9ydW5zLzMzNjI2MjY3OTIwL2F0dGVtcHRzLzEwFgYKKwYBBAGDvzABFgQIDAZwdWJsaWMwRgYKKwYBBAGDvzABGAQ4DDZyZXBvOmh1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5OnJlZjpyZWZzL2hlYWRzL21haW4wgYsGCisGAQQB1nkCBAIEfQR7AHkAdwDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynujgAAAaBiDY+sAAAEAwBIMEYCIQDEfYiQx1B8CiCc7bKU78qxXfEf7t20H1Aytd2nG4003gIhAPuqaokFPLTtUyshaQaCuZzg8wF6uRRPYWiR6vBJReCTMAoGCCqGSM49BAMDA2cAMGQCMHs/LilfqAmUbKGpahIvZKFpxj/rTpZ6zgXmRjAds27c4yeROY25QFFmHhxYjsXPvwIwa+8XHhrglzq5VO62ZW7dZjt0DEN7RlwJjD2L03ukQFZix3UNYLT9eoWlZTndHzXg"},"tlogEntries":[{"logIndex":"2685408631","logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="},"kindVersion":{"kind":"hashedrekord","version":"0.0.1"},"integratedTime":"1788351451","inclusionPromise":{"signedEntryTimestamp":"MEYCIQCyp/NZoVI8yvRDLu2BOzp3JoiFqnqocPUbOtA+VL5PSwIhAJfUyTYvcn37LxpNmI7eeHBSHBheOgB/VjMTUhzVpPcI"},"inclusionProof":{"logIndex":"2563504369","rootHash":"C6kJzkwoQVFfkQM1lzptHJb5ibiMMZY8KF5XfeNElWo=","treeSize":"2563504385","hashes":["oqCUF1rttonrdb+ibaEJwnIfwLq0FiuPDeUpQfhCCPw=","dTWIhT3F1Umu9/hdhEgzxk+n/siheDVD1ovwY1FVeFY=","OpBSGGOhaxbSPxzCbqQVfYtJdXTOqDVCz4Hn9p0imM0=","/2Se/R2Ua6WpNQG8iO+Y4oFdjx3nJQy4gNyAGvZEWsY=","Nym/ornvKo8MZ5giwX4ZfFHgsIEvIHQdu/HH+e/rPx4=","QB1RfK78hT3zXDQgh1OkMbueiSaHP1swr/AwJ1Si3uY=","njpVdnxJpac3yImvEj6xAzQHIV7i922+7aTEshla5dA=","982Ti2YcjxNSIDqoqQICbLdShw3K72lxUnZ7vZor5YQ=","pwl2Bpv3kHYC4hZC5XZnYhFaL8BId2UkAuFHtuJxG9I=","irM82J8wt0Kvp/QQl8mQ79IUipif2h7AnqKrhBLUDHM=","qAsDfLOILmNZBWGm82Th+uj7D5ykWFqR2sQbgBmVuB4=","rqyOcDFiXFwaZCOKOvo4wdflZrzIQurCkeIseuEsj28=","EqUJ5QItRxbnd5XJ32LbWVCyoUICiWjyd0cFIKbkhSw=","vnaqQ3Lk3n/F/o6Jn7hSa/uSnKQKMdh3Il2GvstJSdM=","ZBcsMYEJF/OXyxEyedqmIZKJYBPZ7njHvz/AMniMIFU=","H2EWTqHaPzZyLGzFNdm1vZITRk/1WU8HnEukaJgoG2E=","oHcOV2H5nfxCFsD3J616h87Eiz+X30EjHngkLoDqRJQ=","HiSowX/eHl/VU2Q+A0EfICMiguqx41ThMqJf2HY+o9M=","itRV5Rvo1MAx7h7FsTOgBX8gRAnu5MLfPmZWuLwhlhA=","eXSLrLqKSxRTixSP/k4YimriB2lufao6trqTrsxxlyg=","SndbMKVtcTenAkwi2JBfGzD+mhexp1qJbRIY+A1JRIU=","xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="],"checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n2563504385\nC6kJzkwoQVFfkQM1lzptHJb5ibiMMZY8KF5XfeNElWo=\n\n— rekor.sigstore.dev wNI9ajBGAiEAgxSKCLu/EB8T3z3aidczp2RYHBkb7Cu6SxxkUg8ftfUCIQCtQfwIWAqaKRhTVWsRtt9V39ZRyEZ0Y6e6AVLFPWCp+g==\n"}},"canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIwMjc2Yjc4OWU0MDQwNzYyOTAwNGI2ZTRmMmI1NDhjMGU2Zjg5NzkyNzlhMjNjYzIxNDNlOTg5MGIxOGNiODkwIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUMxZWNXbGdrK25FK000TnNpWStYUlhmNC9pS2N0cDlyWndGN05LWW5wTnp3SWdVSmN4N3Q4U1hheWZZTlZnZU1TUlRjemU5YStndTh4L0hRRDFPVWdhMmo0PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFpWRU5EUW5WcFowRjNTVUpCWjBsVlpuaHBlSEZJUVdOdlZucEZOSGxyY0V0aU5WaFBWUzl6TmpsRmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDlVUVhsTlZFbDRUbnBOZDFkb1kwNU5hbGwzVDFSQmVVMVVTWGxPZWsxM1YycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZPZUU1eFJtSXlhR05LYmxWU2RUTnNhWEJVV0hkNWIwVnlhR3BuTW1nNE1WQlFjVFFLZVRsWVNXdElZbXNyYkdOUlNFSnlOME5aUnpGMFdXTjNiVWt4SzNaNVRITnVPRlEyUnpKbGRqZDZTUzkxVlN0NWVFdFBRMEpuWTNkbloxbEVUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZ5VkVWNkNubE9Oa0ZMZFZobWVWbDFPRlpSZWxaV1ZtUnZXbFp6ZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJKM1dVUldVakJTUVZGSUwwSkhWWGRaTkZwb1lVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb01Wb3laSEJpYldSdFdWZE9iQXBNTW5Sc1kyMDFiR0pJVFhSWk1qbDBZbGhXZFdGWVVqVk1lVFZ1WVZoU2IyUlhTWFprTWpsNVlUSmFjMkl6WkhwTU1rb3hZVmQ0YTB4WE1XaFplVFUxQ2xsWE1YTlJTRXBzV201TmRtRkhWbWhhU0UxMllsZEdjR0pxUVRWQ1oyOXlRbWRGUlVGWlR5OU5RVVZDUWtOMGIyUklVbmRqZW05MlRETlNkbUV5Vm5VS1RHMUdhbVJIYkhaaWJrMTFXakpzTUdGSVZtbGtXRTVzWTIxT2RtSnVVbXhpYmxGMVdUSTVkRTFDT0VkRGFYTkhRVkZSUW1jM09IZEJVVWxGUlZoa2RncGpiWFJ0WWtjNU0xZ3lVbkJqTTBKb1pFZE9iMDFFV1VkRGFYTkhRVkZSUW1jM09IZEJVVTFGUzBSTk5FNXFRVFZhUjFFeFRrUm9hRTE2VlhoYVZFRXlDazF0UlRGUFJFVjNXV3BTYTA1WFRURk5SRVY0VFZkRk5VNVhWVEZQUkdkM1IzZFpTMHQzV1VKQ1FVZEVkbnBCUWtKQlVVNVJibFp3WWtkUlowdEhNV2dLV1RBNVZFdFVRWEpDWjI5eVFtZEZSVUZaVHk5TlFVVkdRa0l4YjJSWFpHNWhWelZ1V20xR2FscFRPWEphV0VwMVdsZDRla3hYVG5aaVZ6RXhZbTFzTUFwbFZFRmtRbWR2Y2tKblJVVkJXVTh2VFVGRlIwSkJPWGxhVjFwNlRESm9iRmxYVW5wTU1qRm9ZVmMwZDA5M1dVdExkMWxDUWtGSFJIWjZRVUpEUVZGMENrUkRkRzlrU0ZKM1kzcHZka3d6VW5aaE1sWjFURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxSVJVY0tRMmx6UjBGUlVVSm5OemgzUVZGclJWbDNlR2hoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiQXBqYlRWc1lraE5kRmt5T1hSaVdGWjFZVmhTTlV4NU5XNWhXRkp2WkZkSmRtUXlPWGxoTWxwellqTmtla3d5U2pGaFYzaHJURmN4YUZsNU5UVlpWekZ6Q2xGSVNteGFiazEyWVVkV2FGcElUWFppVjBad1ltcEJORUpuYjNKQ1owVkZRVmxQTDAxQlJVdENRMjlOUzBSTk5FNXFRVFZhUjFFeFRrUm9hRTE2VlhnS1dsUkJNazF0UlRGUFJFVjNXV3BTYTA1WFRURk5SRVY0VFZkRk5VNVhWVEZQUkdkM1NGRlpTMHQzV1VKQ1FVZEVkbnBCUWtOM1VWQkVRVEZ1WVZoU2J3cGtWMGwwWVVjNWVtUkhWbXROUlVGSFEybHpSMEZSVVVKbk56aDNRVkYzUlUxbmQzZGhTRkl3WTBoTk5reDVPVzVoV0ZKdlpGZEpkVmt5T1hSTU1tZ3hDbG95WkhCaWJXUnRXVmRPYkV3eWRHeGpiVFZzWWtoTmRGa3lPWFJpV0ZaMVlWaFNOVTFFWjBkRGFYTkhRVkZSUW1jM09IZEJVVEJGUzJkM2IwMTZaeklLVFVSc2ExcEVWVEJQUjBWNlRsUkdiRTFFV1hsWlZGVTBUVlJDYVU1SFVURlplbFYzVFZSRmVGbFVhekZhVkZVMFQwUkJaa0puYjNKQ1owVkZRVmxQTHdwTlFVVlBRa0pGVFVRelNteGFiazEyWVVkV2FGcElUWFppVjBad1ltcEJZVUpuYjNKQ1owVkZRVmxQTDAxQlJWQkNRWGROUTJwRmQwNTZSVEJPZWxVeENrMXFhM2RNWjFsTFMzZFpRa0pCUjBSMmVrRkNSVUZSWjBSQ05XOWtTRkozWTNwdmRrd3laSEJrUjJneFdXazFhbUl5TUhaaFNGWnVXakpzZFZveVdtZ0tXVEpWZDBkQldVdExkMWxDUWtGSFJIWjZRVUpGVVZGTFJFRm5lVTVVWTNsTlJHTXdUWHBDZUVKbmIzSkNaMFZGUVZsUEwwMUJSVk5DUjAxTldWZG9NQXBrU0VKNlQyazRkbG95YkRCaFNGWnBURzFPZG1KVE9XOWtWMlJ1WVZjMWJscHRSbXBhVXpseVdsaEtkVnBYZUhwTVYwNTJZbGN4TVdKdGJEQmxVemgxQ2xveWJEQmhTRlpwVEROa2RtTnRkRzFpUnprelkzazVhV1JYYkhOYVF6RjBXVmROZFdWWFJuUmlSVUo1V2xkYWVrd3lhR3haVjFKNlRESXhhR0ZYTkhjS1QwRlpTMHQzV1VKQ1FVZEVkbnBCUWtWM1VYRkVRMmQ2VDBSWmQwOVhVbXRPVkZFMFdWUk5NVTFYVlhkT2FrcG9UbFJuZUUxSFNUQmFSRlpxVGxSQmVBcE5WRVpvVDFSV2JFNVVaelJOUTBWSFEybHpSMEZSVVVKbk56aDNRVkpSUlVWM2QxSmtNamw1WVRKYWMySXpaR1phUjJ4NlkwZEdNRmt5WjNkYVFWbExDa3QzV1VKQ1FVZEVkbnBCUWtaUlVsZEVSbEp2WkVoU2QyTjZiM1pNTW1Sd1pFZG9NVmxwTldwaU1qQjJZVWhXYmxveWJIVmFNbHBvV1RKVmRtRXlWbmtLWW0xV2MyTjVNV3BpTWpGMFpGYzFjR1JJYTNaWlYwNHdZVmM1ZFdONU9YbGtWelY2VEhwTmVrNXFTVEpOYWxrelQxUkpkMHd5UmpCa1IxWjBZMGhTZWdwTWVrVjNSbWRaUzB0M1dVSkNRVWRFZG5wQlFrWm5VVWxFUVZwM1pGZEtjMkZYVFhkU1oxbExTM2RaUWtKQlIwUjJla0ZDUjBGUk5FUkVXbmxhV0VKMkNrOXRhREZhTW1Sd1ltMWtiVmxYVG14TU1uUnNZMjAxYkdKSVRYUlpNamwwWWxoV2RXRllValZQYmtwc1dtcHdlVnBYV25wTU1taHNXVmRTZWt3eU1XZ0tZVmMwZDJkWmMwZERhWE5IUVZGUlFqRnVhME5DUVVsRlpsRlNOMEZJYTBGa2QwUmtVRlJDY1hoelkxSk5iVTFhU0doNVdscDZZME52YTNCbGRVNDBPQXB5Wml0SWFXNUxRVXg1Ym5WcVowRkJRV0ZDYVVSWkszTkJRVUZGUVhkQ1NVMUZXVU5KVVVSRlpsbHBVWGd4UWpoRGFVTmpOMkpMVlRjNGNYaFlaa1ZtQ2pkME1qQklNVUY1ZEdReWJrYzBNREF6WjBsb1FWQjFjV0Z2YTBaUVRGUjBWWGx6YUdGUllVTjFXbnBuT0hkR05uVlNVbEJaVjJsU05uWkNTbEpsUTFRS1RVRnZSME5EY1VkVFRUUTVRa0ZOUkVFeVkwRk5SMUZEVFVoekwweHBiR1p4UVcxVllrdEhjR0ZvU1haYVMwWndlR292Y2xSd1dqWjZaMWh0VW1wQlpBcHpNamRqTkhsbFVrOVpNalZSUmtadFNHaDRXV3B6V0ZCMmQwbDNZU3M0V0Vob2NtZHNlbkUxVms4Mk1scFhOMlJhYW5Rd1JFVk9OMUpzZDBwcVJESk1DakF6ZFd0UlJscHBlRE5WVGxsTVZEbGxiMWRzV2xSdVpFaDZXR2NLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}],"timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyTADAgEAMIICwAYJKoZIhvcNAQcCoIICsTCCAq0CAQMxDTALBglghkgBZQMEAgEwgbcGCyqGSIb3DQEJEAEEoIGnBIGkMIGhAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgwi4Ourbeso3APxJmIPJ4q71ob/BiemrQC6dLfkiaXB8CFHTWdaSbzcBiGvi2YQwwuRqNwhCnGA8yMDI2MDkwMjEyMTczMVowAwIBAaAypDAwLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2GgADGCAdswggHXAgEBMFEwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUOhNULwyQYe68wUMvy4qOiyojiwwwCwYJYIZIAWUDBAIBoIH8MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjYwOTAyMTIxNzMxWjAvBgkqhkiG9w0BCQQxIgQg0YVmlO148L3o7kfCmu3dwoUyCC7Jp2rf3E4CupI7I2cwgY4GCyqGSIb3DQEJEAIvMX8wfTB7MHkEIIX5J7wHq2LKw7RDVsEO/IGyxog/2nq55thw2dE6zQW3MFUwPaQ7MDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAoGCCqGSM49BAMCBGcwZQIwSB3y2j3eQi3qd0lXPPy5lgxcDKFofiqihbIcbOmDFEcnXxabUNU9/Ahm7IgDW/ZmAjEA4kVbIUkceWKn5ZIAMkP6Wtac0e3YP45kwBxHHI87u3oK362q0/jK2scaz5JwZK6f"}]}},"messageSignature":{"messageDigest":{"algorithm":"SHA2_256","digest":"Ana3ieQEB2KQBLbk8rVIwOb4l5J5ojzCFD6YkLGMuJA="},"signature":"MEUCIQC1ecWlgk+nE+M4NsiY+XRXf4/iKctp9rZwF7NKYnpNzwIgUJcx7t8SXayfYNVgeMSRTcze9a+gu8x/HQD1OUga2j4="}}
 
1
+ {"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json","verificationMaterial":{"certificate":{"rawBytes":"MIIHQjCCBsigAwIBAgIUXXFpFj5dR4nUY3PfWGOtm4Ms/yswCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYxMDE0MDMzNDEzWhcNMjYxMDE0MDM0NDEzWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkcCR1twY8rgoRQgRqaDbk+22mTT/G5y+I0b2o61KbnutxYGAkpesiqpVaW6zrP8c6hCyk4Lb5ufLM27SfMYBxqOCBecwggXjMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNVHSMEGDAWgBTf0+nPViQRlvmo2OkoVaLGLhhkPzBvBgNVHREBAf8EZTBjhmFodHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkvLmdpdGh1Yi93b3JrZmxvd3MvYnVpbGQtbWFjLnlhbWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wHwYKKwYBBAGDvzABAgQRd29ya2Zsb3dfZGlzcGF0Y2gwNgYKKwYBBAGDvzABAwQoNWQ3YjZlN2U4NmY1NDMzM2QwNDI4YzcxNGRkNDE5YTY2OGU2Mjk3ZDAbBgorBgEEAYO/MAEEBA1CdWlsZCAobWFjT1MpMCsGCisGAQQBg78wAQUEHWh1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjA7BgorBgEEAYO/MAEIBC0MK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wcQYKKwYBBAGDvzABCQRjDGFodHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkvLmdpdGh1Yi93b3JrZmxvd3MvYnVpbGQtbWFjLnlhbWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoNWQ3YjZlN2U4NmY1NDMzM2QwNDI4YzcxNGRkNDE5YTY2OGU2Mjk3ZDAdBgorBgEEAYO/MAELBA8MDWdpdGh1Yi1ob3N0ZWQwQAYKKwYBBAGDvzABDAQyDDBodHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkwOAYKKwYBBAGDvzABDQQqDCg1ZDdiNmU3ZTg2ZjU0MzMzZDA0MjhjNzE0ZGQ0MTlhNjY4ZTYyOTdkMB8GCisGAQQBg78wAQ4EEQwPcmVmcy9oZWFkcy9tYWluMBoGCisGAQQBg78wAQ8EDAwKMTA3MTQ3NTUyOTAuBgorBgEEAYO/MAEQBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZTAYBgorBgEEAYO/MAERBAoMCDI1NzIwNzQzMHEGCisGAQQBg78wARIEYwxhaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLW1hYy55YW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAETBCoMKDVkN2I2ZTdlODZmNTQzMzNkMDQyOGM3MTRkZDQxOWE2NjhlNjI5N2QwIQYKKwYBBAGDvzABFAQTDBF3b3JrZmxvd19kaXNwYXRjaDBkBgorBgEEAYO/MAEVBFYMVGh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS9hY3Rpb25zL3J1bnMvMzg1MDQxMzA2NDUvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzBGBgorBgEEAYO/MAEYBDgMNnJlcG86aHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHk6cmVmOnJlZnMvaGVhZHMvbWFpbjCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABoTh5kB0AAAQDAEcwRQIhANsjw+PSI+3FTwsUNo4EJG5t0AjLi9NoSyiaxWINboeiAiA39lvrqbqqK9QSwqkcuiIS/zXozDyG6y86+it92EC5BzAKBggqhkjOPQQDAwNoADBlAjEA5ot8iS45jSRz8rVgtLIZLWmL3GjbQJA4TtgCQ8usWuvp+KjGrrcUswJjmbQVW21hAjBw6TyHs9QaXswJ4A1fruABEHDUPL66AZ66at45fUZKYmhQYk8KDDYsWDpWFBnOY4o="},"tlogEntries":[{"logIndex":"3248362763","logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="},"kindVersion":{"kind":"hashedrekord","version":"0.0.1"},"integratedTime":"1791948853","inclusionPromise":{"signedEntryTimestamp":"MEQCIFZ2eQttdCpdFocZW27/RABynxfklCDs5B0fXwRByuOkAiA4T4cbSrTz1EvtWXUrnnEB+zP9LI1FnpOMBtXHmJ/m3g=="},"inclusionProof":{"logIndex":"3126458501","rootHash":"KG8B1Njo4weySLhjF4KwL+QCTLaPmedQPG7yuhMEUhE=","treeSize":"3126458528","hashes":["XZ5oZUoeZujKrhqEEHLlLDuLZtO/pawUiZhtS4VVxVY=","+di6AVxn2BuJ9F1UR2JxW8DWCSKmw8ECLppSJTvYV7Y=","atZUuvmphkDnfXqme/60sJRigx9oX+HpIw+3KpEpJJI=","MN0IpddYiEtCvxvMo2ySq2iW2dNsn2Gvz1tKtFr9St0=","CwB9cYQ1N7iaRvPqIPdBv8Aa94KZfTZ2X30OAz4tHWw=","sDhqg4ggJrGYjJo1/fhgb1NyhtMkAFd5uRw3Ly4EbjI=","5m6EpI8tdpU/f/dAg82Z0NyOapH3Y79BMEemTXSe/uE=","xAezYe4y8AC8w1kxznY3VvWkMI5ZrBpKRLJQ+g6AZUo=","wmiUdaxh+aRNstuEMicffUeQbRU9aJNH9uJggGIyE3w=","uvVdtoNVpwlWFYWxGWmQmDqNieUlTnEDkrfhKEQ+qdg=","wQpKnRo/8I3V7Obbx0N+rKjCIDCeAUS8OZtjYUo/2bI=","CtcIVoI3XLRy3l6ptbqkSasIzLKqUa/s5avVFmCqEpM=","aC90p6Ahh9y8gI/eugOgvu3iOqxJnuR0BmbUL5vdewI=","6+XSlYENbRTsCa1QIVPcpfSDgUH1+EtyTUVFmbfQRjA=","ynO2ldZilpApxyC2LzVm34kdR9cQdxul5YLPLAqv7lg=","wk2tYV/zs2FUIlhL9YQeUw8UqKbqhapvz1h7jtdeQWw=","gg9GNApNke3+zNhl4tsWtmIycCFrOMCB3lys6XuSQNQ=","NlOclldmKPA1tMKIskqHAwuQDYHp31YwpK+OOMrMccc=","qxzHanAzz57SDdmJe0B7bJK72NTIBbwEMGBBKvDOROw=","xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="],"checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n3126458528\nKG8B1Njo4weySLhjF4KwL+QCTLaPmedQPG7yuhMEUhE=\n\n— rekor.sigstore.dev wNI9ajBFAiA0fmbxrMjlxHJ6olB3kEBOckMzWeYIxFCu/xpFSBQuVgIhAPGPR6CcJQQKnDOQG9bkY124BC+xVW8UZu/hKZxv975Z\n"}},"canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI4N2U5N2U1ZjNkM2Q2MDFkMTVlODNmZDIyMWIyZjU0N2NlODg5MzQzOTQ1YzgyN2UzMWNjNmY4YmUxMjY0NTg0In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUNNTUxiamdPNHEvZ0RPWGJrTlgwL3h5MHRzK1pkS3JRU3dXN0E5L2Z0WXp3SWhBTDRLT2NoVHEzT3o0T011RUdvZjdOalBtMVU0azBKd1RBckJjemdFNmg0diIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFJha05EUW5OcFowRjNTVUpCWjBsVldGaEdjRVpxTldSU05HNVZXVE5RWmxkSFQzUnRORTF6TDNsemQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFplRTFFUlRCTlJFMTZUa1JGZWxkb1kwNU5hbGw0VFVSRk1FMUVUVEJPUkVWNlYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZyWTBOU01YUjNXVGh5WjI5U1VXZFNjV0ZFWW1zck1qSnRWRlF2UnpWNUswa3dZaklLYnpZeFMySnVkWFI0V1VkQmEzQmxjMmx4Y0ZaaFZ6WjZjbEE0WXpab1EzbHJORXhpTlhWbVRFMHlOMU5tVFZsQ2VIRlBRMEpsWTNkbloxaHFUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXWkNaMDVXU0ZOTlJVZEVRVmRuUWxSbUNqQXJibEJXYVZGU2JIWnRiekpQYTI5V1lVeEhUR2hvYTFCNlFuWkNaMDVXU0ZKRlFrRm1PRVZhVkVKcWFHMUdiMlJJVW5kamVtOTJUREprY0dSSGFERUtXV2sxYW1JeU1IWmhTRlp1V2pKc2RWb3lXbWhaTWxWMllUSldlV0p0Vm5OamVURnFZakl4ZEdSWE5YQmtTR3QyVEcxa2NHUkhhREZaYVRrellqTktjZ3BhYlhoMlpETk5kbGx1Vm5CaVIxRjBZbGRHYWt4dWJHaGlWM2hCWTIxV2JXTjVPVzlhVjBaclkzazVkRmxYYkhWTlJHdEhRMmx6UjBGUlVVSm5OemgzQ2tGUlJVVkxNbWd3WkVoQ2VrOXBPSFprUnpseVdsYzBkVmxYVGpCaFZ6bDFZM2sxYm1GWVVtOWtWMG94WXpKV2VWa3lPWFZrUjFaMVpFTTFhbUl5TUhjS1NIZFpTMHQzV1VKQ1FVZEVkbnBCUWtGblVWSmtNamw1WVRKYWMySXpaR1phUjJ4NlkwZEdNRmt5WjNkT1oxbExTM2RaUWtKQlIwUjJla0ZDUVhkUmJ3cE9WMUV6V1dwYWJFNHlWVFJPYlZreFRrUk5lazB5VVhkT1JFazBXWHBqZUU1SFVtdE9SRVUxV1ZSWk1rOUhWVEpOYW1zeldrUkJZa0puYjNKQ1owVkZDa0ZaVHk5TlFVVkZRa0V4UTJSWGJITmFRMEZ2WWxkR2FsUXhUWEJOUTNOSFEybHpSMEZSVVVKbk56aDNRVkZWUlVoWGFERmFNbVJ3WW0xa2JWbFhUbXdLVERKMGJHTnROV3hpU0UxMFdUSTVkR0pZVm5WaFdGSTFUVUl3UjBOcGMwZEJVVkZDWnpjNGQwRlJXVVZFTTBwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0FwaWFrRTNRbWR2Y2tKblJVVkJXVTh2VFVGRlNVSkRNRTFMTW1nd1pFaENlazlwT0haa1J6bHlXbGMwZFZsWFRqQmhWemwxWTNrMWJtRllVbTlrVjBveENtTXlWbmxaTWpsMVpFZFdkV1JETldwaU1qQjNZMUZaUzB0M1dVSkNRVWRFZG5wQlFrTlJVbXBFUjBadlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5Xb0tZakl3ZG1GSVZtNWFNbXgxV2pKYWFGa3lWWFpoTWxaNVltMVdjMk41TVdwaU1qRjBaRmMxY0dSSWEzWk1iV1J3WkVkb01WbHBPVE5pTTBweVdtMTRkZ3BrTTAxMldXNVdjR0pIVVhSaVYwWnFURzVzYUdKWGVFRmpiVlp0WTNrNWIxcFhSbXRqZVRsMFdWZHNkVTFFWjBkRGFYTkhRVkZSUW1jM09IZEJVVzlGQ2t0bmQyOU9WMUV6V1dwYWJFNHlWVFJPYlZreFRrUk5lazB5VVhkT1JFazBXWHBqZUU1SFVtdE9SRVUxV1ZSWk1rOUhWVEpOYW1zeldrUkJaRUpuYjNJS1FtZEZSVUZaVHk5TlFVVk1Ra0U0VFVSWFpIQmtSMmd4V1dreGIySXpUakJhVjFGM1VVRlpTMHQzV1VKQ1FVZEVkbnBCUWtSQlVYbEVSRUp2WkVoU2R3cGplbTkyVERKa2NHUkhhREZaYVRWcVlqSXdkbUZJVm01YU1teDFXakphYUZreVZYWmhNbFo1WW0xV2MyTjVNV3BpTWpGMFpGYzFjR1JJYTNkUFFWbExDa3QzV1VKQ1FVZEVkbnBCUWtSUlVYRkVRMmN4V2tSa2FVNXRWVE5hVkdjeVdtcFZNRTE2VFhwYVJFRXdUV3BvYWs1NlJUQmFSMUV3VFZSc2FFNXFXVFFLV2xSWmVVOVVaR3ROUWpoSFEybHpSMEZSVVVKbk56aDNRVkUwUlVWUmQxQmpiVlp0WTNrNWIxcFhSbXRqZVRsMFdWZHNkVTFDYjBkRGFYTkhRVkZSUWdwbk56aDNRVkU0UlVSQmQwdE5WRUV6VFZSUk0wNVVWWGxQVkVGMVFtZHZja0puUlVWQldVOHZUVUZGVVVKRFFVMUliV2d3WkVoQ2VrOXBPSFphTW13d0NtRklWbWxNYlU1MllsTTViMlJYWkc1aFZ6VnVXbTFHYWxwVVFWbENaMjl5UW1kRlJVRlpUeTlOUVVWU1FrRnZUVU5FU1RGT2VrbDNUbnBSZWsxSVJVY0tRMmx6UjBGUlVVSm5OemgzUVZKSlJWbDNlR2hoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiQXBqYlRWc1lraE5kRmt5T1hSaVdGWjFZVmhTTlV4NU5XNWhXRkp2WkZkSmRtUXlPWGxoTWxwellqTmtla3d5U2pGaFYzaHJURmN4YUZsNU5UVlpWekZ6Q2xGSVNteGFiazEyWVVkV2FGcElUWFppVjBad1ltcEJORUpuYjNKQ1owVkZRVmxQTDAxQlJWUkNRMjlOUzBSV2EwNHlTVEphVkdSc1QwUmFiVTVVVVhvS1RYcE9hMDFFVVhsUFIwMHpUVlJTYTFwRVVYaFBWMFV5VG1wb2JFNXFTVFZPTWxGM1NWRlpTMHQzV1VKQ1FVZEVkbnBCUWtaQlVWUkVRa1l6WWpOS2NncGFiWGgyWkRFNWEyRllUbmRaV0ZKcVlVUkNhMEpuYjNKQ1owVkZRVmxQTDAxQlJWWkNSbGxOVmtkb01HUklRbnBQYVRoMldqSnNNR0ZJVm1sTWJVNTJDbUpUT1c5a1YyUnVZVmMxYmxwdFJtcGFVemx5V2xoS2RWcFhlSHBNVjA1MllsY3hNV0p0YkRCbFV6bG9XVE5TY0dJeU5YcE1NMG94WW01TmRrMTZaekVLVFVSUmVFMTZRVEpPUkZWMldWaFNNRnBYTVhka1NFMTJUVlJCVjBKbmIzSkNaMFZGUVZsUEwwMUJSVmRDUVdkTlFtNUNNVmx0ZUhCWmVrSkhRbWR2Y2dwQ1owVkZRVmxQTDAxQlJWbENSR2ROVG01S2JHTkhPRFpoU0ZadVdqSnNkVm95V21oWk1sVjJZVEpXZVdKdFZuTmplVEZxWWpJeGRHUlhOWEJrU0dzMkNtTnRWbTFQYmtwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVEwSnBaMWxMUzNkWlFrSkJTRmRsVVVsRlFXZFNPRUpJYjBGbFFVSXlRVTR3T1UxSGNrY0tlSGhGZVZsNGEyVklTbXh1VG5kTGFWTnNOalF6YW5sMEx6UmxTMk52UVhaTFpUWlBRVUZCUW05VWFEVnJRakJCUVVGUlJFRkZZM2RTVVVsb1FVNXphZ3AzSzFCVFNTc3pSbFIzYzFWT2J6UkZTa2MxZERCQmFreHBPVTV2VTNscFlYaFhTVTVpYjJWcFFXbEJNemxzZG5KeFluRnhTemxSVTNkeGEyTjFhVWxUQ2k5NldHOTZSSGxITm5rNE5pdHBkRGt5UlVNMVFucEJTMEpuWjNGb2EycFBVRkZSUkVGM1RtOUJSRUpzUVdwRlFUVnZkRGhwVXpRMWFsTlNlamh5Vm1jS2RFeEpXa3hYYlV3elIycGlVVXBCTkZSMFowTlJPSFZ6VjNWMmNDdExha2R5Y21OVmMzZEthbTFpVVZaWE1qRm9RV3BDZHpaVWVVaHpPVkZoV0hOM1NnbzBRVEZtY25WQlFrVklSRlZRVERZMlFWbzJObUYwTkRWbVZWcExXVzFvVVZsck9FdEVSRmx6VjBSd1YwWkNiazlaTkc4OUNpMHRMUzB0UlU1RUlFTkZVbFJKUmtsRFFWUkZMUzB0TFMwSyJ9fX19"}],"timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyjADAgEAMIICwQYJKoZIhvcNAQcCoIICsjCCAq4CAQMxDTALBglghkgBZQMEAgEwgbgGCyqGSIb3DQEJEAEEoIGoBIGlMIGiAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgF4SpBSNGyBeEYJqteeo50IYcyY5Q9lMnGHrjBCLJjpMCFQDmg0T/8XI3v4at3VCSh0/D+uFoCBgPMjAyNjEwMTQwMzM0MTNaMAMCAQGgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHbMIIB1wIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MTAxNDAzMzQxM1owLwYJKoZIhvcNAQkEMSIEIGpGGMGmFwKUcv1a+5h9MMqVB3db07jePJsvxdNLvvB6MIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCCF+Se8B6tiysO0Q1bBDvyBssaIP9p6uebYcNnROs0FtzBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQ6E1QvDJBh7rzBQy/Lio6LKiOLDDAKBggqhkjOPQQDAgRnMGUCMFOzjijqD2rZr2NJ1WuJy6Y56y2r0HPi4WkqxKhX+8fNrTHYeQwWpyoWHSZLUtmUnAIxAKFu92gWQ8QRpNkjtbVXUX+vNjrqSrjnWodQdAjosTwc4AD3fdRalfBSH0S76O7Dnw=="}]}},"messageSignature":{"messageDigest":{"algorithm":"SHA2_256","digest":"h+l+Xz09YB0V6D/SIbL1R86Ik0OUXIJ+Mcxvi+EmRYQ="},"signature":"MEYCIQCMMLbjgO4q/gDOXbkNX0/xy0ts+ZdKrQSwW7A9/ftYzwIhAL4KOchTq3Oz4OMuEGof7NjPm1U4k0JwTArBczgE6h4v"}}
build/torch214-metal-aarch64-darwin/__init__.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ggml's flash attention as a torch op, and as a `transformers` attention implementation.
2
+
3
+ This wraps `ggml_attn_ext` out of llama.cpp's Metal backend -- the same kernel llama.cpp runs. ggml
4
+ picks between two implementations of that op by query count (`ne01 < 20` selects the *vector* path, wider
5
+ `q` the *tiled* one); both are ported, so decode and prefill both run on ggml's kernels. Head-dim pairs
6
+ upstream has no template for are refused, not silently served by torch's attention -- ask
7
+ `supports_flash_attn` before selecting this implementation.
8
+ """
9
+
10
+ import os
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+
16
+ # A local (non-nix) build leaves the metallib on disk beside this module instead of embedding it, and
17
+ # `ggml_dispatch.mm` looks it up through this variable when nothing is embedded. Set before the extension
18
+ # is imported, and never over an existing value, so an explicit choice still wins.
19
+ _METALLIB = Path(__file__).parent / "ggml-metal.metallib"
20
+ if _METALLIB.is_file():
21
+ os.environ.setdefault("GGML_ATTN_METALLIB", str(_METALLIB))
22
+
23
+ from ._ops import add_op_namespace_prefix, ops # noqa: E402
24
+
25
+
26
+ def flash_attn(
27
+ q: torch.Tensor,
28
+ k: torch.Tensor,
29
+ v: torch.Tensor,
30
+ mask: torch.Tensor | None = None,
31
+ scale: float | None = None,
32
+ sinks: torch.Tensor | None = None,
33
+ softcap: float = 0.0,
34
+ ) -> torch.Tensor:
35
+ """Flash attention through ggml's vector kernel — the path upstream picks for decode.
36
+
37
+ Args:
38
+ q: `(n_seqs, n_heads, n_q, head_dim)`.
39
+ k, v: `(n_seqs, n_heads_kv, n_kv, head_dim)`. Grouped-query attention is native, so do **not**
40
+ expand them to `n_heads` first — that copy is exactly what this avoids. An f16 cache is read
41
+ as f16, as llama.cpp reads its default cache; other dtypes are read as f32.
42
+ mask: `(n_seqs, 1, n_q, n_kv)` additive mask, or None. Cast to f16 internally, as the kernel
43
+ requires. **A None mask means attend to everything**: ggml has no `is_causal` argument, so
44
+ causality has to arrive as a mask. `flash_attn_forward` builds one when it must.
45
+ scale: softmax scale; defaults to `head_dim ** -0.5`.
46
+ sinks: attention sinks, one logit per query head that joins each row's softmax and takes no
47
+ value (gpt-oss's `s_aux`); upstream's `ggml_flash_attn_ext_add_sinks`.
48
+ softcap: logit softcapping, `softcap * tanh(scores / softcap)` before the softmax (Gemma 2's
49
+ `attn_logit_softcapping`); 0 for none.
50
+
51
+ Returns:
52
+ `(n_seqs, n_q, n_heads, head_dim)` f32 — tokens before heads, which is what SDPA gives after its
53
+ own `.transpose(1, 2)`, so a caller usually wants precisely this and no further permute.
54
+
55
+ Ask `supports_flash_attn` first: it answers for whichever of upstream's two paths the shape selects.
56
+ """
57
+ if scale is None:
58
+ scale = q.shape[-1] ** -0.5
59
+ return ops.flash_attn(q, k, v, mask, scale, sinks, softcap)
60
+
61
+
62
+ def supports_flash_attn(n_q: int, head_dim_k: int, head_dim_v: int) -> bool:
63
+ """Whether this build has a flash-attention kernel for these shapes.
64
+
65
+ Upstream picks its vector kernel for `n_q < 20` and its tiled one above that; both are ported, so
66
+ what is declined is head-dim pairs neither has a template for, and `head_dim_k < head_dim_v`.
67
+ """
68
+ return ops.supports_flash_attn(n_q, head_dim_k, head_dim_v)
69
+
70
+
71
+ @torch.library.register_fake(add_op_namespace_prefix("flash_attn"))
72
+ def _(q, k, v, mask, scale, sinks=None, softcap=0.0):
73
+ n_seqs, n_heads, n_q, _ = q.shape
74
+ return q.new_empty((n_seqs, n_q, n_heads, v.shape[-1]))
75
+
76
+
77
+ __all__ = ["flash_attn", "supports_flash_attn", "flash_attn_forward"]
78
+
79
+
80
+ _CAUSAL_CACHE: dict = {}
81
+
82
+
83
+ def _causal_mask(query: torch.Tensor, n_kv: int) -> torch.Tensor:
84
+ """The additive causal mask ggml requires when the caller supplied none.
85
+
86
+ `ggml_attn_ext` takes no `is_causal` argument: in ggml the mask *is* the causality, and a null mask
87
+ means attend to everything. `transformers` is entitled to hand us None -- `sdpa` carries causality in its
88
+ own `is_causal` flag instead, so the mask is dropped as an optimisation -- and that flag does not reach an
89
+ attention function at all. Rebuilding the mask here restores what was dropped; without it, any `n_q > 1`
90
+ call attends to future positions, which is silent: the logits move but greedy text often does not.
91
+
92
+ Lower-right aligned, matching `sdpa`'s convention when a cache is in play: the `n_q` queries are the last
93
+ `n_q` of the `n_kv` positions, so query `i` may see key `j <= i + (n_kv - n_q)`.
94
+ """
95
+ n_q = query.shape[2]
96
+ key = (n_q, n_kv, str(query.device))
97
+ cached = _CAUSAL_CACHE.get(key)
98
+ if cached is None:
99
+ # f16, not the query dtype: the kernel casts an f32 mask to f16 anyway, and at prefill widths
100
+ # that cast is a second n_q*n_kv allocation per layer per forward -- enough to cost more than
101
+ # the kernel gains. One entry, because a generation reuses one prefill shape and then decodes.
102
+ future = torch.ones(n_q, n_kv, dtype=torch.bool, device=query.device).triu(1 + n_kv - n_q)
103
+ cached = torch.zeros(n_q, n_kv, dtype=torch.float16, device=query.device).masked_fill_(
104
+ future, float("-inf")
105
+ )[None, None]
106
+ _CAUSAL_CACHE.clear()
107
+ _CAUSAL_CACHE[key] = cached
108
+ return cached
109
+
110
+
111
+ def flash_attn_forward(
112
+ module: torch.nn.Module,
113
+ query: torch.Tensor,
114
+ key: torch.Tensor,
115
+ value: torch.Tensor,
116
+ attention_mask: torch.Tensor | None = None,
117
+ scaling: float | None = None,
118
+ dropout: float = 0.0,
119
+ **kwargs,
120
+ ) -> tuple[torch.Tensor, None]:
121
+ """Attention entry point shaped for `transformers`' attention interface.
122
+
123
+ Selected with `attn_implementation="<repo>:flash_attn_forward"`, which is how a kernel provides an
124
+ attention implementation without the caller reaching into `ALL_ATTENTION_FUNCTIONS`.
125
+
126
+ Both of upstream's paths are ported -- the vector kernel for `n_q < 20`, the tiled one above it -- so
127
+ decode and prefill both run on ggml's kernels. A head-dim pair neither has a template for raises, the
128
+ way `flash_attention_2` and the block-sparse kernels do, rather than quietly running torch's attention
129
+ under a name that promises ggml's: what upstream instantiates does not depend on the input, so a model
130
+ whose head dims are unsupported is unsupported for its whole run, and saying so at the first forward
131
+ beats reporting a speedup that never happened. Grouped-query attention is native to the kernel, so
132
+ `key`/`value` keep their own head count.
133
+ """
134
+ if scaling is None:
135
+ scaling = query.shape[-1] ** -0.5
136
+
137
+ n_q, head_dim_k, head_dim_v = query.shape[2], query.shape[-1], value.shape[-1]
138
+ if not supports_flash_attn(n_q, head_dim_k, head_dim_v):
139
+ raise ValueError(
140
+ f"ggml-attn has no kernel for head_dim {head_dim_k}/{head_dim_v} at {n_q} queries. ggml "
141
+ f"instantiates its attention kernels per head-dim pair, and this build carries the pairs "
142
+ f"upstream provides templates for; `supports_flash_attn(n_q, head_dim_k, head_dim_v)` answers "
143
+ f"for any shape. Use `attn_implementation='sdpa'` for this model."
144
+ )
145
+
146
+ mask = attention_mask
147
+ if mask is not None and mask.dtype == torch.bool:
148
+ # The kernel wants an additive mask; a boolean one says which positions are allowed.
149
+ mask = torch.zeros_like(mask, dtype=query.dtype).masked_fill_(~mask, float("-inf"))
150
+ elif mask is None and n_q > 1:
151
+ mask = _causal_mask(query, key.shape[2])
152
+ # transformers passes gpt-oss's sinks as `s_aux` and Gemma 2's softcapping as `softcap`
153
+ sinks = kwargs.get("s_aux")
154
+ softcap = kwargs.get("softcap") or 0.0
155
+ # ggml writes f32; hand the model back the dtype it computes in
156
+ return flash_attn(query, key, value, mask, scaling, sinks, softcap).to(query.dtype), None
build/torch214-metal-aarch64-darwin/_ggml_attn_metal_5d7b6e7.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4a7f22d893de3ae765267295b0199c9fdb15ea5138ac1eef68d518a79ac1c1e0
3
+ size 9579184
build/torch214-metal-aarch64-darwin/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _ggml_attn_metal_5d7b6e7
3
+ ops = torch.ops._ggml_attn_metal_5d7b6e7
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_ggml_attn_metal_5d7b6e7::{op_name}"
build/torch214-metal-aarch64-darwin/metadata.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "ggml-attn",
3
+ "id": "_ggml_attn_metal_5d7b6e7",
4
+ "version": 1,
5
+ "kernels-minver": "0.14.0",
6
+ "license": "MIT",
7
+ "python-depends": [],
8
+ "kernel-depends": [],
9
+ "backend": {
10
+ "type": "metal"
11
+ },
12
+ "digest": {
13
+ "algorithm": "sha256",
14
+ "files": {
15
+ "__init__.py": "2zbEFDRRtbDKJLS22KAG0/SEWEJycxEgVfkBR2gpo+s=",
16
+ "_ggml_attn_metal_5d7b6e7.abi3.so": "Sn8i2JPeOudlJnKVsBmcn9sV6lE4rB7vaNUYp5rBweA=",
17
+ "_ops.py": "YynNnQ4xi51MpqejOgt86BWJgohmwvhxWXeoS5ptgcM="
18
+ }
19
+ },
20
+ "provenance": {
21
+ "kernel-builder": {
22
+ "version": "0.17.0-dev0",
23
+ "commit": "a7f0afdb29a6a3372b1d47180cc0c182454c5e3b",
24
+ "dirty": false
25
+ },
26
+ "kernel": {
27
+ "commit": "5d7b6e7e86f54333d0428c714dd419a668e6297d",
28
+ "dirty": false
29
+ }
30
+ }
31
+ }
build/torch214-metal-aarch64-darwin/metadata.json.sigstore ADDED
@@ -0,0 +1 @@
 
 
1
+ {"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json","verificationMaterial":{"certificate":{"rawBytes":"MIIHQjCCBsigAwIBAgIURE4B3wmtOJ1gPoD7K8IXnqChsAIwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYxMDE0MDMzNDEyWhcNMjYxMDE0MDM0NDEyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsTlfoUbu/2dmQ61xII0WfAK5H6bKrlqs0IBBoVEX4u+Ysdzs7EYsRD3qdbtq/0wpjYznIcVCmVOcTRfoA6tocqOCBecwggXjMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNVHSMEGDAWgBTf0+nPViQRlvmo2OkoVaLGLhhkPzBvBgNVHREBAf8EZTBjhmFodHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkvLmdpdGh1Yi93b3JrZmxvd3MvYnVpbGQtbWFjLnlhbWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wHwYKKwYBBAGDvzABAgQRd29ya2Zsb3dfZGlzcGF0Y2gwNgYKKwYBBAGDvzABAwQoNWQ3YjZlN2U4NmY1NDMzM2QwNDI4YzcxNGRkNDE5YTY2OGU2Mjk3ZDAbBgorBgEEAYO/MAEEBA1CdWlsZCAobWFjT1MpMCsGCisGAQQBg78wAQUEHWh1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjA7BgorBgEEAYO/MAEIBC0MK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wcQYKKwYBBAGDvzABCQRjDGFodHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkvLmdpdGh1Yi93b3JrZmxvd3MvYnVpbGQtbWFjLnlhbWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoNWQ3YjZlN2U4NmY1NDMzM2QwNDI4YzcxNGRkNDE5YTY2OGU2Mjk3ZDAdBgorBgEEAYO/MAELBA8MDWdpdGh1Yi1ob3N0ZWQwQAYKKwYBBAGDvzABDAQyDDBodHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkwOAYKKwYBBAGDvzABDQQqDCg1ZDdiNmU3ZTg2ZjU0MzMzZDA0MjhjNzE0ZGQ0MTlhNjY4ZTYyOTdkMB8GCisGAQQBg78wAQ4EEQwPcmVmcy9oZWFkcy9tYWluMBoGCisGAQQBg78wAQ8EDAwKMTA3MTQ3NTUyOTAuBgorBgEEAYO/MAEQBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZTAYBgorBgEEAYO/MAERBAoMCDI1NzIwNzQzMHEGCisGAQQBg78wARIEYwxhaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLW1hYy55YW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAETBCoMKDVkN2I2ZTdlODZmNTQzMzNkMDQyOGM3MTRkZDQxOWE2NjhlNjI5N2QwIQYKKwYBBAGDvzABFAQTDBF3b3JrZmxvd19kaXNwYXRjaDBkBgorBgEEAYO/MAEVBFYMVGh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS9hY3Rpb25zL3J1bnMvMzg1MDQxMzA2NDUvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzBGBgorBgEEAYO/MAEYBDgMNnJlcG86aHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHk6cmVmOnJlZnMvaGVhZHMvbWFpbjCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABoTh5jCAAAAQDAEcwRQIgPt/bMzI9H/lPVAK7yNp/284wXM3ekfoTEuxIvb74C8QCIQC0DoV33l6xox7NWlzI+JfQdbwt4WFNU8ddPcFFBI6IjTAKBggqhkjOPQQDAwNoADBlAjBmUvA/W2nUlK9P2W7OvUpTOug0zvMKFIItaKgBuEdL7dDrnZqFLgAsynZHBRIEXT0CMQCOSAlz1sRTwGmOqPDPEJrZFDnObLk///JrFjx68UvK9i0wUG1reKUnb9ReJFg+30w="},"tlogEntries":[{"logIndex":"3248362673","logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="},"kindVersion":{"kind":"hashedrekord","version":"0.0.1"},"integratedTime":"1791948852","inclusionPromise":{"signedEntryTimestamp":"MEUCIQDHxpOZ4S5dFimuhv31xen+2Gaqo4vbKK+kPTFRz5eoLAIgbcUiym+vZ9haA+/EyF7u9QdWLMvDXf+aW4zsRwGdBAw="},"inclusionProof":{"logIndex":"3126458411","rootHash":"UTy88wSRYeJzCNFtC+6EHzQCw9IH/XF00/SAfkYSVnw=","treeSize":"3126458434","hashes":["4YtotRO2+YtluvWVBGh2MzCT14FZ79hfvD2zceIDBWA=","KAPmVYYzAU0UxnPk1RmxXlaIAFee7/BCEFrrC3ntnMg=","gjEj4s9lWU1/NMY1bK98096sXmAo/IRZLdIyuPEUh84=","TIUVaxcfIXoWAke2OptcGvkOc2e828xR15qQLVuLmyA=","bzqc0UXAJEY5j5vMeHHrslTz1c9XagR5rGzxcUJSfgM=","NlbB8IGxDqx9fYnmtXewcFDT9mWL2l6v1LYTi325VhI=","KZecN8cLSrkatGauFoJeVIeXiiTuL1Qav2DDRXb0k30=","5m6EpI8tdpU/f/dAg82Z0NyOapH3Y79BMEemTXSe/uE=","xAezYe4y8AC8w1kxznY3VvWkMI5ZrBpKRLJQ+g6AZUo=","wmiUdaxh+aRNstuEMicffUeQbRU9aJNH9uJggGIyE3w=","uvVdtoNVpwlWFYWxGWmQmDqNieUlTnEDkrfhKEQ+qdg=","wQpKnRo/8I3V7Obbx0N+rKjCIDCeAUS8OZtjYUo/2bI=","CtcIVoI3XLRy3l6ptbqkSasIzLKqUa/s5avVFmCqEpM=","aC90p6Ahh9y8gI/eugOgvu3iOqxJnuR0BmbUL5vdewI=","6+XSlYENbRTsCa1QIVPcpfSDgUH1+EtyTUVFmbfQRjA=","ynO2ldZilpApxyC2LzVm34kdR9cQdxul5YLPLAqv7lg=","wk2tYV/zs2FUIlhL9YQeUw8UqKbqhapvz1h7jtdeQWw=","gg9GNApNke3+zNhl4tsWtmIycCFrOMCB3lys6XuSQNQ=","NlOclldmKPA1tMKIskqHAwuQDYHp31YwpK+OOMrMccc=","qxzHanAzz57SDdmJe0B7bJK72NTIBbwEMGBBKvDOROw=","xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="],"checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n3126458434\nUTy88wSRYeJzCNFtC+6EHzQCw9IH/XF00/SAfkYSVnw=\n\n— rekor.sigstore.dev wNI9ajBEAiAYEqnJXtRd66LYXvSYiLQzc7H75rYgztLHnm0Dl3pIsgIgDC6q6eSlDjwv4S6kiHyrfb4ZgviXx57cFUgfARlEsnw=\n"}},"canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI4MGEyZTU4NmVlOTU0MGY2NjQzNGM2YTA3OTZkYjk1NDQzYWQzMjA3NDk3OWUxMDk4NmRhMDdlYTM1MTlmMjYxIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUNvOHVMeHBIY1FTQnhVN2xMQmU5eW9YalpaZ2s3d256bDN4eUZYMlBhek93SWhBUGR5TFhpcUh5cnp5M1JsRHpJa0JLSnA2ZDhxbk1EVkpTby9MRm1FZWhkdSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFJha05EUW5OcFowRjNTVUpCWjBsVlVrVTBRak4zYlhSUFNqRm5VRzlFTjBzNFNWaHVjVU5vYzBGSmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFplRTFFUlRCTlJFMTZUa1JGZVZkb1kwNU5hbGw0VFVSRk1FMUVUVEJPUkVWNVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZ6Vkd4bWIxVmlkUzh5WkcxUk5qRjRTVWt3VjJaQlN6VklObUpMY214eGN6QkpRa0lLYjFaRldEUjFLMWx6Wkhwek4wVlpjMUpFTTNGa1luUnhMekIzY0dwWmVtNUpZMVpEYlZaUFkxUlNabTlCTm5SdlkzRlBRMEpsWTNkbloxaHFUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXWkNaMDVXU0ZOTlJVZEVRVmRuUWxSbUNqQXJibEJXYVZGU2JIWnRiekpQYTI5V1lVeEhUR2hvYTFCNlFuWkNaMDVXU0ZKRlFrRm1PRVZhVkVKcWFHMUdiMlJJVW5kamVtOTJUREprY0dSSGFERUtXV2sxYW1JeU1IWmhTRlp1V2pKc2RWb3lXbWhaTWxWMllUSldlV0p0Vm5OamVURnFZakl4ZEdSWE5YQmtTR3QyVEcxa2NHUkhhREZaYVRrellqTktjZ3BhYlhoMlpETk5kbGx1Vm5CaVIxRjBZbGRHYWt4dWJHaGlWM2hCWTIxV2JXTjVPVzlhVjBaclkzazVkRmxYYkhWTlJHdEhRMmx6UjBGUlVVSm5OemgzQ2tGUlJVVkxNbWd3WkVoQ2VrOXBPSFprUnpseVdsYzBkVmxYVGpCaFZ6bDFZM2sxYm1GWVVtOWtWMG94WXpKV2VWa3lPWFZrUjFaMVpFTTFhbUl5TUhjS1NIZFpTMHQzV1VKQ1FVZEVkbnBCUWtGblVWSmtNamw1WVRKYWMySXpaR1phUjJ4NlkwZEdNRmt5WjNkT1oxbExTM2RaUWtKQlIwUjJla0ZDUVhkUmJ3cE9WMUV6V1dwYWJFNHlWVFJPYlZreFRrUk5lazB5VVhkT1JFazBXWHBqZUU1SFVtdE9SRVUxV1ZSWk1rOUhWVEpOYW1zeldrUkJZa0puYjNKQ1owVkZDa0ZaVHk5TlFVVkZRa0V4UTJSWGJITmFRMEZ2WWxkR2FsUXhUWEJOUTNOSFEybHpSMEZSVVVKbk56aDNRVkZWUlVoWGFERmFNbVJ3WW0xa2JWbFhUbXdLVERKMGJHTnROV3hpU0UxMFdUSTVkR0pZVm5WaFdGSTFUVUl3UjBOcGMwZEJVVkZDWnpjNGQwRlJXVVZFTTBwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0FwaWFrRTNRbWR2Y2tKblJVVkJXVTh2VFVGRlNVSkRNRTFMTW1nd1pFaENlazlwT0haa1J6bHlXbGMwZFZsWFRqQmhWemwxWTNrMWJtRllVbTlrVjBveENtTXlWbmxaTWpsMVpFZFdkV1JETldwaU1qQjNZMUZaUzB0M1dVSkNRVWRFZG5wQlFrTlJVbXBFUjBadlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5Xb0tZakl3ZG1GSVZtNWFNbXgxV2pKYWFGa3lWWFpoTWxaNVltMVdjMk41TVdwaU1qRjBaRmMxY0dSSWEzWk1iV1J3WkVkb01WbHBPVE5pTTBweVdtMTRkZ3BrTTAxMldXNVdjR0pIVVhSaVYwWnFURzVzYUdKWGVFRmpiVlp0WTNrNWIxcFhSbXRqZVRsMFdWZHNkVTFFWjBkRGFYTkhRVkZSUW1jM09IZEJVVzlGQ2t0bmQyOU9WMUV6V1dwYWJFNHlWVFJPYlZreFRrUk5lazB5VVhkT1JFazBXWHBqZUU1SFVtdE9SRVUxV1ZSWk1rOUhWVEpOYW1zeldrUkJaRUpuYjNJS1FtZEZSVUZaVHk5TlFVVk1Ra0U0VFVSWFpIQmtSMmd4V1dreGIySXpUakJhVjFGM1VVRlpTMHQzV1VKQ1FVZEVkbnBCUWtSQlVYbEVSRUp2WkVoU2R3cGplbTkyVERKa2NHUkhhREZaYVRWcVlqSXdkbUZJVm01YU1teDFXakphYUZreVZYWmhNbFo1WW0xV2MyTjVNV3BpTWpGMFpGYzFjR1JJYTNkUFFWbExDa3QzV1VKQ1FVZEVkbnBCUWtSUlVYRkVRMmN4V2tSa2FVNXRWVE5hVkdjeVdtcFZNRTE2VFhwYVJFRXdUV3BvYWs1NlJUQmFSMUV3VFZSc2FFNXFXVFFLV2xSWmVVOVVaR3ROUWpoSFEybHpSMEZSVVVKbk56aDNRVkUwUlVWUmQxQmpiVlp0WTNrNWIxcFhSbXRqZVRsMFdWZHNkVTFDYjBkRGFYTkhRVkZSUWdwbk56aDNRVkU0UlVSQmQwdE5WRUV6VFZSUk0wNVVWWGxQVkVGMVFtZHZja0puUlVWQldVOHZUVUZGVVVKRFFVMUliV2d3WkVoQ2VrOXBPSFphTW13d0NtRklWbWxNYlU1MllsTTViMlJYWkc1aFZ6VnVXbTFHYWxwVVFWbENaMjl5UW1kRlJVRlpUeTlOUVVWU1FrRnZUVU5FU1RGT2VrbDNUbnBSZWsxSVJVY0tRMmx6UjBGUlVVSm5OemgzUVZKSlJWbDNlR2hoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiQXBqYlRWc1lraE5kRmt5T1hSaVdGWjFZVmhTTlV4NU5XNWhXRkp2WkZkSmRtUXlPWGxoTWxwellqTmtla3d5U2pGaFYzaHJURmN4YUZsNU5UVlpWekZ6Q2xGSVNteGFiazEyWVVkV2FGcElUWFppVjBad1ltcEJORUpuYjNKQ1owVkZRVmxQTDAxQlJWUkNRMjlOUzBSV2EwNHlTVEphVkdSc1QwUmFiVTVVVVhvS1RYcE9hMDFFVVhsUFIwMHpUVlJTYTFwRVVYaFBWMFV5VG1wb2JFNXFTVFZPTWxGM1NWRlpTMHQzV1VKQ1FVZEVkbnBCUWtaQlVWUkVRa1l6WWpOS2NncGFiWGgyWkRFNWEyRllUbmRaV0ZKcVlVUkNhMEpuYjNKQ1owVkZRVmxQTDAxQlJWWkNSbGxOVmtkb01HUklRbnBQYVRoMldqSnNNR0ZJVm1sTWJVNTJDbUpUT1c5a1YyUnVZVmMxYmxwdFJtcGFVemx5V2xoS2RWcFhlSHBNVjA1MllsY3hNV0p0YkRCbFV6bG9XVE5TY0dJeU5YcE1NMG94WW01TmRrMTZaekVLVFVSUmVFMTZRVEpPUkZWMldWaFNNRnBYTVhka1NFMTJUVlJCVjBKbmIzSkNaMFZGUVZsUEwwMUJSVmRDUVdkTlFtNUNNVmx0ZUhCWmVrSkhRbWR2Y2dwQ1owVkZRVmxQTDAxQlJWbENSR2ROVG01S2JHTkhPRFpoU0ZadVdqSnNkVm95V21oWk1sVjJZVEpXZVdKdFZuTmplVEZxWWpJeGRHUlhOWEJrU0dzMkNtTnRWbTFQYmtwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVEwSnBaMWxMUzNkWlFrSkJTRmRsVVVsRlFXZFNPRUpJYjBGbFFVSXlRVTR3T1UxSGNrY0tlSGhGZVZsNGEyVklTbXh1VG5kTGFWTnNOalF6YW5sMEx6UmxTMk52UVhaTFpUWlBRVUZCUW05VWFEVnFRMEZCUVVGUlJFRkZZM2RTVVVsblVIUXZZZ3BOZWtrNVNDOXNVRlpCU3pkNVRuQXZNamcwZDFoTk0yVnJabTlVUlhWNFNYWmlOelJET0ZGRFNWRkRNRVJ2VmpNemJEWjRiM2czVGxkc2Vra3JTbVpSQ21SaWQzUTBWMFpPVlRoa1pGQmpSa1pDU1RaSmFsUkJTMEpuWjNGb2EycFBVRkZSUkVGM1RtOUJSRUpzUVdwQ2JWVjJRUzlYTW01VmJFczVVREpYTjA4S2RsVndWRTkxWnpCNmRrMUxSa2xKZEdGTFowSjFSV1JNTjJSRWNtNWFjVVpNWjBGemVXNWFTRUpTU1VWWVZEQkRUVkZEVDFOQmJIb3hjMUpVZDBkdFR3cHhVRVJRUlVweVdrWkViazlpVEdzdkx5OUtja1pxZURZNFZYWkxPV2t3ZDFWSE1YSmxTMVZ1WWpsU1pVcEdaeXN6TUhjOUNpMHRMUzB0UlU1RUlFTkZVbFJKUmtsRFFWUkZMUzB0TFMwSyJ9fX19"}],"timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyDADAgEAMIICvwYJKoZIhvcNAQcCoIICsDCCAqwCAQMxDTALBglghkgBZQMEAgEwgbcGCyqGSIb3DQEJEAEEoIGnBIGkMIGhAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgu8aIi0dX3imGvie6S2le2lyPghi+74nhk528NaY2SYMCFH4OD+nwZi3J7VbUrwvDfEIH7HlGGA8yMDI2MTAxNDAzMzQxMlowAwIBAaAypDAwLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2GgADGCAdowggHWAgEBMFEwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUOhNULwyQYe68wUMvy4qOiyojiwwwCwYJYIZIAWUDBAIBoIH8MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjYxMDE0MDMzNDEyWjAvBgkqhkiG9w0BCQQxIgQgno2MJeHRkuivYuC00cID+HLney8iQEDp2gLuu7rIZ/kwgY4GCyqGSIb3DQEJEAIvMX8wfTB7MHkEIIX5J7wHq2LKw7RDVsEO/IGyxog/2nq55thw2dE6zQW3MFUwPaQ7MDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAoGCCqGSM49BAMCBGYwZAIwf4WCHEtTMBJ6FklRktFddKVPVdiGFRBHGM2Y3dvNo3HFWVooukC7x6hNLeXPYGa1AjBFB2RyuoanWjuMlPw0f3yQHg5guO9fG+MMldXhqsn2ujHIX/DBxBNp0XPDkpindAM="}]}},"messageSignature":{"messageDigest":{"algorithm":"SHA2_256","digest":"gKLlhu6VQPZkNMageW25VEOtMgdJeeEJhtoH6jUZ8mE="},"signature":"MEYCIQCo8uLxpHcQSBxU7lLBe9yoXjZZgk7wnzl3xyFX2PazOwIhAPdyLXiqHyrzy3RlDzIkBKJp6d8qnMDVJSo/LFmEehdu"}}