Skip to content
View spicysharkco's full-sized avatar

Block or report spicysharkco

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
spicysharkco/README.md

spicysharkco

AI research and infra, data, performance, robotics. I send fixes upstream for what I run into: Kubernetes, LLM inference, data tooling, coding agents, ROS 2, OpenCV. Go · Rust · Python · C++ · TypeScript · Write-ups at spicyshark.co · Research at spicyshark.co/research

Infrastructure

Project Merged change Result Story
kube-router #2192 network-policy sync stops copying the iptables table once per pod 320x faster, 99.8% less allocation (benchmark) post
k3s #14801 --disable-etcd on an existing server removes its etcd member no stale member left in the cluster
k3s #14811 tunnel proxy stops leaking a goroutine when both directions of a connection fail 1,029 leaked goroutines → 0 (10,000-run test) post
kine #800 compaction retries on MariaDB error 1020, so kine runs on MariaDB 11.8 44 failed compactions → 0 in 45 s of concurrent writes
cri-tools (crictl) #2212 make verify checks docs and vendor drift in a temp dir instead of rewriting the tree tree byte-identical after every run post
external-dns #6805 TXT registry computes only the ownership record name when checking for missing records, instead of rendering and encrypting every record's labels Records(), which runs every reconcile: 512 ms → 23 ms per call with TXT encryption on, 96% less allocation (1k records, in-memory benchmark) post
redis-py #4434 asyncio client breaks the reference cycle on each error reply 1,000 leaked exceptions → 0 (GC off) post
sql_exporter #1115 log context trims its leading comma again, so failed queries stop logging a false "Invalid context log item" warning 1 false warning per failed query → 0 (test) post
sql_exporter #1116 concurrent /metrics?jobs[]= scrapes stop sharing one job filter, so each response holds only its own job's series 20 of 20 mixed-job test runs → 0, go test -race clean post
sql_exporter #1117 a collectors: glob that overlaps a collector already named no longer fails startup with unknown collector README example config: -config.check error → passes, collector loaded once post
sql_exporter #1118 a JSON secret with a number or boolean beside the DSN, such as the numeric port in AWS database secrets, now resolves its key instead of handing the whole JSON to the driver secret with numeric port: target open error → DSN resolved (test) post
sql_exporter #1119 a reload that switches a single target: config to jobs: is now refused with the scrape mode error, as the reverse switch already was, instead of reporting success and serving the old target /reload single target → jobs: 200, no error → 500 with the error (test) post
sql_exporter #1120 a reload that fails no longer stores the config it could not apply, so /config and the jobs[] filter keep matching the targets that still serve after a failed reload, /metrics?jobs[]=a: 400 invalid job name → 200 post
sql_exporter #1121 a query that fails under min_interval is no longer cached, so the next scrape runs it again instead of replaying the error until the interval ends min_interval: 1h, table created after a failed scrape: m missing and scrape_errors_total rising on every scrape → m 1 on the next scrape post
UniFi Poller #1110 unpoller_device_stations exports one series per station type again, with station_type and tag in the right labels, so the Users and Guests dashboard panels show data UAP with 3 user and 2 guest stations: one series {station_type="", tag="guest"} 3 → user 3 and guest 2 post
UniFi Poller #1113 unpoller_device_temperature_celsius and unpoller_device_storage carry each sensor's and each disk's own labels, so a gateway's sensors no longer overwrite each other's labels UXG with sensors Local 41 and CPU 62 and no disk: usually {temp_area="", temp_type="CPU", tag="cpu"} twice → one series per sensor with its own area and type post
UniFi Poller #1114 unpoller_device_stations exports a USG's own mobile and handheld counts, so the USG Insights Mobile and Handheld panels no longer show the user and guest counts USG with 41 user, 0 guest, 2 mobile and 8 handheld stations: {station_type="mobile"} 41 and {station_type="handheld"} 0 → mobile 2 and handheld 8 post
Radicale (CardDAV) #2285 a CardDAV prop-filter with no test, or test="anyof", returns a card that matches any one of its conditions, as RFC 6352 says, instead of only a card that matches all of them card with NICKNAME:test, prop-filter with no test and text-match test and text-match a: empty multistatus → card returned; test="allof" still excludes it post
filelock (file locks) #856 acquire() resolves the lock path before it raises the hold count, so a FileNotFoundError from a removed working directory leaves the count unchanged relative-path lock, working directory removed, acquire() raises, then with lock: ends: lock_counter 1 and is_locked True → 0 and False (test, four lock types; the maintainer added the nested-acquire test) post
tox (test environments) #4174 positional factor labels such as {factor:0} resolve per env_base table, so each table's environments get their own labels instead of the last table's sync-oci-pw description Sync to → Sync oci to pw (test, failed 3 of 3 runs before the fix) post
Jedi (Python autocompletion and refactoring) #2122 Script.extract_function leaves out the return line and the assignment when the extracted lines define no name, so the call site is a plain g(a) instead of the syntax error = g(a) two print calls extracted from f: = g(a) and a bare return → g(a) and no return (repro; the new test failed 3 of 3 runs before the fix) post
Kamaji (Kubernetes control planes) #1360 removing the whole extraArgs block from a TenantControlPlane now resets the flags it added to the kube-apiserver container, instead of leaving them in place on every later pass resetKubeAPIServerFlags with the block removed and --audit-log-path on the container: args kept → args reset (test, failed 3 of 3 runs before the fix) post
wcmatch (Python glob matching) #245 an inverse extended glob followed by an extended group that holds another, such as !(a)@(b|*(c)), translates to a valid regular expression instead of raising re.error !(2)_@(foo|*(bar)) on 1_foo with EXTMATCH: re.error → True (test, five rows) post
wcmatch (Python glob matching) #246 a star directly before an extended star group, such as a**(b), is read as * followed by the group *(b), so the pattern matches abb instead of only names that end in the literal (b) fnmatch.fnmatch('abb', 'a**(b)', flags=fnmatch.EXTMATCH) False → True; glob.globmatch('b', '**(a|b)b', flags=glob.GLOBSTAR | glob.EXTGLOB) False → True (test, eight rows, eight failed before the fix) post
wcmatch (Python glob matching) #247 glob.glob and glob.iglob with IGNORECASE return a path once, not twice, when two patterns find it, and return both a and A where the file system holds both glob.glob(['A*', '*b'], flags=glob.IGNORECASE) with a file Ab: ['Ab', 'Ab'] → ['Ab'] (test, one row, failed in three test classes before the fix) post
goja (JavaScript engine in Go) #803 Array.from throws RangeError: Invalid array length for an array-like longer than 2**32-1 when this is Array or not a constructor, as Node does, instead of looping once per index Array.from({length: 2**32}): no return in any practical time → RangeError: Invalid array length (test, three calls, failed 3 of 3 runs before the fix) post
Kamaji (Kubernetes control planes) #1363 a missing apiserver.crt in the API server certificate Secret now makes Kamaji regenerate the certificate, instead of panicking in the log line of the names check the API server certificate handler with a stored Secret that holds only apiserver.key: nil pointer panic → new certificate written (test; 34 of 35 specs passed and the new one failed before the fix, all 35 pass after) post
Kamaji (Kubernetes control planes) #1365 a failed DataStore lookup in the TenantControlPlane reconcile is now returned, so it is retried with backoff, instead of being logged and reported as success Reconcile with Spec.DataStore naming a DataStore that does not exist: nil error returned → not-found error returned (test) post
goja (JavaScript engine in Go) #805 TypedArray.from accepts a string or number source, as Node does, instead of throwing TypeError: Value is not an object Uint8Array.from("123"): TypeError: Value is not an object: 123 → [1, 2, 3] (test, five assertions, failed 3 of 3 runs before the fix) post
goja (JavaScript engine in Go) #806 RegExp.prototype.test calls exec, as Node does, instead of throwing TypeError for a plain object with exec and ignoring an exec that was replaced RegExp.prototype.test.call({exec() { return null; }}, "a"): TypeError → false (test, 14 assertions, failed 3 of 3 runs before the fix) post
Prefect (workflow orchestration in Python) #23442 Task.with_options, Flow.with_options and MaterializingTask.with_options copy the hook lists, so a hook added to the copy stays off the original instead of being added to both original task with one on_failure hook, with_options copy, then on_failure(alert) on the copy: the original's on_failure_hooks ['log_failure', 'alert'] → ['log_failure'] (test, 13 rows over tasks, flows and @materialize tasks, all failed before the fix) post
goja (JavaScript engine in Go) #807 RegExp.prototype[Symbol.replace] (non-global) and [Symbol.split] call exec, as Node does, instead of panicking on a nil pointer when exec is missing RegExp.prototype[Symbol.replace].call({}, "a", "b"): Go nil pointer panic → TypeError (test, 9 assertions, failed 3 of 3 runs before the fix) post

Data

Project Merged change Result Story
pgx #2689 interval text encoding no longer overflows on the minimum microseconds value, so the text scans back --2562047788:00:-54.-775808 → -2562047788:00:54.775808, same as PostgreSQL 18
arrow-rs #11628 CSV reader returns an error instead of panicking when a dictionary column holds more distinct values than its key type can index 129 values with Int8 keys: panic → DictionaryKeyOverflowError post
arrow-rs #11630 C Data Interface export of a Field keeps a map's keys-sorted flag, so a sorted map, also inside a struct, list, union or Schema, imports as sorted Map(_, true) in a Field, exported and imported back: Map(_, false) → Map(_, true) post
sqlglot #8662 ClickHouse PASTE JOIN parses as a join instead of PASTE becoming the left table's alias SELECT * FROM foo PASTE JOIN bla: read as foo AS PASTE, bla, a cross join → kept as PASTE JOIN (test)
yfinance #3001 a start or end date whose midnight falls in a daylight-saving gap (Cairo, Santiago, Sao Paulo before 2019) shifts forward to 01:00 instead of raising Sao Paulo 2018-11-04: ValueError nonexistent time → parsed as 01:00 (test)
ezdxf (DXF files) #1433 export_json_tags() escapes backslashes and double quotes in string values, so its JSON parses and an MTEXT with a \P line break loads back unchanged MTEXT first\Psecond, json.loads of the export: JSONDecodeError: Invalid \escape → parses, and load_json_tags() returns the same text (test, both formats) post
gojq (jq in Go) #322 a slice with a negative fractional start, such as .[-1.5:], rounds the start down as jq does, instead of truncating it toward zero, in array slices, string slices and slice assignment .[-1.5:] on [0,1,2]: [2] → [1,2]; .[-1.5:] = ["x"]: [0,1,"x"] → [0,"x"] (test, array and string cases, failed before the fix) post
OjG (Go JSONPath) #243 the in filter operator compares arrays and objects by value, as == and != do, so $[?@.a in @.b] returns the row instead of panicking [{"a":[1],"b":[[1]]}]: comparing uncomparable type []interface {} panic → row returned; (@ in [1]) with 1.0: false → true (test, six rows) post
OjG (Go JSONPath) #246 a parenthesized path in a filter, (@.a), is an existence check like @.a, so $[?(@.a) && (@.b)] returns the row that has both fields instead of nothing [{"a":1},{"b":2},{"a":1,"b":2}]: $[?(@.a) && (@.b)] [] → [{"a":1,"b":2}]; $[?!(@.a)] all three rows → [{"b":2}] (test, five rows, four failed before the fix) post
OjG (Go JSONPath) #248 ! in a filter applies to one term, as in RFC 9535, so $[?!@.a && @.b] returns the row that has b and not a instead of every row the whole !(@.a && @.b) lets through [{"a":1},{"b":2},{"a":1,"b":2},{"c":3}]: $[?!@.a && @.b] [{"a":1},{"b":2},{"c":3}] → [{"b":2}]; $[?!@.a || @.b] [{"c":3}] → [{"b":2},{"a":1,"b":2},{"c":3}] (test, six rows, both tests failed before the fix) post
soupsieve (CSS selectors for Beautiful Soup) #320 :nth-last-child(an+b of S) returns the right elements when the first sibling checked does not match S, so li:nth-last-child(1 of .x) returns the last .x item instead of the one before it <ul><li id="0"></li><li id="1" class="x"></li><li id="2" class="x"></li></ul>: li:nth-last-child(1 of .x) ['1'] → ['2'] (test, three selectors, the cached run failed before the fix) post
soupsieve (CSS selectors for Beautiful Soup) #322 :in-range and :out-of-range accept a week input with a week-year of 10000 or more instead of raising ValueError, so a value of 10000-W20 between a min of 10000-W01 and a max of 10000-W52 is in range <input id="a" type="week" min="10000-W01" max="10000-W52" value="10000-W20">: :in-range ValueError: year 10000 is out of range → ['a'] (test, two rows in each of the two week tests, both failed before the fix) post
PyMC (probabilistic programming in Python) #8503 VonMises.logp uses the scaled i0e instead of log(i0(kappa)), so the log-density of a point inside the support is finite for a large kappa instead of -inf pm.logp(pm.VonMises.dist(mu=0.0, kappa=100.0), 0.0).eval(): -inf → 1.382390229428057 (SciPy 1.382390243648071; test, two cases, both failed before the fix) post
OjG (Go JSONPath) #250 length() of a string counts characters, as RFC 9535 does, instead of bytes, so $[?length(@)==2] returns "жж" and "☺☺" as well as "ab" ["a","ab","жж","☺☺","😀"]: $[?length(@)==2] ["ab"] → ["ab","жж","☺☺"]; $[?length(@)==1] ["a"] → ["a","😀"] (test, one row, the length was 10 before the fix) post
OjG (Go JSONPath) #251 <= and >= in a filter match equal operands of any type, as RFC 9535 defines them, so $[?@.a<=null] and $[?@.a>=true] return {"a":null} and {"a":true} instead of nothing [{"a":null},{"a":true},{"a":false}]: $[?@.a<=null] [] → [{"a":null}]; $[?@.a>=true] [] → [{"a":true}] (test, fifteen rows, the ten match rows failed before the fix) post
OjG (Go JSONPath) #252 a negative number right after an operator in a filter parses, so $[?@.a==-1] reads as $[?(@.a == -1)] instead of failing $[?@.a==-1]: '==-' is not a valid operation error → parses as $[?(@.a == -1)] (test, eleven rows that failed before the fix and four error rows that pass either way) post
OjG (Go JSONPath) #253 \/ and an escaped UTF-16 pair in a quoted name or string parse as one character, so $["\/"] reads as $['/'] and $["\ud83d\ude00"] finds the key for U+1F600 $["\/"]: 0x2f (/) is not a valid escaped character error → parses as $['/']; $["\ud83d\ude00"] on {"😀":1}: [] → [1] (test, eleven rows that failed before the fix and six that pass either way) post
OjG (Go JSONPath) #254 an escaped UTF-16 pair in a JSON string decodes as one character in the oj, gen and sen parsers and the oj and sen tokenizers, so "\ud83d\ude00" reads as U+1F600 instead of two U+FFFD "\ud83d\ude00": "\ufffd\ufffd" → "\U0001f600" (oj parser test, five rows that failed before the fix and eight that pass either way) post
OjG (Go JSONPath) #256 a tab, a line feed or a carriage return counts as blank space wherever a space already did, so $[?\n@.a] reads as $[?(@.a)] instead of failing "$[?\n@.a]" in a Go string: '' is not a value or function error → parses as $[?(@.a)] (test, eight rows that failed before the fix and two error rows that pass either way) post
OjG (Go JSONPath) #255 match() tests the whole string when its pattern has a top-level |, as RFC 9535 does, so $[?match(@, 'ab|cd')] returns "ab" and "cd" and no longer "abx" and "xcd" $[?match(@, 'ab|cd')] over ["ab","cd","abx","xcd"]: all four returned → "ab" and "cd" only (test, three rows that failed before the fix and nine that pass either way) post
NumPyro (probabilistic programming on JAX) #2376 the supports of Uniform, LogUniform and DiscreteUniform are computed from low and high instead of stored as a second copy, so low and high are carried once and an updated distribution reports the updated support (a refactor) Uniform leaves 4 → 2, LogUniform 8 → 4; after a gradient step on Uniform(1.0, 3.0): low 1.5, support.lower_bound 1.0 → 1.5, support(1.2) True → False (test, two cases, both failed before the change) post
NumPyro (probabilistic programming on JAX) #2363 Levy.support is derived from loc, so a Levy that crosses jit, vmap or lax.map keeps its support instead of getting None jax.jit(lambda: dist.Levy(0.0, 1.0, validate_args=True))(): support is None and log_prob(2.0) raises AssertionError → GreaterThan(lower_bound=0.0) and -2.2086592 (SciPy -2.2086593040445908; test, four cases, all failed before the fix) post

LLM inference

Project Merged change Result Story
AIBrix (vLLM) #3126 Hugging Face LoRA adapters download into the adapter directory first and repeat loads hand the engine the same path post
AIBrix (vLLM) #3130 runtime sidecar accepts the hf:// adapter URLs the webhook already allows hf:// adapters load instead of failing with "Unsupported URL scheme" post
AIBrix (vLLM) #3132 per-model HTTPRoute matches /v1/images/generations image requests with no routing strategy reach the model instead of finding no route post
AIBrix (vLLM) #3131 runtime sidecar loads adapters from a mounted local path (/...) that the webhook already allows local-path adapters load with the sidecar on, under the same name check as other sources post
AIBrix (vLLM) #3133 model-router custom paths reach the HTTPRoute once each; the dedup set was never written repeated or default paths no longer count toward the 64-match route limit post
AIBrix (vLLM) #3136 ModelAdapter EndpointSlices declare the address family of their Pods instead of always IPv4 IPv6 Pods: EndpointSlice rejected, adapter Service without endpoints → endpoints created post
AIBrix (vLLM) #3137 POST /CreateUser for an existing user returns the stored limits instead of echoing the request user stored at 50 RPM, repeated create with 100: response 100 → 50 post
AIBrix (vLLM) #3147 the runtime serves aibrix:prompt_tokens_total, aibrix:generation_tokens_total and aibrix:request_success_total, because the six counter rules are keyed by the family name the parser returns, without _total vllm:prompt_tokens_total 12.0 through the collector: no aibrix: line → aibrix:prompt_tokens_total 12.0 (one test row per rule) post
AIBrix (vLLM) #3146 the PodSet deletes a Failed or Succeeded pod so the next reconcile can create its replacement, because the pod keeps its index-derived name and the create returns AlreadyExists Failed or Succeeded pods at indexes 1 and 2: both stay, creates skipped → both deleted with an event each, both back on the next reconcile (test with a Failed and a Succeeded subtest, both failed before the fix) post
AIBrix (vLLM) #3169 a RayClusterFleet with an omitted, empty or partly set strategy gets a 25% RollingUpdate where the controller reads it, because the CRD default fills only an absent key omitted or {}: no ReplicaSet; only a type: nil pointer panic; empty rollingUpdate: "nil value for IntOrString" → one ReplicaSet each (the 4 new specs failed before the fix) post
OME #1231 a computed environment override replaces a ConfigMap or Secret source instead of leaving it beside the new value engine Deployment no longer rejected for value plus valueFrom post
OME #1232 the manager registers the BenchmarkJob controller and its validating webhook again, after a refactor dropped them while the chart still declared the webhook BenchmarkJob create: failed calling webhook → admitted and reconciled into a Job; new test checks every declared webhook path is served post
OME #1234 runtime env overrides that switch between value and valueFrom (or between sources) no longer merge into an entry holding both 3 of 4 merge cases rejected by Kubernetes validation → 0 post
Xinference #5726 async reasoning streams keep chunks that carry no text, so a reply with no text still ends with its finish_reason and usage empty reply on vLLM, SGLang or MLX: body only data: [DONE] → stop and usage chunks post
Xinference #5731 a non-stream reasoning reply that ends inside the thinking block no longer starts reasoning_content with the start tag, so it matches the stream non-stream reply with finish_reason: "length" and no end tag: reasoning_content "<think>\nThe user asks" → "\nThe user asks" post
Xinference #5733 a non-stream reasoning reply with text before the start tag no longer starts content with a stray >: content is cut at the end tag, not at an index counted from the start of the reply reply with a newline before <think>: content ">\n\nHello" → "\n\nHello"; with nothing after the end tag, ">" → "" post
Xinference #5746 a streamed reasoning reply that starts with a whitespace-only chunk no longer gets the start tag inserted ahead of that whitespace, so a <think> the model writes next stays out of reasoning_content stream chunks ["\n", "<think>", "a", "</think>", "b"]: reasoning_content "\n\n<think>a" → "a" post
Xinference #5751 a non-stream reasoning reply that has no <think> before </think> keeps a <think> in the answer as content, so the reply no longer fails or returns the answer's block as reasoning_content reply a</think>Use the <think> tag: IndexError (HTTP 500) → reasoning_content "a"; reply a</think>b<think>c</think>d: reasoning_content "c" → "a" post
Xinference #5756 a streamed reasoning reply that has already ended its reasoning keeps a later </think> in the answer as content, so it is no longer read as the end of the reasoning a second time stream chunks ["a", "</think>", "b", "</think>", "c"]: content "bc" → "b</think>c"; chunks ["a</think>b", "c</think>d"]: reasoning_content "\nac" → "\na" post

AI coding agents

Project Merged change
oh-my-codex #3791 HUD caches the git branch label until HEAD, refs or config change · all 4 merged
oh-my-claudecode #4373 hooks start file-context injectors only for the tools they act on · all 7 merged
oh-my-openagent #10133 git diff stats read NUL-separated, so renamed and quoted paths keep their counts · all 2 merged

Robotics

Project What Result Story
OpenCV (calib3d) #30316 validateDisparity skips out-of-range disparities instead of indexing past the row buffers fixes a crash reported in April 2024 (#25367); two earlier fixes were closed post
slam_toolbox (ROS 2) #905 node removal stops copying the pose graph's vertex map and edge list 84x faster per removal on a 19,870-vertex map (benchmark)
mediamtx (camera streaming) #6359 fMP4 recordings of a VP9 track store the frame height instead of repeating the width 1920x804 stream: init segment Height: 1920 → Height: 804 post
chess-sim2real-benchmark · dataset render generator and 20,000-image sim-to-real benchmark a colour-convention fix took per-square accuracy from 54.4 to 85.2 post

Models

Model Method Result
Qwen3.8-27B-OBLITERATED-DYN-GGUF GGUF quants of OBLITERATUS/Qwen3.8-27B-OBLITERATED with a quant type per tensor group, chosen by measured KL-divergence sensitivity inside a fixed file-size budget same size as the upstream Q4_K_M (16.81 GB): mean KL divergence from BF16 0.0348 → 0.0195, same top token 93.84% → 95.33%; CPU prompt processing 0.85x

Tools

Popular repositories Loading

  1. kube-router kube-router Public

    Forked from cloudnativelabs/kube-router

    Kube-router, a turnkey solution for Kubernetes networking.

    Go

  2. spicysharkco spicysharkco Public

    Profile README

  3. rtk rtk Public

    Forked from rtk-ai/rtk

    CLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies

    Rust

  4. sharkline sharkline Public

    Fast Claude Code statusline (status line) in Rust: git, model, rate limits, context, session time

    Rust

  5. sharkswap sharkswap Public

    Claude Code account switcher: switch / swap between Claude Code accounts without logging in again

    Rust

  6. kubernetes kubernetes Public

    Forked from kubernetes/kubernetes

    Production-Grade Container Scheduling and Management

    Go