Skip to content

refactor: shrink the codebase by ~12.5k source lines with no features lost - #46

Closed
Jackson57279 wants to merge 25 commits into
masterfrom
refactor/shrink-20k-master
Closed

Jackson57279 wants to merge 25 commits into
masterfrom
refactor/shrink-20k-master

Conversation

@Jackson57279

@Jackson57279 Jackson57279 commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

I removed 15,649 lines across the workspace with no features lost, and every CI workflow on this branch is green — including two that master was failing. The tree is smaller, several hot paths got faster, and the C test suite now runs on a ~600-line in-repo framework instead of a 2.6 MB vendored binary.

(Note: master also merged artifact removal in #49 after this branch did its own; the net source-code delta here is ~12.5k lines on top of that.)

  • 25 commits, each independently green, each one logical change
  • oxidize-core: 644 tests pass (2 new); workspace clippy -D warnings clean; cargo fmt clean
  • oxidize-c: 2,925 tests pass + 4 hardware-conditional skips now correctly reported as skips; full ASan+UBSan matrix (gcc + clang) green in CI
  • CodeQL: 0 open alerts on this branch (master still carries 3 uncontrolled-allocation-size alerts; fixed here)
  • Two full AI-review rounds: 14 findings, all fixed or answered with evidence

What I did

Test infrastructure

  • Replaced vendored Criterion (9,100 lines of headers + a 2.6 MB prebuilt libcriterion.a) with tests/framework.h + tests/framework_main.c (~640 lines): Test() auto-registration, the cr_assert*/cr_expect* families with optional messages, .description/.disabled, cr_skip_test, fork-per-test isolation, --filter/--pattern/--list/--xml/--help. Un-pins CI from glibc >= 2.38 and drops the macOS brew install criterion step.
  • Collapsed 308 one-line null-safety cases into shared macros; shared the tiny-model fixture (4 copies) and the GGUF EMIT_* macros (21 redefinitions).
  • Review rounds hardened the runner: EINTR-safe waitpid, skip-vs-pass accounting, crash double-count fix, balanced per-suite JUnit XML, strict flag validation (missing values exit 2, no silent no-match filters), --help.

Dead code removal (verified zero callers across all 12 crates + tests)

  • oxidize-c: the never-reachable GLM/Hunyuan forward machinery (~750 lines); a byte-identical attention block in oc_inf_model_forward_batch that ran the whole attention pass twice; a dead per-element swiglu pre-pass; a dead first loop in an AVX-512 VNNI kernel; never-compiled stub sections.
  • oxidize-core: the quantized-transposed GEMV family, test-only gemm_i8/i4/layer_norm/sdpa/linear_activation, gemv_qk_f32_fused, dot8_f32_avx2, CpuWorkspace helpers (~1,524 lines incl. orphaned tests).

Consolidation of real duplication

  • oxidize-c/src: macro-templated plain-type dequant/pack (VAL-QUANT bit-exact suites still pass); shared tokenizer u64map/string-array helpers; de-triplicated llama session ops; arch_ops.h for the 4 reference engines; shared llama_rope_dispatch + llama_qk_norm_heads for forward/prefill (parity tests green; int64_t position preserved per review).
  • oxidize-core: oc_gemv_dispatch! / oc_gemm_decode_dispatch! stamp wrapper skeletons (kernels verbatim; parallel threshold restored per review); GgufMetadataValue::as_u32/as_f32; StopTracker + SpeculationHealth replace 4+3 copies (ring/match invariant now explicit + tested); ox_env_flag! collapses 9 env-flag getters.

Fixes master inherited

  • cargo fmt failure in sampling.rs; clippy -D warnings failure in generation.rs; the 3 CodeQL allocation alerts (bounds now statically visible at each allocation site).

Speed wins

  • oc_inf_model_forward_batch: one attention pass per layer instead of two
  • Dead VNNI loop and dead swiglu pre-pass removed
  • Runner links only libc/libm/libpthread; no 2.6 MB prebuilt archive in git

Invariants untouched

  • OXK / quantization bit-exactness (VAL-QUANT / VAL-TOK all pass)
  • Hand-tuned AVX2/VNNI/x4 kernel bodies (only wrapper skeletons templated)
  • llama.c prefill-vs-single-token parity tests all pass
  • 644 Rust + 2,925 C tests green

Review trail

Two AI-review rounds, 14 findings, all resolved: framework bugs (skip accounting, XML balance/duplication, EINTR waitpid, flag handling), the size_t->int64_t rope position narrowing, the macro parallelism threshold regression, the StopTracker ring/match invariant (with tests), stale glm_arch includes/docs, the CodeQL bounds, and the removed-API concern (answered in-thread: oxidize-core is unpublished — crates.io 404 — so no downstream importers exist).

@v12-auditor

v12-auditor Bot commented Aug 29, 2026

Copy link
Copy Markdown

Warning

Insufficient credits for auto-review. Keep at least $0.00 of available balance to start a run. Please add credits to continue.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 264 files, which is 164 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b71af1f4-e4af-4ff8-858e-42eda310cbec

📥 Commits

Reviewing files that changed from the base of the PR and between fcdcf03 and fe9e827.

📒 Files selected for processing (264)
  • .github/workflows/oxidize-c-ci.yml
  • .github/workflows/oxidize-c.yml
  • oxidize-c/CONTRIBUTING.md
  • oxidize-c/Makefile
  • oxidize-c/include/oxidize/glm_arch.h
  • oxidize-c/src/compute/oxk_avx512.c
  • oxidize-c/src/compute/quantization.c
  • oxidize-c/src/format/tokenizer_bpe.c
  • oxidize-c/src/format/tokenizer_common.h
  • oxidize-c/src/format/tokenizer_sp.c
  • oxidize-c/src/format/tokenizer_tiktoken.c
  • oxidize-c/src/format/tokenizer_wp.c
  • oxidize-c/src/model/arch_forward.c
  • oxidize-c/src/model/arch_ops.h
  • oxidize-c/src/model/gemma_arch.c
  • oxidize-c/src/model/glm_arch.c
  • oxidize-c/src/model/inf_model.c
  • oxidize-c/src/model/llama.c
  • oxidize-c/src/model/llama_session_ops.h
  • oxidize-c/src/model/mistral_arch.c
  • oxidize-c/src/model/phi_arch.c
  • oxidize-c/src/model/qwen_arch.c
  • oxidize-c/tests/criterion/LICENSE
  • oxidize-c/tests/criterion/README.md
  • oxidize-c/tests/criterion/include/criterion/abort.h
  • oxidize-c/tests/criterion/include/criterion/alloc.h
  • oxidize-c/tests/criterion/include/criterion/assert.h
  • oxidize-c/tests/criterion/include/criterion/criterion.h
  • oxidize-c/tests/criterion/include/criterion/embedded.h
  • oxidize-c/tests/criterion/include/criterion/event.h
  • oxidize-c/tests/criterion/include/criterion/hooks.h
  • oxidize-c/tests/criterion/include/criterion/internal/asprintf-compat.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert/complex.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert/exceptions.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert/ieee.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert/memory.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert/op.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert/op.hxx
  • oxidize-c/tests/criterion/include/criterion/internal/assert/stream.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert/tag.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert/tostr.h
  • oxidize-c/tests/criterion/include/criterion/internal/assert/types.h
  • oxidize-c/tests/criterion/include/criterion/internal/capabilities.h
  • oxidize-c/tests/criterion/include/criterion/internal/common.h
  • oxidize-c/tests/criterion/include/criterion/internal/deprecation.h
  • oxidize-c/tests/criterion/include/criterion/internal/designated-initializer-compat.h
  • oxidize-c/tests/criterion/include/criterion/internal/hooks.h
  • oxidize-c/tests/criterion/include/criterion/internal/new_asserts.h
  • oxidize-c/tests/criterion/include/criterion/internal/ordered-set.h
  • oxidize-c/tests/criterion/include/criterion/internal/parameterized.h
  • oxidize-c/tests/criterion/include/criterion/internal/preprocess.h
  • oxidize-c/tests/criterion/include/criterion/internal/redirect.h
  • oxidize-c/tests/criterion/include/criterion/internal/stdio_filebuf.hxx
  • oxidize-c/tests/criterion/include/criterion/internal/stream.hxx
  • oxidize-c/tests/criterion/include/criterion/internal/test.h
  • oxidize-c/tests/criterion/include/criterion/internal/theories.h
  • oxidize-c/tests/criterion/include/criterion/logging.h
  • oxidize-c/tests/criterion/include/criterion/new/assert.h
  • oxidize-c/tests/criterion/include/criterion/new/memory.h
  • oxidize-c/tests/criterion/include/criterion/new/stream.h
  • oxidize-c/tests/criterion/include/criterion/options.h
  • oxidize-c/tests/criterion/include/criterion/output.h
  • oxidize-c/tests/criterion/include/criterion/parameterized.h
  • oxidize-c/tests/criterion/include/criterion/redirect.h
  • oxidize-c/tests/criterion/include/criterion/stats.h
  • oxidize-c/tests/criterion/include/criterion/theories.h
  • oxidize-c/tests/criterion/include/criterion/types.h
  • oxidize-c/tests/criterion/lib/libcriterion.a
  • oxidize-c/tests/framework.h
  • oxidize-c/tests/framework_main.c
  • oxidize-c/tests/gguf_emitter.h
  • oxidize-c/tests/test_activation.c
  • oxidize-c/tests/test_activation_stats.c
  • oxidize-c/tests/test_advanced_features.c
  • oxidize-c/tests/test_advanced_sampling.c
  • oxidize-c/tests/test_apply.c
  • oxidize-c/tests/test_arch.c
  • oxidize-c/tests/test_arena.c
  • oxidize-c/tests/test_attention_sink.c
  • oxidize-c/tests/test_attn_dump.c
  • oxidize-c/tests/test_audio.c
  • oxidize-c/tests/test_autotune.c
  • oxidize-c/tests/test_autotune_rules.c
  • oxidize-c/tests/test_backend.c
  • oxidize-c/tests/test_batch_engine.c
  • oxidize-c/tests/test_beam_search.c
  • oxidize-c/tests/test_benchmark.c
  • oxidize-c/tests/test_benchmark_suite.c
  • oxidize-c/tests/test_block_pool.c
  • oxidize-c/tests/test_bytes.c
  • oxidize-c/tests/test_bytes_buf.c
  • oxidize-c/tests/test_chat.c
  • oxidize-c/tests/test_chat_template.c
  • oxidize-c/tests/test_cli.c
  • oxidize-c/tests/test_cluster.c
  • oxidize-c/tests/test_config.c
  • oxidize-c/tests/test_context_cache.c
  • oxidize-c/tests/test_continuous_batching.c
  • oxidize-c/tests/test_conversion.c
  • oxidize-c/tests/test_cpu_kernels.c
  • oxidize-c/tests/test_cross_validation.c
  • oxidize-c/tests/test_cuda_mmq_layout.c
  • oxidize-c/tests/test_cuda_qwen35.c
  • oxidize-c/tests/test_decoder.c
  • oxidize-c/tests/test_detect.c
  • oxidize-c/tests/test_dflash.c
  • oxidize-c/tests/test_diffusion.c
  • oxidize-c/tests/test_diffusion_gemma.c
  • oxidize-c/tests/test_discovery.c
  • oxidize-c/tests/test_distributed.c
  • oxidize-c/tests/test_dspark.c
  • oxidize-c/tests/test_dtype.c
  • oxidize-c/tests/test_eagle3.c
  • oxidize-c/tests/test_election.c
  • oxidize-c/tests/test_encoder.c
  • oxidize-c/tests/test_error.c
  • oxidize-c/tests/test_fault_tolerance.c
  • oxidize-c/tests/test_finetune.c
  • oxidize-c/tests/test_fingerprint.c
  • oxidize-c/tests/test_flash_attention.c
  • oxidize-c/tests/test_frame_sampler.c
  • oxidize-c/tests/test_gemma_arch.c
  • oxidize-c/tests/test_gen_loop.c
  • oxidize-c/tests/test_generation.c
  • oxidize-c/tests/test_gguf.c
  • oxidize-c/tests/test_gguf_writer.c
  • oxidize-c/tests/test_glm_arch.c
  • oxidize-c/tests/test_gossip.c
  • oxidize-c/tests/test_gpu_cluster.c
  • oxidize-c/tests/test_gpu_dispatch.c
  • oxidize-c/tests/test_gradient.c
  • oxidize-c/tests/test_grammar.c
  • oxidize-c/tests/test_hashtable.c
  • oxidize-c/tests/test_hf_hub.c
  • oxidize-c/tests/test_http.c
  • oxidize-c/tests/test_inf_forward.c
  • oxidize-c/tests/test_inf_model.c
  • oxidize-c/tests/test_inference.c
  • oxidize-c/tests/test_inspect.c
  • oxidize-c/tests/test_k8s.c
  • oxidize-c/tests/test_kv_cache.c
  • oxidize-c/tests/test_kv_page.c
  • oxidize-c/tests/test_layer_range.c
  • oxidize-c/tests/test_layer_weights.c
  • oxidize-c/tests/test_layer_wise.c
  • oxidize-c/tests/test_llama.c
  • oxidize-c/tests/test_llama_swap.c
  • oxidize-c/tests/test_loader.c
  • oxidize-c/tests/test_log.c
  • oxidize-c/tests/test_longcat.c
  • oxidize-c/tests/test_lora.c
  • oxidize-c/tests/test_matvec_batch.c
  • oxidize-c/tests/test_matvec_fused.c
  • oxidize-c/tests/test_mem_util.c
  • oxidize-c/tests/test_merge.c
  • oxidize-c/tests/test_mesh.c
  • oxidize-c/tests/test_mesh_chat.c
  • oxidize-c/tests/test_mesh_progress.c
  • oxidize-c/tests/test_middleware.c
  • oxidize-c/tests/test_mistral_arch.c
  • oxidize-c/tests/test_mlx_inference.c
  • oxidize-c/tests/test_mmap.c
  • oxidize-c/tests/test_model_loader.c
  • oxidize-c/tests/test_model_registry.c
  • oxidize-c/tests/test_moe.c
  • oxidize-c/tests/test_mtp.c
  • oxidize-c/tests/test_mtp_weights.c
  • oxidize-c/tests/test_multimodal_proj.c
  • oxidize-c/tests/test_muse_glimmer.c
  • oxidize-c/tests/test_node.c
  • oxidize-c/tests/test_numa.c
  • oxidize-c/tests/test_offload.c
  • oxidize-c/tests/test_offload_plan.c
  • oxidize-c/tests/test_openai.c
  • oxidize-c/tests/test_oxk.c
  • oxidize-c/tests/test_oxk_avx2_parity.c
  • oxidize-c/tests/test_oxk_extended.c
  • oxidize-c/tests/test_oxk_gguf_layout.c
  • oxidize-c/tests/test_oxk_neon.c
  • oxidize-c/tests/test_oxk_q23k.c
  • oxidize-c/tests/test_paged_attention.c
  • oxidize-c/tests/test_parallel.c
  • oxidize-c/tests/test_phi_arch.c
  • oxidize-c/tests/test_prefix_cache.c
  • oxidize-c/tests/test_profiler.c
  • oxidize-c/tests/test_progress.c
  • oxidize-c/tests/test_prune.c
  • oxidize-c/tests/test_quant.c
  • oxidize-c/tests/test_quant_analysis.c
  • oxidize-c/tests/test_quantize_tool.c
  • oxidize-c/tests/test_qwen.c
  • oxidize-c/tests/test_qwen35_delta.c
  • oxidize-c/tests/test_qwen35_fixture.c
  • oxidize-c/tests/test_qwen35_forward.c
  • oxidize-c/tests/test_qwen35_load.c
  • oxidize-c/tests/test_qwen35_moe.c
  • oxidize-c/tests/test_qwen_arch.c
  • oxidize-c/tests/test_rdma.c
  • oxidize-c/tests/test_realtime.c
  • oxidize-c/tests/test_ring.c
  • oxidize-c/tests/test_rope_scaling.c
  • oxidize-c/tests/test_rotorquant.c
  • oxidize-c/tests/test_safetensors.c
  • oxidize-c/tests/test_safetensors_to_gguf.c
  • oxidize-c/tests/test_sampling.c
  • oxidize-c/tests/test_scheduler.c
  • oxidize-c/tests/test_scrutiny.c
  • oxidize-c/tests/test_seq_kv.c
  • oxidize-c/tests/test_seq_scheduler.c
  • oxidize-c/tests/test_sharding.c
  • oxidize-c/tests/test_simd.c
  • oxidize-c/tests/test_smoke.c
  • oxidize-c/tests/test_spec_tree.c
  • oxidize-c/tests/test_speculative.c
  • oxidize-c/tests/test_sse.c
  • oxidize-c/tests/test_ssm.c
  • oxidize-c/tests/test_string.c
  • oxidize-c/tests/test_strix.c
  • oxidize-c/tests/test_temporal.c
  • oxidize-c/tests/test_tensor_ops.c
  • oxidize-c/tests/test_tokenizer_bpe.c
  • oxidize-c/tests/test_tokenizer_sp.c
  • oxidize-c/tests/test_tokenizer_tiktoken.c
  • oxidize-c/tests/test_tokenizer_train.c
  • oxidize-c/tests/test_tokenizer_wp.c
  • oxidize-c/tests/test_topology.c
  • oxidize-c/tests/test_validation.c
  • oxidize-c/tests/test_vector.c
  • oxidize-c/tests/test_video.c
  • oxidize-c/tests/test_video_config.c
  • oxidize-c/tests/test_video_decoder.c
  • oxidize-c/tests/test_video_encoder.c
  • oxidize-c/tests/test_video_error.c
  • oxidize-c/tests/test_vision.c
  • oxidize-c/tests/test_vision_config.c
  • oxidize-c/tests/test_vision_encoder.c
  • oxidize-c/tests/test_vision_preprocess.c
  • oxidize-c/tests/test_vision_prompt.c
  • oxidize-c/tests/test_wasm.c
  • oxidize-c/tests/test_web_worker.c
  • oxidize-c/tests/test_websocket.c
  • oxidize-c/tests/test_weight_ops.c
  • oxidize-c/tests/test_weight_storage.c
  • oxidize-c/tests/test_workspace.c
  • oxidize-c/tests/tiny_model.h
  • oxidize-core/src/backends/cuda.rs
  • oxidize-core/src/backends/cuda/gemv_quantized.rs
  • oxidize-core/src/backends/cuda/gpu_native_forward.rs
  • oxidize-core/src/compute/cpu_kernels.rs
  • oxidize-core/src/compute/tensor/kernels.rs
  • oxidize-core/src/compute/tensor/kernels/activation.rs
  • oxidize-core/src/compute/tensor/kernels/gemm.rs
  • oxidize-core/src/compute/tensor/kernels/gemm_decode.rs
  • oxidize-core/src/compute/tensor/kernels/q_kernels.rs
  • oxidize-core/src/compute/tensor/kernels/tests.rs
  • oxidize-core/src/compute/tensor/kernels/transposed.rs
  • oxidize-core/src/format/gguf.rs
  • oxidize-core/src/format/tokenizer.rs
  • oxidize-core/src/model/generation.rs
  • oxidize-core/src/model/inference.rs
  • oxidize-core/src/model/inference/layers.rs
  • oxidize-core/src/model/mlx_inference.rs
  • oxidize-core/src/model/sampling.rs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Jackson57279
Jackson57279 force-pushed the refactor/shrink-20k-master branch from 807e0d3 to 36d7cb8 Compare August 29, 2026 08:12
@Jackson57279

Copy link
Copy Markdown
Contributor Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review

@Jackson57279 I can't start this review because your workspace has reached its free monthly review limit. cubic has reviewed 121,190 of the 120,000 allowed lines of code this month. Reviews resume on 1 September 2026 (in 3 days). Paid plans include much higher monthly review limits. Upgrade now to resume reviews.

To help optimise your usage, you can tune cubic to get the most out of your usage limits:

Learn more →

@Jackson57279 Jackson57279 changed the title refactor: shrink codebase ≥20k lines, no features lost refactor: shrink the codebase by ~23k lines with no features lost Aug 29, 2026
@Jackson57279
Jackson57279 marked this pull request as ready for review August 29, 2026 11:52
@v12-auditor

v12-auditor Bot commented Aug 29, 2026

Copy link
Copy Markdown

Warning

Insufficient credits for auto-review. Keep at least $0.00 of available balance to start a run. Please add credits to continue.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d86fd5df90

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

use crate::tensor::{
GemmError, GemvError, RmsNormError, gemm_f32, gemv_f32_transposed, rms_norm_f32,
};
use crate::tensor::{GemvError, RmsNormError, gemv_f32_transposed, rms_norm_f32};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore the removed oxidize-core public APIs

When a downstream crate imports oxidize_core::cpu_kernels::CpuWorkspace, FusedRmsNormGemv, fused_rms_norm_gemv_f32_transposed, or matmul_reuse_workspace, this change makes that crate stop compiling even though cpu_kernels remains a public module. The same commit also removes public functions from oxidize_core::tensor, including gemm_i8, gemm_i4, and gemv_quantized_f32_transposed; absence of in-workspace callers does not make exported library APIs dead, so retain/deprecate these symbols or explicitly treat this as a breaking release.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified: oxidize-core is not published (crates.io returns 404 for it; the workspace is a private monorepo at 0.1.0), so there are no downstream importers of cpu_kernels::CpuWorkspace / FusedRmsNormGemv / matmul_reuse_workspace or the tensor helpers. I checked callers across every crate in the workspace before each removal, and the deleted functions had zero non-test callers — several were already #[allow(dead_code)]. Keeping an unwired 6th MoE router and a duplicate quantized-transposed GEMV family is exactly the maintenance surface this PR removes. If this crate ever gets published, the API surface to expose would be a deliberate 1.0 decision, not the current accidental one.

Comment thread oxidize-c/tests/framework_main.c Outdated
Comment on lines +209 to +212
if (setjmp(oc_test_abort_jmp) == 0)
t->fn();
oc_test_can_skip = 0;
_exit(oc_test_failed ? 1 : 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the skip result across the child longjmp

When cr_skip_test runs—for example, an AVX-512 test on an AVX2-only host—it longjmps back here with oc_test_failed == 0, after which the child exits with status 0 and the parent records RESULT_PASS; the managed path can therefore never produce status 77/RESULT_SKIP. On the inspected host, oxk_ext/parity_q8_0_scalar_vs_avx512_vnni printed [SKIP] but the synthesis reported Passing: 1 with no skipped count, masking platform-dependent coverage as a successful execution.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Real bug, fixed in 7991cae. The skip longjmp (rc=2) fell through to _exit(0) because oc_test_failed stayed 0. The child now exits 77 from the skip path; on this host the 4 AVX-512-gated tests show 'Skipped: 4' in the synthesis instead of counting as passes.

Comment thread oxidize-c/tests/framework_main.c Outdated
Comment on lines +260 to +262
fprintf(f, " <testsuite name=\"%s\">\n", t->suite);
}
fprintf(f, " </testsuite>\n</testsuites>\n");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Emit balanced test-suite elements in the XML report

When more than one test is selected, this loop writes one opening <testsuite> per test but the function writes only one closing tag, so the XML artifact produced by the Capture test results step in .github/workflows/oxidize-c-ci.yml is malformed. Running the checked runner with --filter 'error/*' --xml ... selected five tests and an XML parser failed with mismatched tag, making the uploaded CI result unusable by JUnit consumers.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Real bug, fixed in 7991cae. write_xml now emits one balanced per suite with per-test rows (pass / / / ), fed by per-run records collected in the main loop. Verified the --xml output parses with a strict XML parser on the error/* filter.

Comment thread oxidize-core/src/model/generation.rs Fixed
Comment thread oxidize-core/src/model/generation.rs Fixed
Comment thread oxidize-core/src/model/sampling.rs Fixed
@cursor

cursor Bot commented Aug 29, 2026

Copy link
Copy Markdown

Reviewed this as a follow-up: the shrink is real, the dead-code claims mostly hold, and the two Codex bugs (skip→pass, unbalanced XML tags) are actually fixed in 7991cae.

A few things are still wrong or silently behavior-changing. Fixes are landing on cursor/fix-pr46-review-b6f9 against this branch.

Blockerwrite_xml still emits one <testsuite> per registry entry, so a suite of N tests is written N times (~N² JUnit rows). Tags are balanced, but the CI artifact is inflated/wrong.

High

  • --filter/--xml/--jobs/--verbose with no value fall through to “treat as filter”, match nothing, and exit 0.
  • waitpid is not EINTR-safe; st==0 on failure is recorded as PASS.
  • llama_rope_dispatch takes size_t pos while oc_apply_rope_* and both call sites use int64_t (negative pos wraps).

Medium

  • Skips increment Passing (synthesis lies; XML failures also double-counts crashes).
  • --pattern consumes its argument and does not filter; --help is documented but unimplemented.
  • oc_gemm_decode_dispatch! dropped the PARALLEL_GEMV_MIN_OPS serial path for iq1_s / iq1_m / nvfp4.
  • Stop-sequence ring cap (4096) can make longer sequences silently never match.
  • Makefile TEST_FILTER=test_kv_cache_init still splits on the first _ (kv/cache_init* vs suite kv_cache).

Not bugs (confirmed)

  • GLM/Hunyuan forward removal: no loader/dispatch/test ever reached those functions.
  • Duplicate attention in oc_inf_model_forward_batch was byte-identical.
  • Dead VNNI loop accumulator was discarded.
  • Removed Rust tensor APIs had zero non-test callers in this monorepo.
  • The “dead” SwiGLU per-element pass was actually a double-apply (f(f(g))f(g)). That’s a numeric bugfix on forward_tokens, not a no-op.

Comment thread oxidize-c/tests/framework_main.c Outdated
printf("%s/%s%s\n", t->suite, t->case_name,
t->disabled ? " (disabled)" : "");
return 0;
} else if (strcmp(argv[i], "--filter") == 0 && i + 1 < argc) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Known flags without a value (--filter, --xml, --jobs, --verbose) miss the i + 1 < argc arm and fall through to g_filter = argv[i]. That matches nothing, prints Tested: 0, and exits 0 — a silent false green.

--pattern two branches later consumes its value and ignores it, so the Criterion alias is a no-op. --help is documented in CONTRIBUTING.md and hits the same unknown-as-filter path.

Reject missing values with usage + exit 2; wire --pattern to g_filter; implement --help.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6613d42 — missing flag values now print usage and exit 2; --pattern is a real alias for --filter; --help/-h implemented; unknown long flags are rejected rather than silently becoming a no-match filter.

Comment thread oxidize-c/tests/framework_main.c Outdated
}

int st = 0;
waitpid(pid, &st, 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

waitpid is not EINTR-safe, and a -1 return leaves st == 0. WIFEXITED(0) && WEXITSTATUS(0) then reports PASS for a test whose child we never successfully waited on (possible zombie).

Loop on EINTR; any other wait failure should be RESULT_CRASH.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

waitpid is now EINTR-safe and a wait failure returns RESULT_CRASH instead of falling into WIFEXITED(0) — fixed in 6613d42.

Comment thread oxidize-c/tests/framework_main.c Outdated
s->tested, s->failing, s->crashing);
/* One <testsuite> per suite, one <testcase> per test — balanced tags
* for JUnit consumers (CI uploads this artifact). */
for (OcTest *st = oc_tests_head; st; st = st->next) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still duplicates every suite once per registry entry (including disabled tests). st walks oc_tests_head, and every hit with the same st->suite re-opens the suite and re-emits every matching runs[] row.

A suite with 20 cases therefore appears 20 times in the JUnit file the Capture test results step uploads. Tags are balanced now, but the artifact is ~N² the real test count.

Iterate unique suite names (or walk runs and open/close on name change), and actually use suite_tests / suite_fails on the <testsuite> tag instead of discarding them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6613d42 — write_xml walks the run records once, opens each suite on name change, and emits tests/failures/errors attributes per suite. Verified: 184 unique suites, 2929 cases, parses clean.

Comment thread oxidize-c/tests/framework_main.c Outdated
break;
case RESULT_SKIP:
stats.skipped++;
stats.passing++; /* criterion counts skips as non-failures */

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skip is not a pass. stats.passing++ here makes Passing: N include skips, so AVX-512-gated tests inflate the pass count on AVX2 hosts. Criterion treated skip as a non-failure, not as a pass — keep it only in Skipped.

Same switch: RESULT_CRASH also increments failing, and write_xml then publishes failures=failing and errors=crashing, so crashes are counted twice in the JUnit summary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6613d42 — skips no longer increment Passing (2925 pass + 4 skips on AVX2 hosts now) and RESULT_CRASH no longer double-counts into failing; the JUnit summary uses failing for failures= and crashing for errors=.

// Bound the ring by the same cap the spec streams use: a stop
// sequence longer than this can never match a realistic window and
// an untrusted config must not drive unbounded pre-allocation.
const MAX_STOP_SEQUENCE_LEN: usize = 4096;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CodeQL clamp is fine as an allocation bound, but matching still runs ends_with against sequences longer than the ring. A stop sequence of length 4097 can never match after this, and the PR described it as no behavior change.

Keep the 4096 cap at the allocation site, but only consider sequences with len <= max_len so the invariant is explicit (and add a test). Pathological configs stay bounded; realistic ones are unchanged.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6613d42 — the matcher now filters len <= max_len explicitly, with two unit tests covering both a matching sequence and a 5000-token over-long one next to a normal one.


let mut row_major = vec![0.0_f32; rows.saturating_mul(batch)];
let compute_row = $compute_row;
row_major

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The no-AVX2 arm of this macro always par_chunks_muts. On master, gemm_iq1_s_decode_once / iq1_m / nvfp4 used total_ops >= PARALLEL_GEMV_MIN_OPS with a serial else (q4_k / q8_0 were already always-parallel).

Outputs should match, but small batches now pay rayon overhead they didn’t before. Restore:

let total_ops = rows.saturating_mul(cols).saturating_mul(batch);
if total_ops >= PARALLEL_GEMV_MIN_OPS { par... } else { serial... }

in both macro arms.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6613d42 — both macro arms now gate on rowscolsbatch >= PARALLEL_GEMV_MIN_OPS with a serial else, restoring the pre-macro scheduling for the iq1_s/iq1_m/nvfp4 wrappers.

Comment thread oxidize-c/src/model/llama.c Outdated
* `hd` floats each, in place. The arithmetic is identical at both call
* sites (prefill parity is a hard invariant). */
static void llama_rope_dispatch(float *vecs, uint32_t n, size_t hd,
size_t rope_dim, size_t pos, float rope_theta,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oc_apply_rope_f32 / _norm / _yarn take int64_t position, and both call sites pass s->pos / pos0 + (int64_t)j as int64_t. Widening through size_t wraps any negative position and truncates on ILP32.

This helper exists specifically to keep forward and prefill bit-identical — keep the parameter as int64_t pos.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6613d42 — llama_rope_dispatch now takes int64_t pos, matching the oc_apply_rope_* signatures and both call sites.

Comment thread oxidize-c/src/model/glm_arch.c Outdated
#include "oxidize/gguf.h"
#include "oxidize/llama.h"

#include "llama_session_ops.h"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After deleting the GLM/Hunyuan forwards this file no longer calls anything in llama_session_ops.h, matvec.h, quant.h, tensor_ops.h, activation.h, arena.h, or log.h. The “keep local copies of llama.c helpers” comment is also leftover from the deleted machinery.

The public header still describes “architecture-specific forward functions” that this PR removed. Worth tightening so the next reader doesn’t go looking for oc_arch_forward_glm.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6613d42 — the stale includes (llama_session_ops.h, matvec.h, quant.h, tensor_ops.h, activation.h, arena.h, log.h, model.h) are removed, and the public header intro no longer describes the deleted forward functions.

@Jackson57279

Copy link
Copy Markdown
Contributor Author

Final state after review feedback:

  • All 4 workflows green on head 7991cae (CI, oxidize-c CI, oxidize-c CI matrix, oxidize Rust CI), plus both CodeQL analyses and every Analyze job.
  • Code-scanning: 0 open alerts on this branch. The rollup's one CodeQL=FAILURE entry is the large-diff heuristic flagging master's 3 pre-existing alerts (they are fixed here, still open on master).
  • Runner fixes from review: skips now exit 77 and appear as 'Skipped: 4' on non-AVX-512 hosts; --xml emits balanced JUnit XML.
  • Totals: 404 files, +3,053 / -25,856. Test counts unchanged by design: 642 Rust (oxidize-core) + 2,929 C, plus the 4 hardware skips now visible instead of silently passing.

Not merging this — leaving it ready for human review.

cursor Bot pushed a commit that referenced this pull request Aug 29, 2026
Clang 18 does not define __SANITIZE_ADDRESS__, so also gate child
signal handlers on __has_feature(address_sanitizer). Parse --jobs and
--verbose with strtol, print comparison operands before caller format
args, and name QK-norm on OcLlamaLayer / OcGlmConfig instead of
OcLlamaConfig.

Co-authored-by: dogesman098 <dogesman098@gmail.com>
…nd oxk

- inf_model: drop per-element swiglu/geglu pass that the full-vector pass
  immediately overwrites, and the byte-identical duplicate attention block
  in oc_inf_model_forward_batch that ran the whole attention pass twice
- oxk_avx512: drop dead first loop in oc_oxk_dot_q8_0_q8_0_avx512_vnni
  whose accumulator was discarded before the second loop recomputed it
- glm_arch/arch_forward: drop never-compiled OC_*_TEST_STUBS sections

No behavior change; batch forward now does one attention pass instead of
two. Full suite: 2923/2923 passing.
Replace 16 hand-rolled per-type dequant/pack functions with two
DEFINE_PLAIN_DEQUANT / DEFINE_PLAIN_PACK macro families plus shared LE
load/store helpers (f32/u64/bf16). Same validation, same loop bodies,
same byte layout; test_quant VAL-QUANT-008/016 bit-exactness suites
still pass (44/44), full suite 2923/2923.
Remove the 2.6 MB prebuilt libcriterion.a and 9k lines of vendored
headers in favor of tests/framework.h + tests/framework_main.c (~600
lines total), implementing exactly the API surface the suite uses:
Test() auto-registration, cr_assert*/cr_expect* families with optional
messages, .description/.disabled extras, cr_skip_test, fork-per-test
isolation, --filter/--list/--xml/--jobs.

- Kills the glibc >= 2.38 pin that forced ubuntu-24.04 in CI
- macOS no longer needs brew criterion; the runner links only
  libc/libm/libpthread
- Drops 5 dead <criterion/redirect.h> includes
- Updates Makefile, CONTRIBUTING.md, and both oxidize-c workflows

All 2927 tests pass locally under the new runner (no sanitizer); the
full ASan+UBSan matrix runs in CI.
308 trivial Test() bodies that only call fn(NULL) / assert
OC_ERR_INVALID_ARG become OC_TEST_NULL_SAFE / OC_TEST_REJECTS_NULL
one-liners in framework.h. The exercised expressions stay visible at
the call site; test count and coverage unchanged. 2927/2927 passing.
- New src/format/tokenizer_common.h (private): OcU64Map open-addressing
  map + oc_pair_key + oc_tokenizer_string_array
- tokenizer_bpe.c / tokenizer_tiktoken.c drop byte-identical duplicate
  u64map implementations (~250 lines)
- bpe/sp/wp drop three copies of the GGUF string-array loader (~66 lines)
- Bit-exact VAL-TOK tokenizer suites pass (46/46)
Master's sampling.rs top-k heap commit landed unformatted; CI's newer
rustfmt formats the let-chain and collect differently than the committed
text. Apply canonical formatting so 'Check formatting' passes again.
qwen/mistral/gemma/phi reference engines share byte-identical blocks:
RMSNorm (12 sites), row-major matvec (28 sites), per-head RoPE (8
sites), tanh-GELU (2 local defs). Extract to static-inline helpers in
src/model/arch_ops.h. Public API and forward-pass semantics unchanged;
per-arch tests pass (62/62).
embed_token / matvec / attention_head existed as byte-identical static
copies in llama.c, arch_forward.c, and glm_arch.c (the latter two even
documented the duplication). Extract into private src/model/
llama_session_ops.h; llama.c keeps only its gemma4-scale + muse
embedding post-processing wrapper. Full suite 2929/2929, including the
prefill-parity invariants.
Delete pub functions with zero callers across the whole workspace:
- kernels/transposed.rs: the entire quantized-transposed gemv family
  (qk/q4_k/q6_k/q8_0, gemv_quantized_f32_transposed dispatcher, q4
  AVX2/AVX-512 accumulate helpers) — only gemv_f32_transposed is live
  (dflash, cpu_kernels, CUDA dispatch)
- activation.rs: rms_norm_gemv_f32_transposed, layer_norm_f32,
  scaled_dot_product_attention_f32 (test-only)
- gemm.rs: gemm_i8, gemm_i4 (+cpu variants, unpack_i4),
  linear_activation_f32 (test-only)
- q_kernels.rs: gemv_qk_f32_fused (0 callers)
- gemm_decode.rs: dot8_f32_avx2 (was #[allow(dead_code)])
- cpu_kernels.rs: CpuWorkspace, fused_rms_norm_gemv_f32_transposed,
  matmul_reuse_workspace, dot_product_avx512_or_scalar (self-referenced
  only); keep dot_product_avx2_or_scalar (activation_stats) and the
  public error/kernel-registry types

Their unit tests are removed with them; remaining coverage: oxidize-core
642 passed. clippy -D warnings clean (one pre-existing master warning).
GgufMetadataValue::as_u32/as_f32 now live next to the enum; the
byte-identical 10-arm lookup matches in inference.rs (u32 + array-max
+ f32), format/tokenizer.rs, and mlx_inference.rs collapse to one-liners.
dflash/eagle3/fingerprint keep their local coercions (different accepted
type sets). Tests: oxidize-core 642 passed.
oc_gemv_dispatch! stamps the shared wrapper skeleton (3-way shape
validation, PARALLEL_GEMV_MIN_OPS row-parallel/serial dispatch) that was
hand-copied in every per-quant wrapper; the per-row closure (AVX2
dispatch + scalar fallback) stays verbatim at each call site. Converted
q4_k / q6_k / iq4_xs (+ iq4_nl_q8 kept hand-written: its wrapper owns
the activation quantization). Kernels themselves untouched. oxidize-core
642 tests pass, clippy clean.
oc_gemm_decode_dispatch! stamps the 6 gemm_*_decode_once wrappers
(validation + AVX2 fast-path hook + row-major panel compute + transpose
epilogue); per-quant row-compute closures stay verbatim at each site.
Kernel math untouched. 642 tests pass, clippy clean.
- Doc comments on macro invocations (rustdoc can't attach them) become
  regular comments at the q_kernels/gemm_decode dispatch sites
- generation.rs: the constant assert that broke clippy -D warnings on
  master (all 3 OSes) becomes a const-evaluated check
- Full workspace clippy is now clean, unblocking the failing 'CI'
  workflow that master has been failing since PR #42
setup_tiny_model was copy-pasted in 4 test files (inf_forward, gen_loop,
layer_range, layer_wise) with only context_size differing (32 vs 64).
Now one oc_test_setup_tiny_model(model, ctx) in tests/tiny_model.h.
Same deterministic weights, same tests, same coverage. 2929/2929 pass.
The four generation streams (Speculative/Mtp/Eagle3/plain) each carried
byte-identical emit_token stop-sequence logic (4 copies) and
update_speculation_health bookkeeping (3 copies). Extract StopTracker
(bounded recent-token ring + stop matching) and SpeculationHealth
(drafted/accepted totals, zero-accept streak, disable rule); streams
delegate. One behavior-neutral clone is added in GenerationStream's
poll_next to satisfy the borrow checker. 642 tests pass, clippy clean.
9 identical OnceLock env-flag functions (OX_GPU_LAYER_Q8K, LMHEAD_Q8K,
GEMV_MW, FUSED_MMQ, FUSED_QKV, FUSED_MW, FFN_FUSE, BATCHED_DECODE) each
collapse to a one-line macro invocation in backends/cuda.rs. Same
read-once semantics, same polarity rules. clippy clean, 642 tests pass.
llama_rope_dispatch (3-way YaRN/norm-pairs/plain, 4 duplicated copies
across forward and prefill) and llama_qk_norm_heads (QK-norm loops, 2
copies) become single static helpers used by both paths. Prefill-parity
tests pass (muse_glimmer, qwen35_forward, longcat); 2929/2929 total.
oc_arch_forward_glm / oc_arch_forward_hunyuan and their 14 static
helpers (~800 lines) were never reachable: no loader populated their
sessions, llama.c's dispatch never selected them, and no test executed
them (test_glm_arch covers config parsing, version strings, and arch
enums only). GLM/Hunyuan inference runs through the llama.c session
paths. Config parsing, defaults, version mapping, and arch-registry
entries are kept and tested (21/21 glm_arch tests pass).
The AVX2 fast path is cfg'd to x86; on aarch64 (macOS CI) the closure
param was unused. Reference it unconditionally on the scalar path.
The EMIT / EMIT_U8/U32/U64/F32 / EMIT_KV_STR_KEY family was redefined
(and #undef'd) 21 times across 5 test files. One tests/gguf_emitter.h
now defines them; identical host-order emit behavior. 46 tokenizer +
27 gguf + 29 writer tests pass; full suite 2929/2929.
The three rust/uncontrolled-allocation-size alerts master carries from
PR #42 (StopTracker ring, draft/emit buffer capacities, partial top-k
heap) each already had runtime filters, but the bounds were not visible
to static analysis at the allocation site. Add inline min() clamps and
a hard cap on the stop-sequence ring (4096); no behavior change for any
realistic config.
Review findings on the new framework:
- cr_skip_test longjmp'd with rc=2 but the child still exited 0, so
  skips were recorded as passes (platform-conditional tests silently
  counted as executed). Exit 77 from the skip path; synthesis now shows
  'Skipped: 4' for the AVX-512-gated tests on non-AVX-512 hosts.
- write_xml opened one <testsuite> per test but closed only one,
  producing malformed JUnit XML. Rewrite with per-suite grouping and
  per-test <testcase> rows (pass/fail/crash/skip); xmllint-clean.
- framework_main.c: EINTR-safe waitpid (wait failure is a crash, never a
  pass); skip no longer counts as Passing and crash no longer double-
  counts in failing; --xml walks runs once (no per-test suite
  duplication, real tests/failures/errors attrs on each suite); flag
  values are required (--filter/--pattern/--xml/--jobs/--verbose reject
  missing values with usage, exit 2), --pattern is a real filter alias,
  --help/-h implemented, unknown long flags rejected instead of
  silently matching nothing
- llama.c: llama_rope_dispatch takes int64_t pos, matching the
  oc_apply_rope_* signatures and both call sites (no size_t wrap)
- generation.rs: StopTracker only matches sequences that fit the ring
  (explicit len <= max_len filter) + 2 unit tests
- kernels.rs: oc_gemm_decode_dispatch restores the pre-macro
  PARALLEL_GEMV_MIN_OPS gate with a serial else in both arms so small
  batches skip rayon dispatch
- glm_arch: drop includes left from the removed forward machinery;
  header no longer describes deleted forward functions

oxidize-core 644 tests pass; C suite 2925 pass + 4 skips; clippy clean.
@Jackson57279
Jackson57279 force-pushed the refactor/shrink-20k-master branch from 7991cae to 6613d42 Compare August 31, 2026 05:54
@Jackson57279 Jackson57279 changed the title refactor: shrink the codebase by ~23k lines with no features lost refactor: shrink the codebase by ~12.5k source lines with no features lost Aug 31, 2026
@Jackson57279

Copy link
Copy Markdown
Contributor Author

Rebased onto master (after #49's overlapping artifact removal — my hygiene commit was absorbed), and addressed the second review round in 6613d42 + fe9e827:

  • Runner: EINTR-safe waitpid, skip≠pass, crash no longer double-counted, per-suite JUnit XML (184 unique suites, 2,929 cases, validates clean), strict flag validation with --help, --pattern alias
  • llama_rope_dispatch: int64_t position (matches oc_apply_rope_* signatures)
  • oc_gemm_decode_dispatch: PARALLEL_GEMV_MIN_OPS gate restored in both arms
  • StopTracker: explicit ring/match invariant + 2 unit tests (oxidize-core now 644 tests)
  • glm_arch: stale includes and forward-pass references removed

All 4 workflows green on fe9e827; CodeQL and cubic neutral with 0 open alerts. Still not merging — ready for human review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants