Skip to content

Validated statistics layer: catalogue, cancellation, Julia UI and evidence (issue #1) - #257

Merged
hyperpolymath merged 9 commits into
mainfrom
arena/3d3fe618-metamanifold-webui
Oct 23, 2026
Merged

hyperpolymath merged 9 commits into
mainfrom
arena/3d3fe618-metamanifold-webui

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Closes the implementation scope of #1 (validated Julia statistics layer) and leaves the two owner/reviewer gates explicitly open rather than self-certified.

What this adds

Bounded method catalogue

  • config/defaults/validated_statistics.kyaml (KYAML, standards YAML-POLICY Y-3 / D307) is the source of truth: 6 methods with supported / unsupported / deferred / out_of_scope, plus the enforced limits.
  • GET /api/v1/statistics/catalogue publishes it as canonical I-JSON/JCS with catalogue_sha256, supported_method_ids, method_count and file.
  • src/analysis/method_catalogue.jl refuses an unapproved catalogue, a supported method without evidence, and any limit that differs from the constant the code enforces.

Canonical responses and cancellation

  • Validated-statistics responses now use jcs_json (they were JSON3-encoded while the trust contract already claimed JCS).
  • Opt-in time_limit_seconds (whole seconds, 1–3600) threads a CancellationToken through the summary loops and the DuckDB row stream. Exhaustion returns 408 statistics_cancelled with no partial result. The deadline is operational only: it is not fingerprinted and not stored in a derived record.

Julia-owned UI

  • GET/POST /statistics is server-rendered with no script and Content-Security-Policy: default-src 'none': form, catalogue block, per-sample/group tables, provenance (input_sha256, policy fingerprint), explicit failure states, optional immutable record. Exempted from the SPA catch-all. No new application TypeScript.

Evidence

  • New unit files: test_method_catalogue, test_statistics_boundaries, test_statistics_adversarial, test_statistics_properties, test_statistics_ui (registered in test/runtests.jl and the focused CI step).
  • scripts/statistics/simulation_study.jl — seeded exact replicates (tolerance 0) and 128/256/512-bit error study against an independent 4096-bit computation, with the tolerance declared before the run.
  • scripts/statistics/mutation_check.py — six planted defects, each required to turn a named test red; refuses a dirty target and verifies restoration.
  • scripts/statistics/biological_validation.jl — compares the layer with the existing Float64 DiversityMetrics on a real matrix; refuses to run without a provenance string.
  • New CI job Statistics standards and evidence: pinned yq v4.53.3 (SHA-256 verified) and pinned hyperpolymath/standards + hyperpolymath/ijson-jcs commits, kyaml-format.sh --check, check-ijson-jcs.sh --enforce, simulation and mutation, with retained artifacts.

Docs: docs/statistics/numeric-contracts.md, docs/statistics/method-catalogue-v1.md, docs/statistics/validation-evidence.md, plus updated VALIDATED_STATISTICS.md.

Deliberately not self-certified

  1. Representative biological validation — the runner exists but no licensed representative count matrix is in the repo (bundled data is FASTQ only). Needs an owner-supplied run or an approved public dataset.
  2. Independent statistical/scientific review + explicit release approval — requires a named reviewer's sign-off on the claim language.

Everything else in the acceptance list is mapped to a checkable artifact in docs/statistics/validation-evidence.md. Exact statistical tests remain deferred; symbolic mathematics is out of scope and #2 stays blocked.

Claim language

descriptive only; no hypothesis test, confidence interval, significance claim or estimator coverage guarantee.

Notes for review

  • Stored derived records remain byte-exact JCS with no trailing newline (the ID addresses those bytes); this is documented in numeric-contracts.md as the one file-level exception to J-1, whose gate covers repository-tracked JSON.
  • time_limit_seconds accepts whole seconds over JSON; decimal tokens are refused by the same raw-number rule as counts.

- Publish the approved method catalogue as KYAML and serve it from
  GET /api/v1/statistics/catalogue as canonical I-JSON/JCS; validate every
  limit against the constants the code enforces.
- Emit JCS for validated-statistics responses and add an opt-in
  time_limit_seconds deadline: 408 statistics_cancelled, no partial result,
  deadline never persisted or fingerprinted.
- Add a Julia-rendered, script-free /statistics page (no new application
  TypeScript) with catalogue block, provenance, accessibility affordances and
  explicit failure states; exempt it from the SPA catch-all.
- Add boundary, adversarial, property and UI tests plus seeded simulation and
  mutation scripts; register them in the test runner and focused CI step.
- Add a CI standards job: pinned yq + ijson-jcs, kyaml-format --check,
  I-JSON/JCS gate, simulation study and mutation campaign with retained
  artifacts.
- Document numeric/cross-language/storage contracts, the catalogue approval
  record and the acceptance evidence map.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T19:47:17.619760Z 1c22ba7 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 41 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: c1a27ff1-48b2-41c5-9aa6-e0fa064c796a
📥 Commits

Reviewing files that changed from the base of the PR and between ccbf597 and 1c22ba7.

📒 Files selected for processing: 29
  • .github/workflows/ci.yml
  • VALIDATED_STATISTICS.md
  • config/defaults/validated_statistics.kyaml
  • docs/sonar-quality-gate.md
  • docs/statistics/issue-1-ultraplan.md
  • docs/statistics/method-catalogue-v1.md
  • docs/statistics/numeric-contracts.md
  • docs/statistics/validation-evidence.md
  • scripts/ci/fetch-statistics-tools.sh
  • scripts/ci/install-r-runtime.sh
  • scripts/ci/run-with-log.sh
  • scripts/statistics/biological_validation.jl
  • scripts/statistics/mutation_check.jl
  • scripts/statistics/simulation_study.jl
  • scripts/tests/test-ci-logging.sh
  • src/MetaManifold.jl
  • src/analysis/exact_summaries.jl
  • src/analysis/high_precision.jl
  • src/analysis/method_catalogue.jl
  • src/analysis/numeric_policy.jl
  • src/server/routes/statistics_ui.jl
  • src/server/routes/validated_statistics.jl
  • src/server/server.jl
  • test/runtests.jl
  • test/unit/test_method_catalogue.jl
  • test/unit/test_statistics_adversarial.jl
  • test/unit/test_statistics_boundaries.jl
  • test/unit/test_statistics_properties.jl
  • test/unit/test_statistics_ui.jl
✨ Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Fork governance

Lane Status Run
DEED syntax (repo deed) 🟢 conformant run 40013857473
K9 conformance (L0–L2; L3 not verified) green (job: success) same run
Hypatia verdict grid purple (job: success) same run

Hypatia grid purple

🟣 critical · commit 1c22ba72ba63 · run 40013857473

Reporter Status Critical High Medium Minor Since previous revision
Hypatia scan 🟣 critical 51 63 26 0 ↔ unchanged
panic-attack assail 🔴 high 0 7 3 0 ↔ unchanged
pons asinorum 🟡 medium 0 0 4 0 ↔ unchanged
rhodibot (RSR compliance) 🟠 indeterminate 0 0 0 0 — indeterminate
panicbot (panic recovery, error handling) 🟠 indeterminate 0 0 0 0 — indeterminate
echidnabot (formal verification: proofs/) 🟠 indeterminate 0 0 0 0 — indeterminate
seambot (integration health: API routes) 🟠 indeterminate 0 0 0 0 — indeterminate
finishingbot (release readiness) 🟠 indeterminate 0 0 0 0 — indeterminate
accessibilitybot (WCAG on the React UI) 🟠 indeterminate 0 0 0 0 — indeterminate
glambot (presentation quality) 🟠 indeterminate 0 0 0 0 — indeterminate
cipherbot ⚪ not applicable 0 0 0 0 ↔ unchanged
sustainabot ⚪ not applicable 0 0 0 0 ↔ unchanged
Hypatia scan: 140 finding(s)
  • critical cicd_rules/banned_language_file — frontend/src/views/run/parseFilterYaml.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/encode.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/charts.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/export.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/figure.test.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/legend.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/types.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/utils/download.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/utils/text.test.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/utils/timeago.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/utils/text.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useUnsavedGuard.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useApi.test.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useApi.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useAnalysis.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useSSE.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useTabParam.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useNavRefresh.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useJobEvents.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/about.ts — TypeScript file detected -- banned language
  • 120 more; see the structured report in the artifact.
panic-attack assail: 10 finding(s)
  • high DynamicCodeExecution — src/pipeline/dada2/context.jl — eval/Meta.parse in src/pipeline/dada2/context.jl
  • high DynamicCodeExecution — src/analysis/analysis.jl — eval/Meta.parse in src/analysis/analysis.jl
  • high DynamicCodeExecution — src/analysis/differential.jl — eval/Meta.parse in src/analysis/differential.jl
  • high DynamicCodeExecution — src/core/provenance.jl — eval/Meta.parse in src/core/provenance.jl
  • high UnboundedLoop — scripts/formats/descendants.py — Unbounded while True loop in scripts/formats/descendants.py
  • high DynamicCodeExecution — scripts/check-julia-syntax.jl — eval/Meta.parse in scripts/check-julia-syntax.jl
  • high DynamicCodeExecution — test/unit/test_permanova.jl — eval/Meta.parse in test/unit/test_permanova.jl
  • medium UnsafeFFI — src/core/memory_probe.jl — 3 ccall/FFI calls in src/core/memory_probe.jl
  • medium UnsafeFFI — install.jl — 1 ccall/FFI calls in install.jl
  • medium ProofDrift — test/unit/test_statistics_properties.jl — 2 `@test x isa Y` assertion(s) with no value check — type-only tests may substitute for an unwritten formal theorem in test/unit/test_statistics_properties.jl
pons asinorum: 4 finding(s)
  • medium swallowed-error — ./scripts/formats/process.py:127 — empty or pass-only exception handler (T0, HEURISTIC)
  • medium swallowed-error — ./scripts/formats/descendants.py:86 — empty or pass-only exception handler (T0, HEURISTIC)
  • medium swallowed-error — ./scripts/formats/descendants.py:55 — empty or pass-only exception handler (T0, HEURISTIC)
  • medium swallowed-error — ./scripts/formats/descendants.py:50 — empty or pass-only exception handler (T0, HEURISTIC)
rhodibot (RSR compliance): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
panicbot (panic recovery, error handling): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
echidnabot (formal verification: proofs/): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
seambot (integration health: API routes): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
finishingbot (release readiness): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
accessibilitybot (WCAG on the React UI): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
glambot (presentation quality): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
cipherbot: not_applicable — no cryptography is implemented in this repository
  • ⚪ not applicable: no cryptography is implemented in this repository
sustainabot: not_applicable — fleet adapter slot reserved; no adapter exists yet (gitbot-fleet README)
  • ⚪ not applicable: fleet adapter slot reserved; no adapter exists yet (gitbot-fleet README)

Scope: static findings reported by each row's tool at the named commit. Purple, red, yellow and blue grade the worst finding present; orange is evidence missing, malformed or a scanner that did not run; grey is an explicit scope exclusion with its reason. No row is a security certification. report.json, badge.json and the raw findings are in the verdict-grid artifact on the linked run.

K9 L0–L2 green

🟢 conformant · commit 1c22ba72ba63 · run 40013857473 · validator hyperpolymath/standards@c6d78606f392

Category Status Pass Fail Indeterminate N/A Since previous revision
K9 contract typecheck 🟢 conformant 1 0 0 0 ↔ unchanged
K9 validator self-test 🟢 conformant 37 0 0 0 ↔ unchanged
K9 live corpus (L0–L2) 🟢 conformant 3 0 0 0 ↔ unchanged

Scope: K9 components L0–L2 against contract v1.0.0 at the named standards commit. L3 signature verification and routed coordination-dialect files are not certified. Green is limited to this scope. Orange is missing evidence; yellow is grandfathered debt or warnings; grey is an explicit scope exclusion. report.json, badge.json and the validator logs are in the k9-grid artifact on the linked run.

… a script

- The mutation campaign is now scripts/statistics/mutation_check.jl, matching
  the repository's Julia-owned tooling and removing a Python entry point whose
  CLI paths SonarCloud rated as high-severity taint findings.
- Tool installation (HTTPS-only curl with a pinned SHA-256, exact-commit
  fetches, cargo build) moves from inline workflow steps into
  scripts/ci/fetch-statistics-tools.sh.
- The I-JSON/JCS gate enforces the canonical config document only; the oracle
  vector file is deliberately non-canonical input and is not a document to
  enforce. The repository-wide pass stays report-only and retained.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>

@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: 0f277cbfe9

ℹ️ 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".

Comment thread .github/workflows/ci.yml
Comment on lines +538 to +539
- name: Set up Julia
run: bash scripts/install-ci-julia.sh

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 Instantiate dependencies in the standards job

On a fresh ubuntu-24.04 runner, this step only installs the Julia binary—scripts/install-ci-julia.sh downloads the runtime and adds it to PATH, but does not instantiate the project. Consequently, the later simulation and mutation steps invoke using MetaManifold without the dependencies from Manifest.toml being installed and the new standards job fails for every relevant change. Add the same Pkg.instantiate() step used by the main test job before running this evidence.

Useful? React with 👍 / 👎.

Comment on lines +21 to +24
function _html_escape(value)
replace(String(value),
'&' => "&amp;", '<' => "&lt;", '>' => "&gt;",
'"' => "&quot;", '\'' => "&#39;")

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 Stringify numeric values before escaping them

A successful form result contains numeric values such as totals, richness, policy limits, and diagnostics, but String(value) has no method for Julia integers. Rendering the first such value therefore raises a MethodError, which the POST handler converts into a 500 error page instead of displaying the result. Use string(value) before applying the HTML replacements so both textual and numeric result fields can be rendered.

Useful? React with 👍 / 👎.

Comment on lines +351 to +353
String("<code>", _html(print_value), "</code><br><span class=\"display\">",
_html(kind), " · ", _html(string(bits)), "-bit · display: ",
_html(display), "</span>")

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 Build the high-precision cell with a string concatenator

When a high-precision metric is defined, this branch calls String with multiple fragments, but Julia's String constructor is not a variadic concatenation function. After the general numeric escaping failure is fixed, every nonzero high-precision result still fails with a MethodError while rendering Shannon or Gini–Simpson. Use string(...), interpolation, or an IOBuffer to assemble the markup.

Useful? React with 👍 / 👎.

Comment on lines +15 to +18
id: "exact-descriptive-summaries",
status: "supported",
summary: "Per-sample and per-group integer totals, observed richness, and exact rational proportions.",
implementation: "src/analysis/exact_summaries.jl",

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 Remove or implement exact-mode observed richness

The approved catalogue publishes observed richness as an output of exact-descriptive-summaries, but SampleSummary, GroupSummary, and summary_to_storage provide only counts, totals, and proportions; the new UI even displays “not reported in exact_counts.” Clients using the catalogue to select a supported method therefore cannot obtain one of its advertised results. Either compute and serialize richness for samples and groups or remove it from this method's approved summary.

Useful? React with 👍 / 👎.

Comment thread scripts/statistics/mutation_check.py Outdated
Comment on lines +183 to +184
killed = code != 0
survived.append(mutant.name) if not killed else None

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 Require the baseline tests to pass before mutation

The campaign treats any nonzero test exit as proof that the planted mutant was killed. If the selected test already fails because of an unrelated regression, setup error, or malformed environment, every affected mutant is reported as killed and the report can claim complete: true without showing that the mutation changed the outcome. Run each selected baseline test set on the restored tree first, or otherwise compare mutant results against a known passing baseline.

Useful? React with 👍 / 👎.

Comment on lines +78 to +80
table = CSV.read(input, DataFrame; copycols=false)
ncol(table) >= 2 || _usage("the CSV needs an identifier column and at least one sample")
feature_names = String.(string.(table[!, 1]))

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 Reject biological-validation inputs with no features

A header-only CSV with an identifier column and at least one sample passes this check, producing a 0 × N matrix. Both summaries then classify every sample as a zero-total undefined case, the comparison loop records no failure, and the script exits 0 with complete: true, so an empty dataset can be presented as successful biological validation. Require at least one data row before running the summaries.

Useful? React with 👍 / 👎.

Comment on lines 76 to +79
metrics, achieved = NumericPolicy.with_precision(; bits=policy.precision_bits) do
[_metric(column, policy) for column in columns]
results = Vector{Any}(undef, length(columns))
for j in eachindex(columns)
check_cancelled!(cancellation)

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 Observe deadlines while waiting for the precision lock

For concurrent high-precision requests, with_precision can block on the global _PRECISION_LOCK, but the first cancellation check in this block runs only after that lock has been acquired. A request with a short time_limit_seconds can therefore remain pinned behind a long million-bit calculation well past its deadline before finally returning 408. Use a cancellable/periodically polled lock acquisition or check the token while waiting so the advertised per-request deadline also bounds queueing on this lock.

Useful? React with 👍 / 👎.

Comment on lines +233 to +237
value = if raw isa Integer && !(raw isa Bool)
Float64(raw)
elseif raw isa AbstractFloat
Float64(raw)
else

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 Enforce whole-second deadlines on the run endpoint

The direct endpoint's raw-token pass rejects decimal deadlines, but the run/DuckDB endpoint calls _statistics_body without that pass and this branch explicitly accepts any finite AbstractFloat. Thus POST /api/v1/studies/{study}/runs/{run}/statistics/summaries accepts values such as 1.5, despite the documented shared contract requiring whole seconds and rejecting decimal tokens. Restrict this field to non-Boolean integers, or apply a field-aware lexical check on the run endpoint.

Useful? React with 👍 / 👎.

…lures

- first(with_precision(...) do ... end) binds the do-block to first(), not to
  with_precision(); bind the tuple first and then unwrap it. This affected the
  simulation study and the property-test reference helpers.
- Emit a checks-API annotation with the log tail when the simulation study or
  the mutation campaign fails, so the reason is visible without the raw log.
- Run the mutation campaign even when the simulation step failed.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>

@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: abf91f9caa

ℹ️ 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".

rng = MersenneTwister(seed)
exact_failures = String[]
metric_failures = String[]
maxima = Dict(Int, Dict{String,BigFloat})(

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 Use a parameterized Dict type for simulation maxima

Every simulation run reaches Dict(Int, Dict{String,BigFloat}), which calls the Dict constructor with two type objects instead of constructing a dictionary type. This raises a MethodError before any replicate runs, so the seeded simulation step cannot produce its evidence report even after project dependencies are installed. Use Dict{Int,Dict{String,BigFloat}}(...) to construct the maxima dictionary.

Useful? React with 👍 / 👎.

Comment thread scripts/statistics/mutation_check.jl Outdated
open(log, "w") do io
println(io, "\$ ", command)
flush(io)
return success(pipeline(command; stdout=io, stderr=io, dir=ROOT))

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 Set the working directory on the mutation test command

On the first mutant, _run_tests passes dir=ROOT to pipeline, but Julia's pipeline does not accept a dir keyword; working directories are configured on Cmd instead. The resulting MethodError propagates out of the campaign after the target is restored, without executing the tests or writing a mutation report. Construct Cmd(command; dir=ROOT) before passing it to pipeline.

Useful? React with 👍 / 👎.

@test rejected(doc -> doc["methods"][1]["evidence"] = Any[])
# Flipping an unsupported entry to supported without evidence is refused.
@test rejected(doc -> doc["methods"][3]["status"] = "supported")
@test rejected(doc -> doc["methods"][3]["evidence"] = Any[])

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 Allow empty evidence for an unsupported catalogue entry

With the shipped catalogue, the third method is parametric-model-fits, which is unsupported and already has evidence: []. This mutation therefore leaves the document valid: _validate_method requires nonempty evidence only for supported methods, so rejected(...) returns false and this assertion fails on every baseline run. Test this requirement against a supported entry, or assert acceptance for the unsupported entry, rather than rejecting the catalogue's intentional representation of an unimplemented method.

Useful? React with 👍 / 👎.

Comment on lines +51 to +52
_adv_body(overrides::Dict) = merge(_ADV_BASE, overrides)
_adv_body(key::String, value) = merge(_ADV_BASE, Dict(key => value))

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 Accept Pair arguments in the adversarial request helper

Most callers pass one or more Pair arguments, starting with _adv_body("time_limit_seconds" => bad) in the deadline test and including three-pair calls in the resource-limit tests. Neither helper method accepts those arguments: one requires a Dict, and the other requires a string followed by a value. These calls raise MethodError before reaching the endpoints, aborting the affected testsets and failing the expanded CI suite. Add a variadic Pair overload that builds the override dictionary, or convert the callers to the supported signatures.

Useful? React with 👍 / 👎.

Arena Agent and others added 2 commits October 23, 2026 18:47
The evidence scripts load JSON3 and the statistics modules, so the job cannot
run them against an uninstantiated environment. The Julia tests job already
performs this step; the standards job now does the same.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- Cmd(...; dir=ROOT) is the supported way to set a working directory; pipeline
  has no dir keyword.
- MetaManifold loads RCall, whose build and init need an R installation even
  when no R code runs. The standards job installs the pinned R runtime from
  tool_versions.yml (read with yq) before instantiating the project.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@coderabbitai
coderabbitai Bot requested a review from JoshuaJewell October 23, 2026 18:55

@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.

ℹ️ 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".

Comment on lines +112 to +113
Threads.atomic_xchg!(token.cancelled, false) &&
throw(OperationCancelledError("cancelled by caller"))

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 caller cancellation after it is observed

For a token cancelled through cancel! without a deadline, the first check_cancelled! clears the cancellation flag before throwing, so every subsequent check succeeds. A caller that catches the exception and passes the same token to exact_summary or high_precision_summary can therefore obtain a successful result despite having cancelled that token. Read the atomic flag without resetting it so cancellation remains observable, and cover repeated checks of an explicitly cancelled token as well as an expired deadline.

Useful? React with 👍 / 👎.

@test permuted.samples[j].total == summary.samples[j].total
@test permuted.samples[j].richness == summary.samples[j].richness
if !isnothing(summary.samples[j].shannon)
@test permuted.samples[j].shannon == summary.samples[j].shannon

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 Compare permuted Shannon values with the declared tolerance

When a permutation changes the order of entropy terms, _metric accumulates them in a different order using finite-precision MPFR subtraction, so mathematically equivalent inputs need not produce bit-identical Shannon values. I reproduced this with 256-bit MPFR for counts [123456, 654321, 981234, 432198] and the permutation [981234, 432198, 654321, 123456]. This exact-equality assertion can therefore reject correct results in the seeded property suite and fail CI. Use the existing _close tolerance for Shannon here; Gini–Simpson can retain exact equality because its accumulation uses integer arithmetic.

Useful? React with 👍 / 👎.

Arena Agent and others added 3 commits October 23, 2026 19:17
- The _statistics_cancellation docstring ended with a stray ')' instead of the
  closing triple quote, which made the whole server module unparseable.
- join(gen, delim) needs its generator parenthesised; the large-matrix UI test
  lacked them.
Both were caught by CI; a tree-sitter parse pass over every .jl file in the
repository now shows no errors in changed files.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
The governance contract allows exactly two exit-preserving pipelines in ci.yml;
the two evidence steps added a second pair and tripped test-ci-logging.sh.
Rather than relax the contract, the logic moves into scripts/ci/run-with-log.sh,
which the same test now exercises directly: producer status preserved, failure
annotated with an escaped log tail, log retained.

scripts/ci/install-r-runtime.sh does the pinned R install for both jobs
(core for the standards job, full for the Julia suite), which also removes the
duplicated wget block SonarCloud flagged.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
shell:S6506 is a vulnerability, so it moves the security rating on its own.
--https-only constrains the first request only; curl with both --proto and
--proto-redir is the spelling this repository already uses for every pinned
download, and the key is now written from a private temporary file so a
truncated download is never left in /usr/share/keyrings.

Also: [[ instead of [ throughout the new scripts, the failure annotation moves
to stderr (the runner parses workflow commands on both streams), and
docs/sonar-quality-gate.md records the rule and the reasoning, as that page
requires.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>

@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: 3cbda4101f

ℹ️ 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".

Comment on lines +216 to +218
for bad in (9007199254740992, "-1", "1.5", "1e3")
body = _adv_body("counts" => [[bad, 2], [3, 4]])
@test _adv_post("/api/v1/statistics/summaries", body).status == 422

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 Expect HTTP 400 for the unsafe integer token

Once the request helper accepts Pair arguments, the 9007199254740992 case still fails this assertion: _statistics_body calls ijson_read, whose unsafe-integer check in src/canonical.jl throws ArgumentError, and _statistics_guard maps that exception to HTTP 400, not 422. The new boundary suite already expects 400 for the same token. Separate this numeric-token case from the invalid count strings and expect 400 so the adversarial suite does not reject correct endpoint behavior.

Useful? React with 👍 / 👎.

@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 23, 2026 19:44
@sonarqubecloud

Copy link
Copy Markdown

@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: 1c22ba72ba

ℹ️ 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".

"complete" => isempty(survived),
)
open(output, "w") do io
println(io, JSON3.pretty(report))

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 Write the evidence JSON directly to the report stream

When the mutation campaign finishes, JSON3.pretty(report) prints the JSON to stdout and returns nothing, so this writes only nothing\n into the report file. Consequently, the standards job uploads an invalid JSON artifact instead of the mutation evidence, even if the campaign succeeds. The same mistake affects the --output branches in simulation_study.jl and biological_validation.jl. Pass io directly to JSON3.pretty(io, report) in all three scripts; the pinned version's implementation explicitly defaults the one-argument overload to stdout.

Useful? React with 👍 / 👎.

@hyperpolymath
hyperpolymath merged commit 60322bf into main Oct 23, 2026
23 of 26 checks passed
@hyperpolymath
hyperpolymath deleted the arena/3d3fe618-metamanifold-webui branch October 23, 2026 19:59
hyperpolymath added a commit that referenced this pull request Oct 23, 2026
…259)

Follow-up to #257, which merged with its statistics jobs still red: the
two
committed bugs below were only reachable once the job got past
precompilation,
so the evidence gate never ran to completion on the merged commit.

## What was broken

- **`_html_escape` called `String(value)`.** Storage dictionaries carry
integers
as JSON numbers (`precision_bits`, `round_digits`, `richness`,
diagnostics),
and `String(::Int)` is a `MethodError`. Every result page therefore fell
into
its 500 branch, and the UI tests saw the failure block instead of a
result.
  `string(value)` is the contract: any printable value is rendered.
- **`Dict(Int, Dict{String,BigFloat})(...)`** in the simulation study
called the
two-argument `Dict` constructor instead of parametrising `Dict`, so the
study
  threw a `MethodError` before running a single replicate.

## Diagnostics

The failure digest in the Julia job cut nothing, so a single evaluated
HTML page
filled every annotation and hid the assertions that failed. Each line is
now cut
to 320 characters and the chunks are larger, so the digest names the
failures
instead of reproducing a page.

## Evidence

The `Statistics standards and evidence` and `Julia tests` jobs run on
this PR;
the remaining statistics failures (property tolerances, storage
round-trip) are
being diagnosed from those annotations, not assumed fixed.

Refs #1.

---------

Co-authored-by: Arena Agent <agent@arena.ai>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
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.

1 participant