infra: stop shared-file conflicts (per-unit plan files, reports from CI, union merges)

- plan/modules.toml -> plan/units/<id>.toml (scripts/units-split.py), read everywhere
  through harness/plan/units.py (Python) and crates/difftest/src/plan.rs (difftest).
- reports/difftest/ untracked and gitignored: CI uploads main's set as the
  difftest-reports artifact; scripts/fetch-reports.sh downloads it for the progress
  checklist, the site and the --jobs queue order (fixture-size fallback otherwise).
- .gitattributes: merge=union for plan/findings.md and plan/upstream-issues.md.
- scripts/units-migrate-branch.sh moves an old branch's modules.toml edits into the
  unit files after it merges main.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
bherbruck
2026-10-21 19:39:59 -04:00
parent 1b7f113f9a
commit fe4a9c1425
536 changed files with 3977 additions and 4491429 deletions
+4
View File
@@ -0,0 +1,4 @@
# Append-only logs: a local `git merge` keeps both sides' new entries instead of
# conflicting. GitHub's own mergeability check ignores this, so merge main locally.
plan/findings.md merge=union
plan/upstream-issues.md merge=union
+37 -2
View File
@@ -83,6 +83,9 @@ jobs:
difftest:
runs-on: blacksmith-16vcpu-ubuntu-2404
needs: [test]
permissions:
contents: read
actions: read # scripts/fetch-reports.sh reads main's report artifact
env:
SOLIDCORE_CPP_DIR: ${{ github.workspace }}/.cpp
steps:
@@ -91,11 +94,11 @@ jobs:
- name: Skip when no unit is green
id: green
run: |
if [ -f plan/modules.toml ] && grep -Eq '^\s*status\s*=\s*"green"' plan/modules.toml; then
if grep -Eqs '^\s*status\s*=\s*"(green|partial)"' plan/units/*.toml; then
echo "any=true" >> "$GITHUB_OUTPUT"
else
echo "any=false" >> "$GITHUB_OUTPUT"
echo "No green units in plan/modules.toml; nothing to difftest."
echo "No green units in plan/units/; nothing to difftest."
fi
- name: Clone upstream at pinned commit
@@ -181,6 +184,14 @@ jobs:
if: steps.green.outputs.any == 'true'
run: cargo clippy --workspace --all-targets --features difftest/cpp -- -D warnings
# Reports are not committed. main's latest set (uploaded below) only orders the
# --jobs queue, heaviest unit first; without it difftest estimates from fixtures.
- name: Fetch main's difftest reports (queue order)
if: steps.green.outputs.any == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: scripts/fetch-reports.sh || echo "no previous reports; queue ordered by fixture size"
- name: Difftest green units
if: steps.green.outputs.any == 'true'
# Optimised profile (Cargo.toml [profile.difftest]): identical results, about 20x
@@ -188,6 +199,30 @@ jobs:
# process per unit, one per vCPU (same output and reports as a serial run).
run: cargo run --profile difftest -p difftest --features cpp -- --green --jobs 0
# main's reports are published from here (site, PROGRESS.md case counts,
# scripts/fetch-reports.sh), never committed.
- name: Keep only reports of green/partial units
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.green.outputs.any == 'true' && !cancelled()
run: |
python3 - <<'PY'
import pathlib, sys
sys.path.insert(0, "harness/plan")
import units
keep = {u["id"] for u in units.load_units() if u.get("status") in ("green", "partial")}
for p in pathlib.Path("reports/difftest").glob("*.json"):
if p.stem not in keep:
p.unlink()
PY
- name: Upload difftest reports
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.green.outputs.any == 'true' && !cancelled()
uses: actions/upload-artifact@v4
with:
name: difftest-reports
path: reports/difftest/*.json
if-no-files-found: error
retention-days: 90
# The runners' own unit tests (guards, decoders, probes) need the C++ reference, so
# the test job cannot run them. Same profile as above: only the test harness of the
# difftest crate is compiled on top of that build.
+6
View File
@@ -21,6 +21,7 @@ on:
permissions:
contents: read
actions: read # download main's difftest-reports artifact
pages: write
id-token: write
@@ -48,6 +49,11 @@ jobs:
else
echo "build=true" >> "$GITHUB_OUTPUT"
fi
- name: Fetch main's difftest reports
if: steps.gate.outputs.build == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: scripts/fetch-reports.sh || echo "no reports; unit pages will say so"
- name: Build site
if: steps.gate.outputs.build == 'true'
run: python3 site/build.py --out _site
+20 -5
View File
@@ -1,16 +1,20 @@
name: Progress checklist
# Regenerates plan/PROGRESS.md from plan/modules.toml, committed difftest reports
# and open "port: <unit id>" PRs, and commits it to main when it changed.
# PRs never edit PROGRESS.md themselves.
# Regenerates plan/PROGRESS.md from plan/units/*.toml, main's difftest reports (CI
# artifact, scripts/fetch-reports.sh) and open "port: <unit id>" PRs, and commits it
# to main when it changed. PRs never edit PROGRESS.md themselves.
on:
push:
branches: [main]
paths:
- plan/modules.toml
- reports/difftest/*.json
- plan/units/**
- harness/plan/progress.py
- harness/plan/units.py
- harness/plan/test_progress.py
workflow_run: # main's CI uploaded fresh reports (case counts)
workflows: ["CI"]
types: [completed]
branches: [main]
pull_request_target:
types: [opened, reopened, closed, edited, ready_for_review, converted_to_draft]
schedule:
@@ -20,6 +24,7 @@ on:
permissions:
contents: write
pull-requests: read
actions: read # download main's difftest-reports artifact
concurrency:
group: progress
@@ -33,13 +38,23 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 (pinned: this job has contents: write)
with:
ref: main
fetch-depth: 0 # fetch-reports.sh falls back to the last committed reports
- name: Test progress generator
run: python3 -m unittest discover -s harness/plan -p 'test_*.py'
- name: Fetch main's difftest reports
id: reports
env:
GH_TOKEN: ${{ github.token }}
run: |
if scripts/fetch-reports.sh; then echo "ok=true" >> "$GITHUB_OUTPUT"
else echo "No reports: keeping PROGRESS.md (case counts would be lost)."; fi
- name: Regenerate
if: steps.reports.outputs.ok == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: python3 harness/plan/progress.py --prs
- name: Commit if changed
if: steps.reports.outputs.ok == 'true'
run: |
if git diff --quiet -- plan/PROGRESS.md; then echo "unchanged"; exit 0; fi
git config user.name "github-actions[bot]"
+5
View File
@@ -15,3 +15,8 @@ target/
# Third-party test corpora (scripts/fetch-ssi-corpus.sh); never committed
/corpus
__pycache__/
# Difftest reports: generated by difftest, uploaded by CI from main (artifact
# difftest-reports, scripts/fetch-reports.sh); never committed
/reports/difftest/
+36 -10
View File
@@ -9,7 +9,7 @@ crates/solidcore the kernel (pure Rust, no unsafe, wasm-ok) owner:
crates/solidcore-ffi extern "C" bindings to the C++ kernel (feature cpp)
crates/difftest side-by-side Rust vs C++ runner
harness/cpp C++ reference build (build.sh -> bin/cpp) + shim/<unit>.cpp
plan/ modules.toml (units, claims), STATUS.md, findings.md, order.md
plan/ units/<id>.toml (one file per unit), STATUS.md, findings.md, order.md
```
## 1. Hard rules
@@ -139,15 +139,15 @@ Every ported file starts with:
## 4. Porting a unit (PR workflow)
Unit list and states: `plan/modules.toml` (format: `plan/modules.schema.md`, order:
`plan/order.md`). **`plan/PROGRESS.md` is the checklist** (regenerated on `main` by CI;
Unit list and states: `plan/units/<unit id>.toml`, one file per unit (format:
`plan/modules.schema.md`, order: `plan/order.md`). **`plan/PROGRESS.md` is the checklist** (regenerated on `main` by CI;
never edit it in a PR). **Any `todo` unit can be claimed.** A unit is *ready* when its `depends_on` are all
`green` or `partial` (`soft_depends_on` never blocks; see section 4a); ready units are
the easiest, lowest `layer` first. Claiming a unit that is not ready is fine:
- Calls into a missing dependency are stubbed (`UNPORTED(<unit>)`, cases deferred; 4a).
- If you need a **type** (struct, enum variant, base class) from a missing dependency,
port the minimum of it yourself and record it in that unit's `notes` in
`plan/modules.toml` as `CO-PORTED in <your unit> (PR #n): <C++ symbols> -> <Rust path>`
`plan/units/<that unit>.toml` as `CO-PORTED in <your unit> (PR #n): <C++ symbols> -> <Rust path>`
so its eventual porter extends your code instead of duplicating it.
- If that dependency has an open `port:` PR, do not port the same code twice: build on
that PR's branch (merge it into yours) or agree on the split in that PR's comments.
@@ -161,7 +161,7 @@ into `upstream/` (see README), then run `scripts/fetch-cpp.sh`, or
latest `main` (`git fetch origin && git switch -c unit/<unit id> origin/main`),
`git commit --allow-empty -m "claim: <unit id>"`, push, and open a draft PR titled
exactly **`port: <unit id>`**. **The lowest-numbered open PR for a unit wins**; if
yours lost, close it. Do not edit `plan/modules.toml` to claim. Push WIP at least
yours lost, close it. Do not edit `plan/units/` to claim. Push WIP at least
daily; a draft PR with no pushes for 48 h may be taken over (comment on it first).
If the unit's `notes` mention a WIP branch on `origin`, start from it.
2. **Port** the upstream functions the unit owns (listed in
@@ -207,11 +207,11 @@ into `upstream/` (see README), then run `scripts/fetch-cpp.sh`, or
readers bound header counts; input-driven recursion is bounded (section 1).
9. **`UNPORTED` stubs only for calls into units that are not `green`/`partial`**,
tagged with the owning unit from `harness/callgraph/units.json`; co-ports are
recorded as `CO-PORTED` in `plan/modules.toml` notes.
recorded as `CO-PORTED` in that unit's `plan/units/<id>.toml` notes.
6. **Finish the PR**: merge the latest `origin/main` into your branch (never rebase a
pushed branch), re-verify, set the unit's `status` to `"green"` or `"partial"` in
`plan/modules.toml` with case/deferred counts in `notes` (plus any units you
promoted), commit, push, and mark the PR ready. Put the difftest summary lines in
`plan/units/<unit id>.toml` with case/deferred counts in `notes` (plus the files of
any units you promoted), commit, push, and mark the PR ready. Put the difftest summary lines in
the PR description. CI runs fmt, clippy, tests, wasm, difftest on every green or
partial unit, and the difftest runner tests. **CI is the merge gate.** Once CI is
green, a maintainer adds the PR to the merge queue after a quick check (stub tags,
@@ -219,6 +219,27 @@ into `upstream/` (see README), then run `scripts/fetch-cpp.sh`, or
with the latest `main`. Deep adversarial review happens after merge; anything it
finds comes back as a follow-up issue or PR, so keep the step-5 checklist honest.
**Shared files (avoid merge conflicts).** Every open PR touches the same plan, so:
- Edit only `plan/units/<id>.toml` of your unit (and of units you promote or co-port
into). There is no shared `plan/modules.toml` any more.
- Never commit `reports/difftest/` (gitignored). difftest still writes your reports
there locally; CI regenerates them, uploads main's set as the `difftest-reports`
artifact, and the site and `plan/PROGRESS.md` read that
(`scripts/fetch-reports.sh` downloads it). Quote your summary lines in the PR instead.
- `plan/findings.md` and `plan/upstream-issues.md` are append-only: add new entries,
do not rewrite old ones. `.gitattributes` gives them `merge=union`, so a local
`git merge origin/main` keeps both sides' entries. GitHub's own conflict check
ignores that attribute, so when GitHub says your PR conflicts, merge main locally
and push.
- **Branches from before the per-unit split** (they edit `plan/modules.toml` or commit
reports): merge main, then run the migration, which moves your `modules.toml` edits
into `plan/units/*.toml` and untracks your reports:
```sh
git fetch origin && git merge origin/main; scripts/units-migrate-branch.sh && git commit --no-edit
```
It reports a `CONFLICT` for a field main also changed (it keeps yours; check it) and
lists any other conflicted files for you to resolve before committing.
**Blocked** (gate cannot be met, upstream behaviour unclear): record details in
`plan/findings.md`, set `status = "blocked"` with a reason in `notes`, and open the PR
with just that so others can see it. Never sit on a draft PR you have stopped working
@@ -251,10 +272,15 @@ The kernel core is one big call cycle, so the plan dropped ~2,300 calls as *back
## 5. Where things go
- `plan/units/<id>.toml`: one unit's plan entry (status, claims, notes). Edit only
your unit's file. Every tool reads them through `harness/plan/units.py` (Rust:
`crates/difftest/src/plan.rs`).
- `plan/findings.md`: Rust-vs-C++ disagreements, upstream bugs, nondeterminism (e.g.
upstream `srand(time(NULL))`), anything a later agent must know.
upstream `srand(time(NULL))`), anything a later agent must know. Append-only.
- `plan/upstream-issues.md`: upstream C++ defects also get an entry here (problems only,
with location, trigger, how found and whether the C++ build confirmed it).
with location, trigger, how found and whether the C++ build confirmed it). Append-only.
- `reports/difftest/<unit>.json`: difftest output. Not committed: CI uploads main's set
as an artifact; `scripts/fetch-reports.sh` downloads it.
- `plan/PROGRESS.md`: the checklist (generated; never edit by hand).
- `plan/STATUS.md`: overall progress summary and handoff notes.
- `bin/`: all build output (cargo `target-dir`, `bin/cpp/` for C++). Gitignored. Never
+6
View File
@@ -114,6 +114,12 @@ Contributions are pull requests, one per port unit, and AI agents are welcome:
2. Claim it by opening a draft PR titled `port: <unit id>` (lowest-numbered PR wins).
3. Port it, prove it with difftest against the C++ reference, mark the PR ready.
To keep parallel PRs from conflicting: edit only your unit's `plan/units/<unit id>.toml`,
never commit `reports/difftest/` (CI generates them), and only append to
`plan/findings.md` and `plan/upstream-issues.md`. A branch started before the per-unit
split migrates with `git fetch origin && git merge origin/main;
scripts/units-migrate-branch.sh && git commit --no-edit`.
The full rules, style and step-by-step workflow are in [AGENTS.md](AGENTS.md) (point your
agent at it).
+11 -7
View File
@@ -3,7 +3,7 @@
`difftest` runs every case of a unit through **upstream SMLib (C++, via
`solidcore-ffi`)** and the **solidcore Rust port** on identical inputs and
compares the results. A unit may be marked `status = "green"` in
`plan/modules.toml` only when `difftest --status-of <id>` prints `green`, and
`plan/units/<id>.toml` only when `difftest --status-of <id>` prints `green`, and
`status = "partial"` only when it prints `partial` (AGENTS.md section 4a).
## Quick start
@@ -26,7 +26,7 @@ nice -n 10 cargo test -p difftest --features cpp # harness s
|---|---|
| `--unit <id>` | run one unit (repeatable; `*` and `?` match several registered runners, e.g. `--unit 'nlib.*'`) |
| `--jobs N` / `-j N` | run N units at a time, each in its own child process (default `1`: one process, in order; `0`: every core). Output, reports and exit status are the same as with `1` (below) |
| `--green` | all units with `status = "green"` or `"partial"` in `plan/modules.toml` (one without a runner FAILS; a `green` unit that comes out partial FAILS) |
| `--green` | all units with `status = "green"` or `"partial"` in `plan/units/*.toml` (one without a runner FAILS; a `green` unit that comes out partial FAILS) |
| `--status-of <id>` | run the unit (no report) and print only `green`, `partial` or `fail`; exit `1` on `fail` (also when no runner is registered) |
| `--all` | every registered runner |
| `--list` | registered runners, their plan status and case counts |
@@ -94,7 +94,8 @@ With `--jobs N` and more than one unit (`--green`, `--all`, several or a glob of
<id>` with the other options; the C++ kernel keeps global state, so units never share a
process or run on threads). At most N children run at once; the queue is ordered longest
first by the `cases_total` of each unit's previous report (in `--report-dir`, else
`reports/difftest/`), and the next unit starts as soon as a child exits. The parent
`reports/difftest/`; a unit with no report is estimated from the size of its
`fixtures/<id>/`, about 512 bytes a case), and the next unit starts as soon as a child exits. The parent
prints each unit's lines in the serial order and the usual summary line, so stdout,
`reports/difftest/*.json` and the exit status are identical to a serial run's. Timing
goes to stderr only: `difftest --jobs N: wall … s, sum of unit times … s, longest unit
@@ -417,11 +418,12 @@ nice -n 10 cargo run --profile difftest -p difftest --features cpp -- --unit foo
nice -n 10 cargo run --profile difftest -p difftest --features cpp -- --unit foo.bar --perturb # must say SENSITIVE
cargo clippy -p difftest -p solidcore-ffi --features difftest/cpp --all-targets -- -D warnings
git add harness/cpp/shim/foo_bar.cpp crates/solidcore-ffi/src/units/foo_bar.rs \
crates/difftest/src/units/foo_bar.rs fixtures/foo.bar reports/difftest/foo.bar.json
crates/difftest/src/units/foo_bar.rs fixtures/foo.bar plan/units/foo.bar.toml
```
Commit the report produced with the default `--seeds` (it is deterministic, so
diffs in it are meaningful). Then set `status` to what
Do not commit `reports/difftest/foo.bar.json` (gitignored; CI regenerates every
green/partial unit's report and publishes main's set). Quote its summary line in the
PR instead. Then set `status` in `plan/units/foo.bar.toml` to what
`--status-of foo.bar` prints (`green` or `partial`; never on `fail`).
## `--ssi-corpus`: exact ground-truth SSI corpus
@@ -546,7 +548,9 @@ nice -n 10 cargo run -p difftest -- --solidcraft-cases '3526-*' # ids (<f
`wasm32-unknown-unknown`; the difftest binary refuses to run without `cpp`, except for `--solidcraft-cases` (Rust only).
* Debugging: the binary is `bin/debug/difftest`; set breakpoints with
mcp-debugger (the C++ kernel is built with `-g`).
* Reports: `reports/difftest/<unit>.json` — sorted keys, no timestamps,
* Reports: `reports/difftest/<unit>.json` — not committed (gitignored): CI uploads
main's set as the `difftest-reports` artifact, `scripts/fetch-reports.sh`
downloads it. Sorted keys, no timestamps,
shortest round-trip floats, non-finite floats as `"NaN"`/`"inf"`; failing
cases include inputs and up to 20 mismatches.
* Reference platform: x86-64 Linux (as CI). Upstream converts out-of-range
+60 -19
View File
@@ -3,12 +3,12 @@
//!
//! The C++ kernel keeps global state, so units never share a process (no threads). The
//! parent hands out units dynamically from one queue, longest first (by the case count
//! of each unit's previous report in the report directory), and spawns the next one as
//! soon as a child exits. A child is the same binary run as `--unit <id>` with the
//! caller's other options and [`WORKER_ENV`] set; it prints and writes its report
//! exactly as a serial run does. The parent prints each child's output in the serial
//! order (as soon as every earlier unit is done) and the usual final summary, so stdout
//! and the reports are identical to a serial run's.
//! of each unit's previous report in the report directory, else an estimate from its
//! fixture size), and spawns the next one as soon as a child exits. A child is the same
//! binary run as `--unit <id>` with the caller's other options and [`WORKER_ENV`] set;
//! it prints and writes its report exactly as a serial run does. The parent prints each
//! child's output in the serial order (as soon as every earlier unit is done) and the
//! usual final summary, so stdout and the reports are identical to a serial run's.
//!
//! A child that crashes (signal, unexpected exit, no summary line) fails only its own
//! unit, with the tail of its stderr. Children are killed when the parent returns;
@@ -93,20 +93,40 @@ pub fn forwarded_args(raw: &[String]) -> Vec<String> {
out
}
/// Case count of the first `<dir>/<id>.json` found in `dirs` (0 when there is none):
/// the scheduling weight.
fn previous_cases(dirs: &[&Path], id: &str) -> u64 {
/// Case count of the first `<dir>/<id>.json` found in `dirs`.
fn previous_cases(dirs: &[&Path], id: &str) -> Option<u64> {
dirs.iter()
.find_map(|d| std::fs::read_to_string(d.join(format!("{id}.json"))).ok())
.and_then(|t| serde_json::from_str::<serde_json::Value>(&t).ok())
.and_then(|v| v.get("cases_total").and_then(serde_json::Value::as_u64))
.unwrap_or(0)
}
/// Queue order: heaviest previous report (looked up in `dirs`, in order) first, ties
/// (and units without a report) in the serial order.
pub fn schedule(units: &[String], dirs: &[&Path]) -> Vec<usize> {
let weights: Vec<u64> = units.iter().map(|u| previous_cases(dirs, u)).collect();
/// Fixture bytes per case, roughly, for [`fixture_weight`].
const FIXTURE_BYTES_PER_CASE: u64 = 512;
/// Estimated case count of a unit with no previous report: total size of
/// `<fixtures>/<id>/*.json` at about [`FIXTURE_BYTES_PER_CASE`] bytes a case (reports
/// are CI artifacts, not committed, so a fresh checkout has none).
fn fixture_weight(fixtures: &Path, id: &str) -> u64 {
let Ok(rd) = std::fs::read_dir(fixtures.join(id)) else {
return 0;
};
rd.filter_map(Result::ok)
.filter(|e| e.path().extension().and_then(|x| x.to_str()) == Some("json"))
.filter_map(|e| e.metadata().ok())
.map(|m| m.len())
.sum::<u64>()
/ FIXTURE_BYTES_PER_CASE
}
/// Queue order: heaviest first, ties in the serial order. The weight is the case count
/// of the unit's previous report (looked up in `dirs`, in order), else its fixture
/// estimate under `fixtures` (see [`fixture_weight`]).
pub fn schedule(units: &[String], dirs: &[&Path], fixtures: &Path) -> Vec<usize> {
let weights: Vec<u64> = units
.iter()
.map(|u| previous_cases(dirs, u).unwrap_or_else(|| fixture_weight(fixtures, u)))
.collect();
let mut order: Vec<usize> = (0..units.len()).collect();
order.sort_by_key(|&i| (std::cmp::Reverse(weights.get(i).copied().unwrap_or(0)), i));
order
@@ -250,8 +270,15 @@ fn spawn(exe: &Path, args: &[String], id: &str, unit: usize) -> std::io::Result<
/// Runs `units` in up to `jobs` child processes and prints like the serial loop in
/// `main.rs`: each unit's lines in `units` order, then the summary line. `weights` are
/// the report directories whose previous reports order the queue (see [`schedule`]).
pub fn run_parallel(units: &[String], args: &[String], jobs: usize, weights: &[&Path]) -> ExitCode {
/// the report directories whose previous reports order the queue, `fixtures` the
/// fixture root for units without one (see [`schedule`]).
pub fn run_parallel(
units: &[String],
args: &[String],
jobs: usize,
weights: &[&Path],
fixtures: &Path,
) -> ExitCode {
let exe = match std::env::current_exe() {
Ok(e) => e,
Err(e) => {
@@ -260,7 +287,7 @@ pub fn run_parallel(units: &[String], args: &[String], jobs: usize, weights: &[&
}
};
let wall = Instant::now();
let mut queue: VecDeque<usize> = schedule(units, weights).into();
let mut queue: VecDeque<usize> = schedule(units, weights, fixtures).into();
let mut results: Vec<Option<UnitRun>> = vec![None; units.len()];
let mut times: Vec<Duration> = vec![Duration::ZERO; units.len()];
let mut printed = 0usize;
@@ -444,11 +471,25 @@ mod tests {
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(dir.join("b.json"), r#"{"cases_total": 5}"#).unwrap();
std::fs::write(dir.join("c.json"), r#"{"cases_total": 50}"#).unwrap();
let fixtures = dir.join("fixtures");
let none = dir.join("none");
let order = schedule(
&s(&["a", "b", "c", "d"]),
&[dir.join("none").as_path(), &dir],
&[none.as_path(), &dir],
&fixtures,
);
assert_eq!(order, vec![2, 1, 0, 3]);
// Without a report, fixture size estimates the weight (b's report still wins).
std::fs::create_dir_all(fixtures.join("a")).unwrap();
std::fs::create_dir_all(fixtures.join("b")).unwrap();
std::fs::write(fixtures.join("a").join("x.json"), vec![b' '; 10 * 512]).unwrap();
std::fs::write(fixtures.join("b").join("x.json"), vec![b' '; 100 * 512]).unwrap();
let order = schedule(
&s(&["a", "b", "c", "d"]),
&[none.as_path(), &dir],
&fixtures,
);
let _ = std::fs::remove_dir_all(&dir);
assert_eq!(order, vec![2, 1, 0, 3]);
assert_eq!(order, vec![2, 0, 1, 3]);
}
}
+4 -3
View File
@@ -2,7 +2,7 @@
//!
//! ```text
//! cargo run -p difftest --features cpp -- --unit <id> [--unit <id>...]
//! cargo run -p difftest --features cpp -- --green # all status=green|partial units in plan/modules.toml
//! cargo run -p difftest --features cpp -- --green # all status=green|partial units in plan/units/*.toml
//! cargo run -p difftest --features cpp -- --green --jobs 0 # same, one child process per unit, all cores
//! cargo run -p difftest --features cpp -- --all # every registered runner
//! cargo run -p difftest --features cpp -- --list
@@ -272,10 +272,11 @@ fn main() -> ExitCode {
let jobs = difftest::jobs::resolve(args.jobs.unwrap_or(1)).min(wanted.len());
if jobs > 1 {
let fwd = difftest::jobs::forwarded_args(&raw);
// Previous reports order the queue; a fresh --report-dir falls back to the default.
// Previous reports order the queue; a fresh --report-dir falls back to the default,
// and a unit with no report anywhere to its fixture size (reports are not committed).
let default_dir = root.join("reports").join("difftest");
let dirs = [report_dir.as_path(), default_dir.as_path()];
return difftest::jobs::run_parallel(&wanted, &fwd, jobs, &dirs);
return difftest::jobs::run_parallel(&wanted, &fwd, jobs, &dirs, &root.join("fixtures"));
}
let mut failed = 0usize;
+81 -41
View File
@@ -1,11 +1,12 @@
//! Reads unit ids/statuses from `plan/modules.toml` (format: `plan/modules.schema.md`).
//! Reads unit ids/statuses from `plan/units/<id>.toml`, one file per unit (format:
//! `plan/modules.schema.md`; the Python twin is `harness/plan/units.py`).
use std::fs;
use std::path::Path;
use crate::HarnessError;
/// One `[[unit]]` entry (only the fields difftest needs).
/// One unit file (only the fields difftest needs).
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PlanUnit {
/// Unit id.
@@ -25,48 +26,60 @@ pub const STATUSES: &[&str] = &[
"out_of_scope",
];
/// Parses `<root>/plan/modules.toml`.
/// Loads every `<root>/plan/units/*.toml`, sorted by id. Each file's `id` must equal
/// its file name.
pub fn load(root: &Path) -> Result<Vec<PlanUnit>, HarnessError> {
let path = root.join("plan").join("modules.toml");
let text = fs::read_to_string(&path)
.map_err(|e| HarnessError::new(format!("{}: {e}", path.display())))?;
parse(&text).map_err(|e| HarnessError::new(format!("{}: {e}", path.display())))
}
/// Parses modules.toml text.
pub fn parse(text: &str) -> Result<Vec<PlanUnit>, String> {
let v: toml::Value = toml::from_str(text).map_err(|e| e.to_string())?;
let units = v
.get("unit")
.and_then(toml::Value::as_array)
.cloned()
.unwrap_or_default();
let dir = root.join("plan").join("units");
let rd =
fs::read_dir(&dir).map_err(|e| HarnessError::new(format!("{}: {e}", dir.display())))?;
let mut files: Vec<_> = rd
.filter_map(|e| e.ok().map(|e| e.path()))
.filter(|p| p.extension().and_then(|e| e.to_str()) == Some("toml"))
.collect();
files.sort();
let mut out = Vec::new();
for (i, u) in units.iter().enumerate() {
let id = u
.get("id")
.and_then(toml::Value::as_str)
.ok_or_else(|| format!("unit #{i}: missing id"))?;
let status = u
.get("status")
.and_then(toml::Value::as_str)
.unwrap_or("todo");
if !STATUSES.contains(&status) {
return Err(format!(
"unit {id}: unknown status `{status}` (expected one of {})",
STATUSES.join(", ")
));
for path in files {
let err = |e: String| HarnessError::new(format!("{}: {e}", path.display()));
let text = fs::read_to_string(&path).map_err(|e| err(e.to_string()))?;
let unit = parse_unit(&text).map_err(err)?;
let stem = path.file_stem().and_then(|s| s.to_str()).unwrap_or("");
if unit.id != stem {
return Err(err(format!(
"id `{}` does not match the file name",
unit.id
)));
}
out.push(PlanUnit {
id: id.to_string(),
status: status.to_string(),
});
out.push(unit);
}
out.sort_by(|a, b| a.id.cmp(&b.id));
Ok(out)
}
/// Parses the text of one unit file (top-level `id`, `status`, ...).
pub fn parse_unit(text: &str) -> Result<PlanUnit, String> {
let v: toml::Value = toml::from_str(text).map_err(|e| e.to_string())?;
let id = v
.get("id")
.and_then(toml::Value::as_str)
.ok_or_else(|| "missing id".to_string())?;
let status = v
.get("status")
.and_then(toml::Value::as_str)
.unwrap_or("todo");
if !STATUSES.contains(&status) {
return Err(format!(
"unit {id}: unknown status `{status}` (expected one of {})",
STATUSES.join(", ")
));
}
Ok(PlanUnit {
id: id.to_string(),
status: status.to_string(),
})
}
/// Ids of units with `status = "green"` or `"partial"` (what `--green` runs), in
/// file order.
/// the order of `units` (by id, as [`load`] returns them).
pub fn green_units(units: &[PlanUnit]) -> Vec<String> {
units
.iter()
@@ -81,11 +94,38 @@ mod tests {
#[test]
fn parses_green() {
let t =
"[[unit]]\nid = \"a\"\nstatus = \"green\"\n[[unit]]\nid = \"b\"\nstatus = \"todo\"\n\
[[unit]]\nid = \"c\"\nstatus = \"partial\"\n";
let u = parse(t).unwrap();
let u: Vec<PlanUnit> = [
"id = \"a\"\nstatus = \"green\"\n",
"id = \"b\"\nstatus = \"todo\"\n",
"id = \"c\"\nstatus = \"partial\"\n# trailing comment\n",
]
.iter()
.map(|t| parse_unit(t).unwrap())
.collect();
assert_eq!(green_units(&u), vec!["a".to_string(), "c".to_string()]);
assert!(parse("[[unit]]\nid = \"x\"\nstatus = \"done\"\n").is_err());
assert!(parse_unit("id = \"x\"\nstatus = \"done\"\n").is_err());
assert!(parse_unit("status = \"green\"\n").is_err());
}
#[test]
fn loads_unit_dir_and_checks_file_names() {
let dir = std::env::temp_dir().join(format!("difftest-plan-{}", std::process::id()));
let units = dir.join("plan").join("units");
fs::create_dir_all(&units).unwrap();
fs::write(units.join("b.y.toml"), "id = \"b.y\"\nstatus = \"green\"\n").unwrap();
fs::write(
units.join("a.x.toml"),
"id = \"a.x\"\nstatus = \"partial\"\n",
)
.unwrap();
fs::write(units.join("README"), "not a unit").unwrap();
let got = load(&dir).unwrap();
assert_eq!(
green_units(&got),
vec!["a.x".to_string(), "b.y".to_string()]
);
fs::write(units.join("c.toml"), "id = \"other\"\n").unwrap();
assert!(load(&dir).is_err());
fs::remove_dir_all(&dir).unwrap();
}
}
+2 -2
View File
@@ -14,13 +14,13 @@ python3 harness/callgraph/why.py SmPoly.cpp --group boolean # restrict
|---|---|---|
| 1 | `extract.py` | `tu/*.json`: per-TU definitions, call edges, classes, globals (libclang over `bin/cpp/compile_commands.json`) |
| 2 | `build_graph.py` | `graph.json`, `closure.json` (CHA + RTA closures from `entrypoints.py` roots), `files.json`, `resolve.json`, `overriders.json` |
| 3 | `plan_units.py` | `plan/modules.toml`, `plan/order.md`, `harness/callgraph/units.json`, `plan_summary.json` |
| 3 | `plan_units.py` | `plan/units/<id>.toml`, `plan/order.md`, `harness/callgraph/units.json`, `plan_summary.json` |
| 4 | `write_closure.py` | `plan/closure.md`, `harness/callgraph/unused_functions.txt` |
Other files: `entrypoints.py` (in-scope SM_API entry points and kernel roots), `pp.py` (`#if`
evaluator for text scans), `scc_probe.py` (function-level SCC statistics), `why.py`.
`units.json` maps every unit id in `plan/modules.toml` to the exact upstream functions (qualified
`units.json` maps every unit id in `plan/units/` to the exact upstream functions (qualified
name, file, line, line count, clang USR) it owns. A unit that names a file in `upstream` owns only
the listed functions of that file; other functions of the same file belong to other units or are
out of scope (`unused_functions.txt`).
+30 -26
View File
@@ -4,7 +4,7 @@
Inputs (bin/callgraph/, produced by extract.py + build_graph.py):
graph.json, closure.json, resolve.json, overriders.json, files.json, globals.json
Outputs:
plan/modules.toml units per plan/modules.schema.md
plan/units/<id>.toml one file per unit, per plan/modules.schema.md
plan/order.md parallel layers + critical path
plan/closure.md closure report (files, unused code, hazards, threading)
harness/callgraph/units.json unit -> upstream functions (USR, name, file, lines)
@@ -604,11 +604,7 @@ json.dump(out_units, open(os.path.join(HERE, "units.json"), "w"), indent=1, sort
# ----------------------------------------------------------------------------------------------
# modules.toml
def tq(s):
return json.dumps(s)
# plan/units/<id>.toml
def unit_tests_for(a, k=6):
ts = sorted(set((n, t) for n, t, fx in unit_tests.get(a, [])))
picked = [t for n, t in ts[:k]]
@@ -625,9 +621,13 @@ SM_API_GROUP_ROOTS = collections.defaultdict(list)
for r in ROOTS:
SM_API_GROUP_ROOTS[UID.get(r, "")].append(F[r]["name"])
lines_out = ["# Generated by harness/callgraph/plan_units.py -- edit statuses/claims freely; regenerate only",
"# with care (ids are stable for a given closure). Function lists: harness/callgraph/units.json.",
"# est_lines = in-scope (reachable) upstream function lines in the unit.", ""]
# One file per unit (plan/units/<id>.toml, harness/plan/units.py). Regenerating resets
# statuses/claims/notes: do it only with care (ids are stable for a given closure).
# est_lines = in-scope (reachable) upstream function lines in the unit.
sys.path.insert(0, os.path.join(ROOT, "harness", "plan"))
import units as plan_units # noqa: E402
plan_out = {}
for un in sorted(units, key=lambda x: (layer[x["id"]], x["id"])):
a = un["id"]
up = sorted({F[u]["file"] for u in un["funcs"]})
@@ -652,22 +652,26 @@ for un in sorted(units, key=lambda x: (layer[x["id"]], x["id"])):
notes.append("hazards: " + ",".join(hz))
if ntests > len([t for t in tests if not t.startswith("pt_")]):
notes.append("%d upstream test entry points reach this unit" % ntests)
lines_out += [
"[[unit]]",
"id = %s" % tq(a),
"upstream = [%s]" % ", ".join(tq(x) for x in up),
"rust_module = %s" % tq(un["rust_module"]),
"depends_on = [%s]" % ", ".join(tq(b) for b in DEPS[a]),
"est_lines = %d" % usize(un),
"layer = %d" % layer[a],
"tests = [%s]" % ", ".join(tq(t) for t in tests),
'status = "todo"',
'claimed_by = ""',
'claimed_at = ""',
"notes = %s" % tq("; ".join(notes)),
"",
]
open(os.path.join(ROOT, "plan", "modules.toml"), "w").write("\n".join(lines_out))
plan_out[a] = {
"id": a,
"upstream": up,
"rust_module": un["rust_module"],
"depends_on": list(DEPS[a]),
"est_lines": usize(un),
"layer": layer[a],
"tests": tests,
"status": "todo",
"claimed_by": "",
"claimed_at": "",
"notes": "; ".join(notes),
}
units_dir = os.path.join(ROOT, "plan", "units")
os.makedirs(units_dir, exist_ok=True)
for f in os.listdir(units_dir):
if f.endswith(".toml") and f[:-5] not in plan_out:
os.remove(os.path.join(units_dir, f))
for a, u in plan_out.items():
open(os.path.join(units_dir, a + ".toml"), "w").write(plan_units.dump_unit(u))
# ----------------------------------------------------------------------------------------------
# order.md
@@ -690,7 +694,7 @@ o = ["# Port order (parallel layers)", "",
"evaluation -> offset/blend surfaces -> curve-on-surface -> surface point solve -> surface",
"evaluation). Unit-level strongly connected components were linearised with a weighted greedy",
"feedback-arc-set; the dropped *back-edges* are listed in each unit's `notes` in",
"`plan/modules.toml`. A unit with back-edges can be ported in its layer, but its difftest can only",
"`plan/units/<id>.toml`. A unit with back-edges can be ported in its layer, but its difftest can only",
"cover paths whose callees are already ported; full side-by-side validation of such a unit is",
"re-run when the back-edge targets turn green (keep `status = \"claimed\"` until then or record",
"the partial coverage in `plan/findings.md`).", "",
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# Regenerate the call graph and the plan (plan/closure.md, plan/modules.toml, plan/order.md).
# Regenerate the call graph and the plan (plan/closure.md, plan/units/*.toml, plan/order.md).
# Requires bin/cpp/compile_commands.json (harness/cpp/build.sh) and libclang (see README.md).
set -euo pipefail
cd "$(dirname "$0")/../.."
+1 -1
View File
@@ -117,7 +117,7 @@ w("in-scope operation (mass properties integrate exactly over faces, `SmBrep::Co
w("The only reachable `SmTess.cpp`/`SmPoly*.cpp` code is CHA residue: `SmAttribute::Copy` dispatching")
w("to polygon/decimation attribute types, `SmBrepCache::BuildTrees` dispatching `CalculateBoundingBox`")
w("to `SmCPolyFace`, and `SmApiTransform` accepting a `SmPolyBrep`. Those units (`query.poly`,")
w("`query.tess`) are flagged low priority in `plan/modules.toml`.")
w("`query.tess`) are flagged low priority in `plan/units/<id>.toml`.")
w("")
w("## Rust module totals")
w("")
+12 -10
View File
@@ -1,11 +1,13 @@
#!/usr/bin/env python3
"""Regenerate plan/PROGRESS.md from plan/modules.toml and committed difftest reports.
"""Regenerate plan/PROGRESS.md from plan/units/*.toml and the difftest reports.
CI (.github/workflows/progress.yml) runs this on main and commits the result; PRs never
edit plan/PROGRESS.md. Locally:
python3 harness/plan/progress.py # from the manifest and committed reports
python3 harness/plan/progress.py # from plan/units and reports/difftest/
python3 harness/plan/progress.py --prs # also mark units with an open "port: <id>" PR
Output is deterministic (no timestamps); statuses, claims and report counts drive changes.
Reports are not committed: CI uploads them from main (artifact `difftest-reports`) and
`scripts/fetch-reports.sh` downloads the latest set into reports/difftest/.
The counting helpers (`summary`, `is_ready`, `module`, `DONE`) are also imported by the
GitHub Pages site generator (site/build.py), so both report the same numbers.
@@ -16,7 +18,9 @@ import subprocess
import sys
import pathlib
import re
import tomllib
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
import units as plan_units # noqa: E402 (the shared plan loader)
ROOT = pathlib.Path(__file__).resolve().parents[2]
DONE = ("green", "partial")
@@ -25,15 +29,13 @@ ORDER = ["geom", "nurbs", "curve", "surface", "topology", "intersect", "primitiv
ICON = {"green": "✅", "partial": "🟡", "claimed": "🔨", "blocked": "⛔", "todo": "⏳"}
def load_units(text=None):
"""Units from plan/modules.toml (or from `text`, e.g. an older revision of it)."""
if text is None:
text = (ROOT / "plan/modules.toml").read_text()
return tomllib.loads(text)["unit"]
def load_units():
"""Units from plan/units/*.toml (sorted by id)."""
return plan_units.load_units(ROOT)
def load_case_counts(units):
"""Default-run counts from committed reports; omit units without a report.
"""Default-run counts from reports/difftest/; omit units without a report.
Notes can describe stress runs or contain operation numbers (e.g. "op-0 cases"),
so they are not a source for the published case count. Reject invalid reports
@@ -120,7 +122,7 @@ def main():
out = [
"# Port progress",
"",
"Generated from `plan/modules.toml` and `reports/difftest/*.json` by "
"Generated from `plan/units/*.toml` and CI's `reports/difftest/*.json` by "
"`harness/plan/progress.py`; do not edit by hand.",
"",
f"**{count['green'] + count['partial']} / {len(units)} units ported** "
+16 -23
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Split light dependencies out of `depends_on` into `soft_depends_on` (plan/modules.toml).
"""Split light dependencies out of `depends_on` into `soft_depends_on` (plan/units/*.toml).
A dependency U -> D is *soft* when U's functions call at most MAX_CALLS distinct functions
of D and D owns no methods of a class U's own classes are or derive from (so U needs no
@@ -17,7 +17,6 @@ import collections
import json
import os
import pathlib
import re
import sys
ROOT = pathlib.Path(__file__).resolve().parents[2]
@@ -64,20 +63,13 @@ def needs_type(u, d):
return bool(mine & own_classes[d])
path = ROOT / "plan/modules.toml"
text = path.read_text()
blocks = re.split(r"(?m)^(?=\[\[unit\]\])", text)
out, moved, total = [], 0, 0
for b in blocks:
m = re.search(r'(?m)^id = "([^"]+)"', b)
if not m:
out.append(b)
continue
uid = m.group(1)
deps = re.findall(r'"([^"]+)"', re.search(r"(?m)^depends_on = \[(.*)\]$", b).group(1))
sm = re.search(r"(?m)^soft_depends_on = \[(.*)\]\n", b)
deps += re.findall(r'"([^"]+)"', sm.group(1)) if sm else []
deps = sorted(set(deps))
sys.path.insert(0, str(ROOT / "harness/plan"))
import units as plan_units # noqa: E402
moved, total = 0, 0
for u in plan_units.load_units(ROOT):
uid = u["id"]
deps = sorted(set(u.get("depends_on", [])) | set(u.get("soft_depends_on", [])))
if uid not in units_json:
# Not a port unit (e.g. audit.recursion): its ordering is deliberate, keep it hard.
hard = deps
@@ -86,12 +78,13 @@ for b in blocks:
soft = [d for d in deps if d not in hard]
total += len(deps)
moved += len(soft)
if sm:
b = b.replace(sm.group(0), "")
b = re.sub(r"(?m)^depends_on = \[.*\]$",
lambda _: "depends_on = " + json.dumps(hard) + "\nsoft_depends_on = " + json.dumps(soft),
b, count=1)
out.append(b)
path.write_text("".join(out))
new = {}
for k, v in u.items(): # soft_depends_on goes right after depends_on
if k == "soft_depends_on":
continue
new[k] = v
if k == "depends_on":
new[k], new["soft_depends_on"] = hard, soft
plan_units.write_unit(new, ROOT)
print(f"soft_depends_on: {moved} of {total} dependencies (max {MAX_CALLS} calls, no type dependency)",
file=sys.stderr)
+224
View File
@@ -0,0 +1,224 @@
#!/usr/bin/env python3
"""Shared loader and writer for the port plan: one file per unit, `plan/units/<id>.toml`.
Format: `plan/modules.schema.md`. Each file holds one unit's fields as top-level keys
(`id`, `upstream`, `rust_module`, ...); `id` must equal the file name. Every tool that
reads the plan goes through this module (harness/plan/progress.py, site/build.py,
harness/plan/soften.py, harness/callgraph/plan_units.py, scripts/units-split.py,
scripts/units-migrate-branch.sh); the Rust side (`crates/difftest/src/plan.rs`) follows
the same rules. Units are always returned sorted by id.
Before the split (PR "infra: stop shared-file conflicts") the plan was the single file
`plan/modules.toml` with `[[unit]]` tables; `parse_modules_toml` and `split_modules_toml`
still read that layout for old revisions (site timeline, branch migration).
python3 harness/plan/units.py check # parse every unit file
python3 harness/plan/units.py migrate BASE TIP [--root R] # see units-migrate-branch.sh
"""
import json
import pathlib
import re
import sys
import tomllib
ROOT = pathlib.Path(__file__).resolve().parents[2]
UNITS_DIR = pathlib.PurePosixPath("plan/units")
# Canonical key order of a unit file (plan/modules.schema.md).
FIELDS = ["id", "upstream", "rust_module", "depends_on", "soft_depends_on", "est_lines",
"layer", "tests", "status", "claimed_by", "claimed_at", "notes"]
STATUSES = ["todo", "claimed", "partial", "green", "blocked", "out_of_scope"]
_ID_RE = re.compile(r"^[A-Za-z0-9_.\-]+$")
# ---------------------------------------------------------------- reading
def parse_unit(text, name="<unit>"):
"""One unit from the text of a `plan/units/<id>.toml` file."""
u = tomllib.loads(text)
if not isinstance(u.get("id"), str):
raise ValueError(f"{name}: missing id")
return u
def units_dir(root=None):
return pathlib.Path(root or ROOT) / UNITS_DIR
def load_units(root=None):
"""All units of the working tree at `root` (default: the repository), sorted by id."""
out = []
for p in sorted(units_dir(root).glob("*.toml")):
u = parse_unit(p.read_text(), str(p))
if u["id"] != p.stem:
raise ValueError(f"{p}: id {u['id']!r} does not match the file name")
out.append(u)
return out
def units_from_texts(texts):
"""Units from {file stem: text} (e.g. blobs of a git tree), sorted by id."""
return [parse_unit(texts[k], k) for k in sorted(texts)]
def parse_modules_toml(text):
"""Units of the old single-file `plan/modules.toml`, sorted by id."""
return sorted(tomllib.loads(text).get("unit", []), key=lambda u: u["id"])
def split_modules_toml(text):
"""{id: unit file text} from the old `plan/modules.toml`, keeping each unit's lines
(including comment lines that follow its fields) verbatim."""
blocks = re.split(r"(?m)^\[\[unit\]\][ \t]*\n", text)
out = {}
for b in blocks[1:]:
body = b.rstrip() + "\n"
u = parse_unit(body)
if u["id"] in out:
raise ValueError(f"duplicate unit {u['id']}")
out[u["id"]] = body
parsed = {u["id"]: u for u in tomllib.loads(text).get("unit", [])}
if set(parsed) != set(out):
raise ValueError("split lost units: " + ", ".join(sorted(set(parsed) ^ set(out))))
for uid, body in out.items():
if tomllib.loads(body) != parsed[uid]:
raise ValueError(f"unit {uid}: split text does not round-trip")
return out
# ---------------------------------------------------------------- writing
def toml_value(v):
"""Canonical one-line TOML for the value types unit files use."""
if isinstance(v, bool):
return "true" if v else "false"
if isinstance(v, int):
return str(v)
if isinstance(v, str):
return json.dumps(v, ensure_ascii=False).replace("\x7f", "\\u007f")
if isinstance(v, list):
return "[" + ", ".join(toml_value(x) for x in v) + "]"
raise TypeError(f"unsupported value {v!r}")
def dump_unit(u):
"""Canonical text of a unit file (FIELDS order, then any extra keys)."""
keys = [k for k in FIELDS if k in u] + [k for k in u if k not in FIELDS]
return "".join(f"{k} = {toml_value(u[k])}\n" for k in keys)
def set_field(text, key, value):
"""`text` with `key = value` replaced in place (or appended after the last key line),
leaving every other line, including comments, untouched."""
line = f"{key} = {toml_value(value)}"
pat = re.compile(rf"(?m)^{re.escape(key)}[ \t]*=.*$")
if pat.search(text):
return pat.sub(lambda _: line, text, count=1)
lines = text.splitlines()
last = max((i for i, l in enumerate(lines) if re.match(r"^[A-Za-z0-9_\-]+[ \t]*=", l)), default=-1)
lines.insert(last + 1, line)
return "\n".join(lines) + "\n"
def del_field(text, key):
return re.sub(rf"(?m)^{re.escape(key)}[ \t]*=.*\n?", "", text, count=1)
def unit_path(uid, root=None):
if not _ID_RE.match(uid):
raise ValueError(f"bad unit id {uid!r}")
return units_dir(root) / f"{uid}.toml"
def write_unit(u, root=None):
"""Writes a unit; an existing file keeps its layout and comments, only changed
fields are rewritten."""
p = unit_path(u["id"], root)
if p.exists():
text = p.read_text()
old = parse_unit(text, str(p))
for k in old:
if k not in u:
text = del_field(text, k)
for k in [k for k in FIELDS if k in u] + [k for k in u if k not in FIELDS]:
if old.get(k) != u[k]:
text = set_field(text, k, u[k])
else:
p.parent.mkdir(parents=True, exist_ok=True)
text = dump_unit(u)
if parse_unit(text, str(p)) != u:
raise ValueError(f"{p}: rewrite does not round-trip")
p.write_text(text)
return p
# ---------------------------------------------------------------- branch migration
def migrate(base_text, tip_text, root=None):
"""Applies a branch's `plan/modules.toml` edits (`tip_text` vs its merge base
`base_text`) to the per-unit files under `root`, field by field (3-way: a field the
branch did not change keeps main's value). Returns (changed ids, conflicts); a
conflict (main and the branch both changed a field differently) takes the branch's
value and is reported."""
base = {u["id"]: u for u in parse_modules_toml(base_text)} if base_text.strip() else {}
tip = {u["id"]: u for u in parse_modules_toml(tip_text)}
changed, conflicts = [], []
for uid in sorted(set(base) | set(tip)):
b, t = base.get(uid), tip.get(uid)
if b == t:
continue
p = unit_path(uid, root)
if t is None: # the branch removed the unit
if p.exists():
p.unlink()
changed.append(uid)
continue
cur = parse_unit(p.read_text(), str(p)) if p.exists() else None
if cur is None:
if b is not None:
conflicts.append(f"{uid}: removed on main but edited on the branch (restored)")
write_unit(t, root)
changed.append(uid)
continue
new = dict(cur)
for k in [k for k in FIELDS if k in t or (b and k in b)] + \
[k for k in list(t) + list(b or {}) if k not in FIELDS]:
bv, tv = (b or {}).get(k), t.get(k)
if bv == tv:
continue
if cur.get(k) not in (bv, tv):
conflicts.append(f"{uid}.{k}: changed on main and on the branch (kept the branch's value)")
if tv is None:
new.pop(k, None)
else:
new[k] = tv
if new != cur:
write_unit(new, root)
changed.append(uid)
return changed, conflicts
def main(argv):
if argv[:1] == ["check"]:
us = load_units()
bad = [f"{u['id']}: status {u.get('status')!r}" for u in us if u.get("status", "todo") not in STATUSES]
for b in bad:
print(b, file=sys.stderr)
print(f"{len(us)} units OK" if not bad else f"{len(bad)} bad unit(s)")
return 1 if bad else 0
if argv[:1] == ["migrate"] and len(argv) >= 3:
root = argv[argv.index("--root") + 1] if "--root" in argv else None
base_text = pathlib.Path(argv[1]).read_text()
tip_text = pathlib.Path(argv[2]).read_text()
changed, conflicts = migrate(base_text, tip_text, root)
for uid in changed:
print(f"plan/units/{uid}.toml")
for c in conflicts:
print(f"CONFLICT {c}", file=sys.stderr)
return 3 if conflicts else 0
print(__doc__, file=sys.stderr)
return 2
if __name__ == "__main__":
sys.dont_write_bytecode = True
sys.exit(main(sys.argv[1:]))
+1 -1
View File
@@ -79,7 +79,7 @@ in-scope operation (mass properties integrate exactly over faces, `SmBrep::Compu
The only reachable `SmTess.cpp`/`SmPoly*.cpp` code is CHA residue: `SmAttribute::Copy` dispatching
to polygon/decimation attribute types, `SmBrepCache::BuildTrees` dispatching `CalculateBoundingBox`
to `SmCPolyFace`, and `SmApiTransform` accepting a `SmPolyBrep`. Those units (`query.poly`,
`query.tess`) are flagged low priority in `plan/modules.toml`.
`query.tess`) are flagged low priority in `plan/units/<id>.toml`.
## Rust module totals
+19 -3
View File
@@ -1,8 +1,12 @@
# plan/modules.toml schema (shared contract)
# Plan unit file schema (shared contract)
The port plan is one TOML file per unit, `plan/units/<id>.toml` (until 2026-10 it was the
single file `plan/modules.toml` with one `[[unit]]` table per unit; the fields are the
same, now as top-level keys). The file name must equal `id`. A PR edits only the files
of the units it changes, so parallel PRs do not conflict.
```toml
[[unit]]
id = "nlib.knots" # dotted, stable, unique
id = "nlib.knots" # dotted, stable, unique; = the file name
upstream = ["source/SMLib/src/..."] # upstream file(s) relative to upstream/
rust_module = "nurbs::knots" # target path inside crates/solidcore
depends_on = [] # unit ids that must be green/partial before claiming
@@ -15,3 +19,15 @@ claimed_by = ""
claimed_at = ""
notes = ""
```
Comment lines (`# ...`) after the fields are allowed and kept by the tools.
Readers and writers all go through one loader: `harness/plan/units.py` (Python:
`load_units`, `write_unit`; `python3 harness/plan/units.py check` validates every file)
and `crates/difftest/src/plan.rs` (difftest `--green`). Units are listed in id order.
- `scripts/units-split.py`: one-time split of the old `plan/modules.toml` into
`plan/units/` (each unit's lines copied verbatim and checked to round-trip).
- `scripts/units-migrate-branch.sh`: for a branch started before the split, moves its
`plan/modules.toml` edits (relative to its merge base with main) into the unit files;
run it after merging main (AGENTS.md section 4).
-3667
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -9,7 +9,7 @@ the previous layers are green. Dependencies are static calls plus conservative v
evaluation -> offset/blend surfaces -> curve-on-surface -> surface point solve -> surface
evaluation). Unit-level strongly connected components were linearised with a weighted greedy
feedback-arc-set; the dropped *back-edges* are listed in each unit's `notes` in
`plan/modules.toml`. A unit with back-edges can be ported in its layer, but its difftest can only
`plan/units/<id>.toml`. A unit with back-edges can be ported in its layer, but its difftest can only
cover paths whose callees are already ported; full side-by-side validation of such a unit is
re-run when the back-edge targets turn green (keep `status = "claimed"` until then or record
the partial coverage in `plan/findings.md`).
+12
View File
@@ -0,0 +1,12 @@
id = "audit.recursion"
upstream = []
rust_module = "(crate-wide)"
depends_on = ["blend.fillet_corner_p2", "blend.fillet_corner_p3", "blend.hcr", "boolean.api_brep", "heal.heal_data_p3", "intersect.curve_class_p8", "intersect.surface_drop_curve", "intersect.surface_intersector_p5", "intersect.surface_silhouette", "mass.integrator", "offset.offset_executive_p2", "primitive.api_curves", "primitive.api_primitives", "query.api_queries", "query.tess", "surface.b_spline_volume_n_lib", "surface.cone_p3", "surface.srf_in_volume", "surface.surf_of_extrusion_p2", "surface.surface_point_solve_p3", "sweep.api_brep", "sweep.api_surfaces"]
soft_depends_on = []
est_lines = 0
layer = 65
tests = []
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "Not a port: audit every recursive path in crates/solidcore (direct and mutual recursion, incl. via Curve/Surface dispatch) and give each a depth bound returning SolidError, or convert to an explicit-stack loop only where iteration order stays identical (difftest must not change). Motivation: wasm32 has no stack guard page, so overflow corrupts memory. See AGENTS.md (recursion) and plan/findings.md (nested reads). Depends on all sink units so it runs last."
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_corner_p1"
upstream = ["source/SMLib/inc/SmFilletCorner.h", "source/SMLib/src/SmFilletCorner.cpp"]
rust_module = "blend::fillet_corner::p1"
depends_on = ["blend.fillet_executive_p1", "blend.fillet_geom_p1", "blend.fillet_solver_p1", "blend.fillet_standard_solver_p1", "curve.curve_p2", "geom.axis2_placement", "geom.extent1d", "geom.extent2d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_surface_p1", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1", "topology.vertex", "topology.vertexuse"]
soft_depends_on = ["boolean.merge_p1", "boolean.topology_intersector_p2", "boolean.topology_intersector_p3", "curve.curve_p1", "curve.curve_p5", "curve.line", "geom.a_object", "geom.attribute", "geom.geom_utility_p1", "intersect.surface_intersector_p1", "nurbs.b_spline_curve_p1", "nurbs.b_spline_curve_p2", "nurbs.b_spline_surface_p2", "surface.plane_p1", "surface.surface_p4", "surface.surface_p5", "surface.surface_p6", "surface.surface_p7", "topology.brep_p4", "topology.brep_p7", "topology.edgeuse_p3", "topology.face_p2", "topology.proto_topology_p1"]
est_lines = 1971
layer = 59
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "55 fns; largest: SmFilletCorner::MakeConstantRadiusFillet, SmFilletCorner::MakeFaceBrep, SmFilletCorner::InsertIntersectionTopology, sm_CreateSrfOfRevolution; cycle back-edges (call into later units; stub or co-port): blend.fillet_geom_p3(3), blend.fillet_geom_p5(1); unit-SCC #22 (220 units); hazards: ptr-hash; 319 upstream test entry points reach this unit; CO-PORTED in blend.fillet_corner_p3 (PR #256): SmFilletCorner members and constructor, GetCornerType/GetName -> blend::fillet_corner::p3::{FilletCorner, FilletCorner::new, FilletCornerKind}; its stubs there: sm_TestG1Continuity, SmFilletNx1Corner::CheckNx1Degeneracy, CreateEndPatch, MakeFaceBrep, CalcCornerVertGeom; CO-PORTED in blend.fillet_executive_p3 (PR #244): read-only CornerView (GetFilletedVertex, GetCornerType, GetName)"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_corner_p2"
upstream = ["source/SMLib/inc/SmFilletCorner.h", "source/SMLib/src/SmFilletCorner.cpp"]
rust_module = "blend::fillet_corner::p2"
depends_on = ["blend.fillet_corner_p1", "blend.fillet_geom_p1", "blend.fillet_geom_p2", "blend.fillet_solver_p1", "curve.curve_p2", "geom.extent1d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector2d", "geom.vector3d", "intersect.surface_intersector_p1", "nurbs.b_spline_curve_p1", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1", "topology.vertex"]
soft_depends_on = ["blend.fillet_executive_p1", "blend.fillet_executive_p2", "blend.fillet_geom_p3", "blend.fillet_geom_p4", "blend.fillet_geom_p5", "blend.fillet_geom_p6", "blend.fillet_standard_solver_p2", "curve.curve_p1", "geom.extent2d", "geom.geom_utility_p1", "nurbs.b_spline_curve_p2", "nurbs.b_spline_surface_p2", "surface.offset_surface", "surface.surface_p1", "surface.surface_p4", "surface.surface_p7", "topology.edgeuse_p3", "topology.face_p2", "topology.proto_topology_p1", "topology.vertexuse"]
est_lines = 1892
layer = 64
tests = ["SM_API_test:TestSmFilletPreview", "SM_API_test:TestSmSurfaceSurfaceFillet", "SM_API_test:TestSmCircularFillet", "SM_API_test:TestSmChamferFillet", "SM_API_test:TestSmFilletEdges", "SM_API_test:TestSmFilletEdgesPerEdge"]
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "16 fns; largest: SmFilletCorner::MakeVariableRadiusFillet, SmFilletNx1ClosedCorner::AdjustTangentCorner, SmFilletCorner::MakeAnalyticCornerSurface, SmFilletConvexNxNCorner::AdjustTopology; unit-SCC #22 (220 units); 31 upstream test entry points reach this unit; CO-PORTED in blend.fillet_corner_p3 (PR #256): the constructors of SmFillet1x1Corner, SmFilletNx1ClosedCorner, SmFilletNx1Corner, SmFillet3x2MixedConvexityCorner, SmFilletNx2Corner, SmFilletNxNCorner -> blend::fillet_corner::p3::FilletCorner::new (FilletCornerKind); its stubs there: sm_FindConcaveEdgeuses, MakeAnalyticCornerSurface, AdjustConcaveCornerTopology, SmFilletConvexNxNCorner::AdjustTopology, SmFilletNx1ClosedCorner::AdjustTangentCorner"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_corner_p3"
upstream = ["source/SMLib/src/SmFilletCorner.cpp"]
rust_module = "blend::fillet_corner::p3"
depends_on = ["blend.fillet_corner_p1", "blend.fillet_executive_p1", "blend.fillet_geom_p1", "blend.fillet_solver_p1", "curve.curve_p2", "geom.extent1d", "geom.object", "geom.vector3d", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1", "topology.vertex"]
soft_depends_on = ["blend.fillet_geom_p3", "blend.fillet_geom_p4", "curve.curve_p6", "geom.tol", "intersect.surface_drop_lib_p3", "intersect.surface_intersector_p1", "nurbs.b_spline_curve_p1", "nurbs.b_spline_curve_p2", "nurbs.b_spline_curve_p3", "nurbs.b_spline_surface_n_lib_p2", "nurbs.b_spline_surface_p1", "topology.edgeuse_p2", "topology.edgeuse_p3", "topology.face_p2", "topology.proto_topology_p1", "topology.vertexuse"]
est_lines = 1697
layer = 61
tests = ["SM_API_test:TestSmFilletPreview", "SM_API_test:TestSmCircularFillet", "SM_API_test:TestSmChamferFillet", "SM_API_test:TestSmFilletEdges", "SM_API_test:TestSmFilletEdgesPerEdge", "SM_API_test:TestSmVariableRadiusFillet"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "14 fns; largest: SmFilletNx2Corner::AdjustTangentCorner, SmFilletCorner::Create, SmFilletCorner::CreateCornerPatch, SmFilletNx2Corner::AdjustTopology; cycle back-edges (call into later units; stub or co-port): blend.fillet_corner_p2(11), blend.fillet_geom_p2(1), blend.fillet_geom_p5(1), blend.fillet_geom_p6(1); unit-SCC #22 (220 units); 26 upstream test entry points reach this unit; PARTIAL (PR #256, built on PR #252 = #147 + #192): 1005 cases (308 upstream-file fixtures from TestFiles/pt_TestFiles/Fillet, 400 generated, 60 review cases with SmPlane user surfaces, 156 review cases with real SmLine 3x2 edge curves, 81 with real SmCircle 3x2 edge curves), 560 passed, 390 deferred (blend.fillet_corner_p1 111, blend.fillet_corner_p2 126, blend.fillet_executive_p1 6, blend.fillet_geom_p5 13, blend.fillet_geom_p6 33, intersect.surface_drop_lib_p3 78, surface.cone_p1 11, surface.surf_of_extrusion_p2 12), 55 rejected (40 of them review joins that succeed without an original face, where upstream would delete harness objects); every patch builder past its state checks is deferred (MakeAnalyticCornerSurface / CreateEndPatch / DropCurve), so no CreateCornerBlend default-patch values are compared; SmFilletSolver::SplitFilletGeomAtSideEdge (ported in blend.fillet_solver_p1 on FilletGeomRef) is stubbed in AdjustTangentCorner as UNPORTED(blend.fillet_geom_p6), its first blocker; the 3x2 curve join dispatches on the curve kind (SmLine/SmEllipse JoinWith overrides), as upstream's virtual JoinWith does; no CreateCornerPatch implementation compares surface output yet (corner_p1/p2 porters must extend the runner); UPDATE (PR #247, blend.fillet_geom_p6): GetRailIndexOfVertex reaches part 6 and AdjustTangentCorner's GetRailVertex / SetPointClass / GetCommonEdges after the split are ported up to CalcCornerVertGeom (UNPORTED(blend.fillet_corner_p1)); the SplitFilletGeomAtSideEdge stub is retagged UNPORTED(blend.fillet_solver_p1) (its port works on FilletGeomRef). The shim's tangent pre-check now mirrors the split loop (GetRailIndexOfVertex, DropPoint, IsValueOnBoundary) and stops only where a geometry would be split (refusing the uninitialised lRailIdx / bSuccess cases). Re-run: 1005 cases, 592 pass, 0 failed, 358 deferred (blend.fillet_solver_p1 1), 55 rejected; --perturb SENSITIVE 592/592"
@@ -0,0 +1,12 @@
id = "blend.fillet_custom_solver"
upstream = ["source/SMLib/inc/SmFilletCustomSolver.h", "source/SMLib/src/SmFilletCustomSolver.cpp"]
rust_module = "blend::fillet_custom_solver"
depends_on = ["geom.axis2_placement", "geom.extent1d", "geom.extent2d", "geom.object", "geom.solution_array", "geom.vector2d", "geom.vector3d", "intersect.surface_intersector_p1", "nurbs.b_spline_curve_p1", "surface.surface_p7", "topology.edgeuse_p1"]
soft_depends_on = ["curve.curve_p1", "curve.curve_p2", "curve.curve_p4", "curve.curve_p5", "curve.curve_p6", "geom.geom_utility_p2", "geom.matrix", "geom.tol", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_curve_p2", "nurbs.b_spline_curve_p3", "nurbs.b_spline_surface_n_lib_p1", "nurbs.b_spline_surface_n_lib_p2", "nurbs.b_spline_surface_p1", "nurbs.b_spline_surface_p2", "surface.offset_surface", "surface.surf_of_extrusion_p1", "surface.surface_p1", "surface.surface_p2", "surface.surface_p4", "surface.surface_p5", "topology.edge", "topology.face_p2"]
est_lines = 1236
layer = 41
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PARTIAL: difftest 448 cases (48 fixture, 400 generated), 401 pass, 0 failed, 47 deferred (blend.fillet_standard_solver_p2 47: GuessPointOnPlaneSolve; LocalPointSolve_1 on the other rail's offset runs since surface.surface_point_solve_p3 landed), max_rel_err 0; earlier: --perturb SENSITIVE (360/360); 4000-seed run 4048 cases, 3242 pass, 0 failed, 806 deferred. CreateSurface (SmEiffelTowerCrossSectionFSG) is compared on 'Eiffel tower' sections over straight (ruled branch), concentric arc (surface of revolution branch) and free-form rails (skin with extrusion cross-boundary derivative surfaces), equal radii, vanishing/zero second arc, touching rails (point sections), mismatched point counts and knot vectors, different intervals on parallel 2-point line rails (the only different-interval inputs the FFI guard admits), tolerances 0 to above the rail gap, scales 1e-6 to 1e6; the shim's solver is an SmConstantRadiusFS (CreateSurface reads only its context and tolerance). LoadJacobian / LoadInitialValues of SmEiffelTowerFS and SmSecantConstantRadiusFS run in C++ on solvers built on an SmApiCreateBox edge use with their offset surfaces, orientations and radii replaced and edge uses cleared; the offset surfaces are the ported SmOffsetSurface (surface.offset_surface, wired in PR #62) built with the case's lSingularities: SM_SS_UNKNOWN (upstream's default) now runs SmSurface::GetSingularities; LoadInitialValues with rbDoSurf2Calcs runs GlobalPointSolve, and LocalPointSolve on the other rail's offset (a copy: the solver is borrowed shared), which reaches LocalPointSolve_1 (surface.surface_point_solve_p3, landed). Other stubs: UNPORTED(blend.fillet_standard_solver_p2) GuessPointOnPlaneSolve, the SmConstantRadiusFS edge-use constructor (ConstantRadiusAssistedFs::from_edgeuse) wired by blend.fillet_standard_solver_p1 (PR #168); the inherited SmConstantRadiusFS/SmConstantRadiusAssistedFS overrides GetJacobianSize, SetupOffsetValues, OffsetRadiiCanChange and GetType call blend.fillet_standard_solver_p1's (PR #192 after #168; IsKindOf stays UNPORTED at _p2; no case count changed). Co-ports (see CO-PORTED notes of blend.fillet_solver_p1, blend.fillet_standard_solver_p1); the offset surface co-port is replaced by surface.offset_surface (PR #62). Plan notes: 8 fns; largest: SmEiffelTowerFS::LoadInitialValues, SmSecantConstantRadiusFS::LoadInitialValues, SmEiffelTowerCrossSectionFSG::CreateSurface, SmEiffelTowerFS::LoadJacobian; cycle back-edges (call into later units; stub or co-port): blend.fillet_solver_p1(8), blend.fillet_standard_solver_p2(2); unit-SCC #22 (220 units); only 3 of 1236 lines survive RTA (reached via virtual dispatch to classes no in-scope entry point constructs); low priority / likely deferrable; 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_executive_p1"
upstream = ["source/SMLib/inc/SmFilletExecutive.h", "source/SMLib/src/SmFilletExecutive.cpp", "source/SM_API/src/SmApiBrep.cpp", "source/SM_API/src/SmApiFillets.cpp"]
rust_module = "blend::fillet_executive::p1"
depends_on = ["blend.fillet_executive_p3", "blend.fillet_geom_p1", "blend.fillet_solver_p1", "blend.fillet_standard_solver_p1", "boolean.merge_p1", "boolean.merge_p3", "curve.curve_p2", "geom.a_object", "geom.attribute", "geom.context", "geom.extent1d", "geom.object", "geom.vector3d", "nurbs.b_spline_curve_p1", "surface.surface_p1", "surface.surface_p2", "topology.brep_p1", "topology.brep_p4", "topology.brep_p5", "topology.edge", "topology.edgeuse_p1", "topology.face_p2", "topology.shell", "topology.vertex"]
soft_depends_on = ["boolean.topology_intersector_p1", "curve.curve_cache", "geom.extent2d", "geom.tol", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_curve_p2", "surface.surface_p7", "topology.brep_p2", "topology.brep_p3", "topology.brep_p8", "topology.face_p1", "topology.proto_topology_p1", "topology.topology", "topology.vertexuse"]
est_lines = 2063
layer = 58
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "73 fns; largest: SmFilletExecutive::DoPiecewiseMerge, SmFilletExecutive::TestAndConvertBigRadFillet, SmFilletExecutive::SetFilletParameters, SmFilletExecutive::RemoveTopoEdges; entry points: SmApiChamferFillet, SmApiCircularFillet, SmApiFilletEdges, SmApiFilletEdgesPerEdge, SmApiSetBevelCorners, SmApiSurfaceSurfaceFillet, SmApiVariableRadiusFillet; cycle back-edges (call into later units; stub or co-port): blend.fillet_corner_p1(6), blend.fillet_executive_p2(3), blend.fillet_standard_solver_p2(3), blend.fillet_corner_p3(2), blend.fillet_corner_p2(1), blend.fillet_geom_p2(1), blend.fillet_geom_p5(1), blend.fillet_geom_p6(1); unit-SCC #22 (220 units); hazards: ptr-iter; 319 upstream test entry points reach this unit; CO-PORTED in blend.fillet_corner_p3 (PR #256): SmFilletExecutive::m_vEdgeuseSolverMap, GetFilletSolverOfEdgeuse -> blend::fillet_corner::p3::FilletExecutiveData; CO-PORTED in blend.fillet_standard_solver_p1 (PR #168): the SmFilletLaw / SmLinearFilletLaw / SmBSplineFilletLaw data the variable-radius solver reads (start/end radius, law curve, m_pExtended, IsLinearLaw, Get/SetExtendedEdgeCurve) -> solidcore::blend::fillet_standard_solver::p1::{FilletLaw, FilletLawKind}; FilletLaw::evaluate is UNPORTED(blend.fillet_executive_p1) SmFilletLaw::Evaluate; CO-PORTED in blend.fillet_executive_p3 (PR #244): SmFilletExecutive member data -> blend::fillet_executive::p3::FilletExecutive<O>; SmFilletErrorInfo data and selective assignment -> ErrorInfo<O> (extend these records, not duplicate types); CO-PORTED in blend.fillet_executive_p2 (PR #267): SmFilletExecutive::m_sLawSequenceEdgeList -> blend::fillet_executive::p3::FilletExecutive::law_sequence_edges"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_executive_p2"
upstream = ["source/SMLib/inc/SmFilletExecutive.h", "source/SMLib/src/SmFilletExecutive.cpp"]
rust_module = "blend::fillet_executive::p2"
depends_on = ["blend.fillet_executive_p1", "blend.fillet_geom_p1", "blend.fillet_solver_p1", "blend.fillet_standard_solver_p1", "blend.fillet_standard_solver_p2", "boolean.merge_p1", "geom.context", "geom.extent1d", "geom.object", "geom.vector3d", "nurbs.b_spline_curve_p1", "topology.brep_p1", "topology.edge"]
soft_depends_on = ["blend.fillet_corner_p1", "blend.fillet_geom_p4", "blend.fillet_solver_p2", "blend.fillet_solver_p3", "blend.fillet_solver_p4", "boolean.topology_intersector_p1", "boolean.topology_intersector_p2", "curve.curve_p2", "curve.curve_p8", "geom.a_object", "geom.solution_array", "geom.tol", "geom.vector2d", "nurbs.b_spline_curve_n_lib", "surface.offset_surface", "surface.surface_p2", "topology.brep_p2", "topology.brep_p3", "topology.brep_p4", "topology.edgeuse_p1", "topology.proto_topology_p1", "topology.topology"]
est_lines = 1152
layer = 61
tests = ["SM_API_test:TestSmFilletPreview", "SM_API_test:TestSmSurfaceSurfaceFillet", "SM_API_test:TestSmCircularFillet", "SM_API_test:TestSmChamferFillet", "SM_API_test:TestSmFilletEdges", "SM_API_test:TestSmFilletEdgesPerEdge"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PARTIAL (PR #267): 12/12 fns; difftest 275 cases (259 fixture in fixtures/blend.fillet_executive_p2/constructed.json + 16 generated): 250 pass at max_rel_err 0 (224 fixture + 16 generated law constructors compared on every value, 4 empty-edge SetFilletParameters, 2 null-dereference guards and 1 box with fewer than 12 edges (box_edge_count) erroring on both sides, 3 empty-executive SetFilletBrepEdgeMap/ProcessSmoothEdgeSequences/CollectTangentEdgeSequence), 0 failed, 25 deferred (blend.fillet_executive_p1 22: NoteError/AddFilletSurfaceGenerator/LoadFilletSolver; blend.fillet_standard_solver_p2 2: SmConstantDistanceFS/SmVariableRadiusFS constructors; topology.face_p2 1: SmFace::GetTolerance in the constant-radius solver constructor); SmTemporaryRadiusChange and every non-empty executive member defer at executive p1 until it lands; upstream UB-206, WR-208, UB-209; the UNPORTED(blend.fillet_executive_p2) SmTemporaryRadiusChange::SetUp stub in blend::fillet_geom::p2 stays (see plan/findings.md, blend.fillet_executive_p2 'Not wired'): its base FilletSolver cannot reach a variable-radius law without #260's FilletSolverKind, the RAII scope must wrap RailEdgeuseIntersect with &mut solvers, it needs a concrete-id entry point, and law evaluation is still executive p1's; builds on H1D 38c5677c (FilletLaw edge map, arc length, extended law; declared dependency); 12 fns; largest: SmFilletExecutive::SurfaceSurfaceFillet, SmFilletExecutive::DoSurfaceFilleting, SmFilletExecutive::SetFilletParameters, SmFilletExecutive::CollectTangentEdgeSequence; cycle back-edges (call into later units; stub or co-port): blend.fillet_geom_p6(1); unit-SCC #22 (220 units); 31 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_executive_p3"
upstream = ["source/SMLib/src/SmFilletExecutive.cpp"]
rust_module = "blend::fillet_executive::p3"
depends_on = ["blend.fillet_geom_p1", "blend.fillet_solver_p1", "boolean.merge_p1", "boolean.topology_intersector_p1", "geom.context", "geom.object", "geom.tol", "geom.vector3d", "heal.stitch_p1", "topology.brep_p1", "topology.brep_p3", "topology.edge"]
soft_depends_on = ["blend.fillet_solver_p4", "blend.fillet_solver_p5", "boolean.topology_intersector_p2", "curve.curve_p2", "geom.a_object", "geom.attribute", "heal.stitch_p2", "surface.surface_p2", "topology.brep_p2", "topology.brep_p4", "topology.edgeuse_p1", "topology.face_p1", "topology.face_p3", "topology.topology", "topology.vertex"]
est_lines = 1608
layer = 54
tests = ["SM_API_test:TestSmCircularFillet", "SM_API_test:TestSmChamferFillet", "SM_API_test:TestSmFilletEdges", "SM_API_test:TestSmFilletEdgesPerEdge", "SM_API_test:TestSmVariableRadiusFillet", "SM_API_test:TestSmSetBevelCorners"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PR #244: 3/3 control-flow bodies, complete continuations; difftest 291 cases: 116 state/error-path passes, 0 failures, 175 deferred (executive_p1 46, topology.brep_p4 111 and query.brep 18 since PR #267 wired ProcessSmoothEdgeSequences and the merged topology.brep_p2 SetTolerance; executive_p2 129 before); with_values=116 no_values=0; 0 successful geometry/topology parity cases. Includes 7 actual upstream API examples, Rust setup deferred to executive_p1. 19 core tests +4 FFI guard tests. 3 fns; largest: SmFilletExecutive::DoFilleting, SmFilletExecutive::CreateFilletBrep, SmFilletExecutive::DoFillet; cycle back-edges (call into later units; stub or co-port): blend.fillet_corner_p1(13), blend.fillet_executive_p1(12), blend.fillet_executive_p2(2), blend.fillet_geom_p4(2), blend.fillet_corner_p3(1), blend.fillet_geom_p6(1); unit-SCC #22 (220 units); 25 upstream test entry points reach this unit; UPDATE (PR #247): ExecutiveAccess::trim_original_surfaces is a required adapter delegating to blend::fillet_geom::p6::FilletBrep::trim_original_surfaces (as insert_geom_topology for p4); no case reaches it, re-run unchanged"
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_geom_p2"
upstream = ["source/SMLib/src/SmFilletGeom.cpp"]
rust_module = "blend::fillet_geom::p2"
depends_on = ["blend.fillet_corner_p1", "blend.fillet_geom_p1", "blend.fillet_geom_p6", "blend.fillet_solver_p1", "curve.curve_p2", "geom.extent1d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_curve_p1", "surface.offset_surface", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1", "topology.vertex", "topology.vertexuse"]
soft_depends_on = ["blend.fillet_executive_p2", "blend.fillet_solver_p2", "curve.curve_p3", "curve.curve_p6", "geom.extent2d", "intersect.point_class", "intersect.surface_drop_lib_p3", "intersect.surface_intersector_p1", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_surface_p1", "surface.plane_p1", "surface.plane_p2", "surface.surface_p11", "surface.surface_p4", "topology.edgeuse_p3", "topology.face_p2"]
est_lines = 2077
layer = 62
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PARTIAL (PR #263): difftest 350 cases (50 fixture in fixtures/blend.fillet_geom_p2/cases.json, 300 generated at 1e-6..1e6 scales incl. coincident/parallel/disjoint-domain planes, tiny/negative tolerances, zero directions, reversed and coincident points, sub-domain rails), 219 pass bit-identical (max_rel_err 0, with_values 219, no_values 0; 125 compare a status-0 run: sm_SrfSrfIntersection plane/plane 55 and B-spline/B-spline 34, CalcRailRailInterpolation 24, UpdateSplitFace 12; 94 an upstream error status), 0 failed, 131 deferred (surface.surface_cache_p1 54, intersect.surface_drop_lib_p3 33, intersect.surface_intersector_p2 23, intersect.surface_intersector_p4 19, curve.crv_on_surf 2); --perturb SENSITIVE 219/219. The four vertex calculators (CalcRailIntRail, CalcRailIntEdgeuse, CalcVertOnCrossSection, CalcSetBackVert) are compared on their no-corner null-pointer exit only (35 cases): past it they read the corner, UNPORTED(blend.fillet_corner_p1); their bodies are ported and stop at stubs for blend.fillet_solver_p2 (RailRailIntersect, PointOnPlaneSolve), blend.fillet_geom_p6 (GetRailIndexOfSideEU, RailEdgeuseIntersect, ShouldSwapFaces), blend.fillet_executive_p2 (SmTemporaryRadiusChange::SetUp) and intersect.surface_drop_lib_p3 (SmSurface::DropCurve off planes). Built on PR #256 (blend.fillet_corner_p3, carrying #252, #147, #192); wires the sm_SrfSrfIntersection stubs of blend.fillet_geom_p4 and blend.fillet_solver_p1 (re-run: both partial, 0 failed). Merge fix: SmFilletGeom::MakeFaceBrep (p4) takes the NotifyEnv the face makers now need. No co-ports. Shim is compiled into blend_fillet_geom_p1.cpp's translation unit for the file-static helpers. Plan notes: 10 fns; largest: SmFilletVertex::CalcRailIntEdgeuse, SmFilletEdge::CalcRailRailInterpolation, sm_SrfSrfIntersection, SmFilletVertex::CalcVertOnCrossSection; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; UPDATE (PR #247, blend.fillet_geom_p6): GetRailIndexOfSideEU, RailEdgeuseIntersect (now stopping at SmFilletSolver::RailEdgeuseIntersect, blend.fillet_solver_p2) and ShouldSwapFaces wired; UpdateSplitFace takes the kernel, target and corner table. Re-run unchanged: 350 cases, 219 pass, 0 failed, 131 deferred"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_geom_p3"
upstream = ["source/SMLib/src/SmFilletGeom.cpp"]
rust_module = "blend::fillet_geom::p3"
depends_on = ["blend.fillet_geom_p1", "blend.fillet_solver_p1", "curve.curve_p2", "geom.extent1d", "geom.object", "geom.solution_array", "geom.vector3d", "intersect.surface_intersector_p1", "surface.offset_surface", "topology.edge", "topology.edgeuse_p1", "topology.proto_topology_p1", "topology.vertex"]
soft_depends_on = ["blend.fillet_corner_p1", "blend.fillet_executive_p1", "blend.fillet_intersector", "curve.curve_p1", "curve.curve_p4", "curve.curve_p6", "geom.geom_utility_p1", "geom.tol", "geom.vector2d", "intersect.surface_intersector_p4", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_curve_p1", "topology.vertexuse"]
est_lines = 1032
layer = 60
tests = ["SM_API_test:TestSmFilletPreview", "SM_API_test:TestSmSurfaceSurfaceFillet", "SM_API_test:TestSmCircularFillet", "SM_API_test:TestSmChamferFillet", "SM_API_test:TestSmFilletEdges", "SM_API_test:TestSmFilletEdgesPerEdge"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "6 fns; largest: SmFilletGeom::ReCalcFilletGeom, SmFilletGeom::TopologySplit, SmFilletEdge::CalcFilletIntFillet, SmFilletVertex::CalcMateGeom; cycle back-edges (call into later units; stub or co-port): blend.fillet_geom_p5(9), blend.fillet_geom_p2(7), blend.fillet_geom_p6(4), blend.fillet_geom_p4(2), blend.fillet_solver_p2(2), blend.fillet_corner_p2(1); unit-SCC #22 (220 units); 31 upstream test entry points reach this unit; PR #242 partial: 325 cases (25 fixture in fixtures/blend.fillet_geom_p3/cases.json, 7 of them expected_rejection regressions; 300 generated: mates, on-vertex, fillet x fillet edges (with and without a 3D curve, crossing planes and patches), corner-edge dispatch (incl. CalcRailRailInterpolation), the part-2/4 vertex calculators through CalcCornerVertGeom and as a mate's main vertex, ReCalcFilletGeom with unset (-SM_BIG_DOUBLE) rail-end uvs), 275 passed, 43 deferred (intersect.surface_intersector_p4 31: DoPointIntersection on the SmFilletIntersector in ReCalcFilletGeom, a DISPATCH GAP: the base driver does not reach the fillet intersector's overrides and FilletSolver does not implement fillet_intersector::FilletSolverOps, the intersector's constructor is wired (#179); and the point-based intersection inside sm_SrfSrfIntersection of two B-spline fillet surfaces; blend.fillet_geom_p5 8: CalcCrossSection, the vertex CalcFilletIntFillet; blend.fillet_corner_p1 2: GetFilletEdges in CalcRailRailInterpolation with a corner; blend.fillet_corner_p2 2: RecordFilletError after a failed intersection), 7 rejected, 0 failed, max_rel_err=4.6e-15, no absolute floors; 2000-seed sweep 1750 pass / 268 deferred / 0 failed; --perturb SENSITIVE 275/275; --fuzz 3000 FUZZ-PASS. The stubs into blend.fillet_geom_p2 and p4 (#263) are wired: CalcRailIntRail, CalcRailIntEdgeuse, CalcVertOnCrossSection, CalcSetBackVert, CalcRailIntExtendedEdgeuse, CalcFilletInt2Fillets, CalcRailRailInterpolation and sm_SrfSrfIntersection (then SetCurve/SetUVCurve); the shim runs the vertex calculators on vertices without a corner, as #263's shims do. The edge's CalcFilletIntFillet is FilletBrep::calc_edge_fillet_int_fillet (the vertex one is blend.fillet_geom_p5's, #264). Carries #192 at 3fe34880. TopologySplit is kernel-tested only (upstream needs a real SmFilletExecutive). ReCalcFilletGeom never reaches success until the intersector dispatch gap is closed. Back-edge UNPORTED(blend.fillet_geom_p3) TopologySplit in blend/fillet_solver/p1.rs (split_fillet_geom_at_side_edge) is not wired: it sits behind an earlier blend.fillet_geom_p6 stub (GetRailIndexOfVertexuse) and uses the solver's opaque FilletGeomRef; wire it with the &mut FilletBrep threading that #192's findings describe for the blend.fillet_geom_p1 sites (and #303). Upstream issues UB-211 (CalcVertOnVert NULL/wrong-kind object), UB-185 (unbounded mate recursion; MAX_MATE_DEPTH = 64), UB-208 (ReCalcFilletGeom reads the first of no sorted points without a march direction), UB-210 (CalcFilletIntFillet reads the context of a missing corner); the shim refuses exactly those models.; UPDATE (PR #247): the part 5 calculators are wired in CalcCornerVertGeom / CalcCornerEdgeGeom (CalcFilletIntFillet, CalcCrossSection, CalcFilletIntSideFace, CalcEdgeOnExtendedEdge) and in the edge's CalcFilletIntFillet (now taking the target B-rep); ReCalcFilletGeom's CalcCrossSection stays UNPORTED(blend.fillet_geom_p5) (it needs a solver table ReCalcFilletGeom does not get; unreachable today). Re-run: 325 cases, 283 pass, 0 failed, 35 deferred, 7 rejected"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_geom_p4"
upstream = ["source/SMLib/src/SmFilletGeom.cpp"]
rust_module = "blend::fillet_geom::p4"
depends_on = ["blend.fillet_corner_p1", "blend.fillet_geom_p1", "blend.fillet_solver_p1", "geom.a_object", "geom.extent1d", "geom.extent2d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_curve_p1", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1", "topology.vertex"]
soft_depends_on = ["blend.fillet_executive_p1", "boolean.merge_p1", "boolean.topology_intersector_p2", "boolean.topology_intersector_p3", "curve.curve_p2", "curve.curve_p3", "curve.curve_p4", "curve.curve_p5", "curve.curve_p6", "curve.curve_p8", "geom.attribute", "geom.axis2_placement", "geom.extent3d", "intersect.surface_intersector_p1", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_curve_p2", "nurbs.b_spline_surface_n_lib_p1", "nurbs.b_spline_surface_n_lib_p2", "nurbs.b_spline_surface_p1", "surface.plane_p1", "surface.surf_of_revolution_p1", "surface.surface_p1", "surface.surface_p11", "surface.surface_p4", "surface.surface_p5", "topology.brep_p1", "topology.brep_p7", "topology.face_p2", "topology.face_p4", "topology.trimming_tools", "topology.vertexuse"]
est_lines = 2074
layer = 60
tests = ["SM_API_test:TestSmFilletPreview", "SM_API_test:TestSmSurfaceSurfaceFillet", "SM_API_test:TestSmCircularFillet", "SM_API_test:TestSmChamferFillet", "SM_API_test:TestSmFilletEdges", "SM_API_test:TestSmFilletEdgesPerEdge"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PARTIAL (edited by PR #264 blend.fillet_geom_p5, difftest re-run with identical results: sm_CreateUVCurve's surface solves name the surface via UvSurfaceHandle; calc_fillet_int_2_fillets names its two curves via blend.fillet_geom_p1's CurveObjectHandle; srf_srf_intersection / SrfSrfCurves are pub(super)): difftest 398 cases (98 fixture incl. 42 review adversarial sm_CreateUVCurve cases and 6 MakeFaceBrep solver-tolerance cases, 300 generated), 362 pass, 0 failed, 36 deferred (blend.fillet_geom_p6 36: JoinTwoFilletVertsByCurves in MakeFaceBrep, SmFilletEdge::CalcBlendingRail, GetRailIndexOfVertexuse); sm_CreateUVCurve compared fully (bit-identical); sm_SrfSrfIntersection (blend.fillet_geom_p2, wired by that unit) in the vertex calculators and the plane branch of sm_CreateUVCurve are not reached by the shim's models; RegisterExistingSSI (ported in boolean.topology_intersector_p2) stays stubbed as UNPORTED(blend.fillet_executive_p1) because it runs on the executive's intersector; InsertIntersectionTopology unit tests only (needs the fillet executive, blend.fillet_executive_p1). Only sm_CreateUVCurve compares real values; MakeFaceBrep, CalcBlendingGeom and the three vertex calculators compare early exits only (everything after JoinTwoFilletVertsByCurves or sm_SrfSrfIntersection is deferred, and the p1 model cannot put an original face on a fillet edge, so CalcRailIntExtendedEdgeuse never passes NER(pSideFace)): the porter of blend.fillet_geom_p6 must extend this runner. Built on PR #147 (blend.fillet_geom_p1) and PR #192 (blend.fillet_solver_p1), both merged. Was: 8 fns; largest: sm_CreateUVCurve, SmFilletGeom::MakeFaceBrep, SmFilletGeom::InsertIntersectionTopology, SmFilletVertex::CalcRailIntExtendedEdgeuse; cycle back-edges (call into later units; stub or co-port): blend.fillet_geom_p2(4), blend.fillet_geom_p6(4); unit-SCC #22 (220 units); 31 upstream test entry points reach this unit; UPDATE (PR #247, blend.fillet_geom_p6): GetRailIndexOfVertexuse, JoinTwoFilletVertsByCurves, CalcBlendingRail and RecordFilletError wired to part 6 (MakeFaceBrep's 3D curve list is Option<Curve>, as the join appends). The runner's MakeFace B-rep now has the void infinite region SmBrep() makes (Brep::new_with_infinite_region; before, TrimSurfaceWithModelSpaceCurves stopped at NER(pRegion) where C++ goes on). Fix: CalcBlendingGeom reads m_vRails[i] as its loop reaches it (a NULL second rail after a failing first rail is SM_ERR, not SM_ERR_NULL_POINTER; 2 fixtures in review.json). Re-run: 400 cases, 382 pass, 0 failed, 18 deferred (topology.brep_p3 18); --seeds 2000: 2038 pass, 0 failed, 60 deferred; --perturb SENSITIVE 382/382"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_geom_p5"
upstream = ["source/SMLib/src/SmFilletGeom.cpp"]
rust_module = "blend::fillet_geom::p5"
depends_on = ["blend.fillet_corner_p1", "blend.fillet_geom_p1", "blend.fillet_geom_p2", "blend.fillet_geom_p4", "blend.fillet_geom_p6", "blend.fillet_solver_p1", "curve.curve_p2", "geom.extent1d", "geom.extent2d", "geom.object", "geom.solution_array", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_curve_p1", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1", "topology.proto_topology_p1", "topology.topology", "topology.vertex"]
soft_depends_on = ["blend.fillet_executive_p1", "curve.curve_p1", "curve.curve_p4", "curve.curve_p6", "curve.curve_p9", "curve.hermite_curve", "geom.tol", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_curve_p2", "surface.offset_surface", "surface.plane_p1", "surface.surface_p11", "surface.surface_p7", "topology.face_p2", "topology.vertexuse"]
est_lines = 1952
layer = 63
tests = ["SM_API_test:TestSmFilletPreview", "SM_API_test:TestSmSurfaceSurfaceFillet", "SM_API_test:TestSmCircularFillet", "SM_API_test:TestSmChamferFillet", "SM_API_test:TestSmFilletEdges", "SM_API_test:TestSmFilletEdgesPerEdge"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PARTIAL (PR #264, unstacked: #252 blend.fillet_geom_p4 is merged): all 13 fns ported (SmFilletGeom(SmFilletSolver*, type) was CO-PORTED in blend.fillet_geom_p1 as FilletGeom::new; the other 12 in blend::fillet_geom::p5 with UNPORTED stubs at each unported call: blend.fillet_corner_p1 (corner type/flags/filleted vertex/extended surfaces/tolerance), blend.fillet_corner_p2 (RecordFilletError), blend.fillet_geom_p6 (FindEdgeTangentAtPoint, Copy), blend.fillet_executive_p1 (GetPseudoBrep), blend.fillet_geom_p1 sm_ExamineNFixFilletGeoms (justified: findings.md 'blend.fillet_geom_p5: examine solvers'); the builders stop at FilletBrep::new_fillet_edgeuse's UNPORTED(topology.brep_p3) infinite region). blend.fillet_geom_p2 wired (sm_SrfSrfIntersection through p4's adapter, SmFilletEdge::UpdateSplitFace with its status ignored). The UNPORTED(blend.fillet_geom_p5) stubs in blend.fillet_solver_p1 / blend.fillet_corner_p3 stay (justified: findings.md 'blend.fillet_geom_p5: solver and corner callers'; follow-up for blend.fillet_solver_p1 / blend.fillet_corner_p3: address geometries in a FilletBrep). difftest 300 generated cases: 245 pass, 0 fail, 55 deferred (blend.fillet_geom_p6 37: 26 SplitFace cases at SmFilletEdge::ShouldSwapFaces, 11 SM_BT_BLEND end curves at FindEdgeTangentAtPoint; intersect.surface_intersector_p2 7 and _p4 1: the cliff-rail and side-face surface intersections of TrimRails; topology.brep_p3 10: SmBrep::SmBrep of 5 MakeFilletEdge and 5 MakeRailEdge), max_rel_err 0; --perturb SENSITIVE 245/245. Per op: IntFillet 3, CrossSection 54, SideFace 7, ExtEdge 4, TrimRails 140, SplitFace 32 (6 pass), MakeEdge 5, RailEdge 5, EndCurve 49 (11 BLEND, all deferred), RailEdgeuse 1. Paths (breakpoint count per case): 32 cases reach UpdateSplitFace, 26 of them ShouldSwapFaces (all deferred; the 6 that do not reach it compare original and split faces); 44 reach TrimCliffRails (36 pass, 8 defer at the intersection) and 7 of those CalcCliffRailIntEdge; 11 reach FindEdgeTangentAtPoint (SM_BT_BLEND, all deferred). Of the 245 passes 202 compare 3+ values (trim_rails, cross_section, split_face), 39 compare the status and one value and 4 only the status (CalcFilletIntFillet/CalcEdgeOnExtendedEdge stop at the first NER of their corner and the builders at their early exits, so the bodies of calc_fillet_int_fillet and calc_edge_on_extended_edge are compared by no case until blend.fillet_corner_p1 lands). Review rounds: the rail solves name the rail curve in their solutions (CurveObjectHandle), p4's sm_CreateUVCurve its surface (UvSurfaceHandle), p1's sm_TwoPntsIntersection / p2's CalcSetBackVert their surfaces (SurfaceHandle) and p4's CalcFilletInt2Fillets its curves, so SmGlobalSolver::IdenticalSolutions merges near-duplicates as upstream (findings.md 'rail trims and cross sections disagree in the tolerance-dominated regime (resolved)'); upstream-issues UB-213 (CalcCrossSection lifts *pUVCurve1) and UB-214 (CalcFilletIntSideFace pCorner) and UB-238 (MakeRailEdgeuse leaves a deleted vertex use linked; the RailEdgeuse op refuses that path). Shim: harness/cpp/shim/blend_fillet_geom_p5_static.inc, included by the p1 shim after p4's; p1's model gained pc_kind 4 (an SmEdge for SM_PC_EDGE). Plan notes: 13 fns; largest: SmFilletGeom::TrimCliffRails, SmFilletGeom::TrimRailCurves, SmFilletEdge::CalcCrossSection, SmFilletVertex::CalcFilletIntFillet; cycle back-edges (call into later units; stub or co-port): blend.fillet_corner_p2(1); unit-SCC #22 (220 units); 31 upstream test entry points reach this unit; UPDATE (PR #247, blend.fillet_geom_p6): FindEdgeTangentAtPoint (CreateEndCurve now takes the target B-rep) and SmFilletGeom::Copy wired to part 6. Re-run: 300 cases, 274 pass, 0 failed, 26 deferred (intersect.surface_intersector_p2 7, _p4 1, topology.brep_p3 18; none on blend.fillet_geom_p6)"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_geom_p6"
upstream = ["source/SMLib/src/SmFilletGeom.cpp"]
rust_module = "blend::fillet_geom::p6"
depends_on = ["blend.fillet_geom_p1", "blend.fillet_solver_p1", "curve.curve_p2", "geom.extent1d", "geom.extent2d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_curve_p1", "surface.surface_p2", "topology.brep_p3", "topology.edge", "topology.edgeuse_p1", "topology.topology", "topology.vertex"]
soft_depends_on = ["blend.fillet_corner_p1", "blend.fillet_executive_p1", "blend.fillet_solver_p2", "boolean.merge_p1", "boolean.topology_intersector_p1", "curve.curve_p6", "curve.hermite_curve", "geom.context", "geom.geom_utility_p1", "intersect.curve_class_p1", "intersect.point_class", "intersect.surface_drop_lib_p3", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_curve_p2", "surface.offset_surface", "surface.surface_p11", "surface.surface_p4", "surface.surface_p7", "topology.edgeuse_p3", "topology.face_p2", "topology.loopuse", "topology.topology_traverser", "topology.vertexuse"]
est_lines = 1813
layer = 60
tests = ["SM_API_test:TestSmFilletPreview", "SM_API_test:TestSmSurfaceSurfaceFillet", "SM_API_test:TestSmCircularFillet", "SM_API_test:TestSmChamferFillet", "SM_API_test:TestSmFilletEdges", "SM_API_test:TestSmFilletEdgesPerEdge"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "17 fns; largest: SmFilletGeom::TrimOriginalSurfaces, SmFilletEdge::CalcBlendingRail, SmFilletEdge::CalcSetBackRail, JoinTwoFilletVertsByCurves; unit-SCC #22 (220 units); 31 upstream test entry points reach this unit; PR #247 partial: 400 generated cases (edge on edge, fillet end, set-back rail, blending rail, ShouldSwapFaces, JoinTwoFilletVertsByCurves, SmFilletGeom::Copy, the rail lookups and SetUpRailPoint, sm_MoveTSP, RailEdgeuseIntersect, RecordFilletError), 304 pass bit-identical, 0 failed, 96 deferred (harness:analytic-geometry-export 61: ops evaluating cone/cylinder/torus/revolution faces or analytic edges the B-rep export carries as their B-spline part; topology.face_p4 11: sm_ClassifyFacePoint's face queries (the stub owner moved from topology.face_p3 when that unit landed); blend.fillet_executive_p1 9: NoteFilletError; blend.fillet_solver_p2 8: RailEdgeuseIntersect; intersect.surface_drop_lib_p3 7: DropCurve), max_rel_err=0, no absolute floors; --seeds 3000: 2396 pass, 604 deferred, 0 failed; --perturb SENSITIVE 304/304; --fuzz 2000 FUZZ-PASS. After topology.face_p4 (PR #239) landed: 315 pass, 0 failed, 85 deferred (its 11 sm_ClassifyFacePoint cases compare bit-identical); --perturb SENSITIVE 315/315. Built on #242 (blend.fillet_geom_p3, which merges #147 and #192; re-merged at eb6560b7). No co-ports: the corner members part 6 reads come from blend::fillet_corner::p3::FilletCorner (#256) and the solver lookup is blend::fillet_geom::p4::solver_of. TrimOriginalSurfaces is not compared against the C++, kernel-tested only (needs a fillet B-rep and executive topology-intersector mates the shim does not build); the curve-classification branch of ShouldSwapFaces is not generated. Wired UNPORTED(blend.fillet_geom_p6) in blend/fillet_geom/p3.rs (CalcEdgeOnEdge, CalcFilletEnd, CalcSetBackRail through CalcCornerEdgeGeom; sm_MoveTSP in ReCalcFilletGeom), p2.rs (GetRailIndexOfSideEU, RailEdgeuseIntersect, ShouldSwapFaces), p4.rs (GetRailIndexOfVertexuse, JoinTwoFilletVertsByCurves, CalcBlendingRail, RecordFilletError), fillet_corner/p3.rs (GetRailVertex) and fillet_executive/p3.rs (TrimOriginalSurfaces adapter); p4 deferred 36 -> 0 on part 6, corner_p3 33 -> 0. GetRailIndexOfVertexuse takes an Option and keeps upstream's NER(pFVU). Not wired: GetRailIndexOfVertexuse, GetRailVertex, SetUpRailPoint in blend/fillet_solver/p1.rs (split_fillet_geom_at_side_edge, split_fillet_geom): those take the solver's opaque FilletGeomRef and a plain pseudo Brep, not a FilletBrep, as for p3's TopologySplit. Found on the way: surface.surface_p2's sm_IntersectAndSplit passed no curve handle, so near-duplicate plane roots were not merged as upstream and LiftCurve split UV curves ~1e-10 off (findings.md); main's #444 fixed it the same way and this PR now uses main's fix. Moved onto #303 (blend.fillet_solver_p1 green: FilletGeomRef replaced by pseudo-B-rep FilletGeomIds; merge e67e390e): wired the solver's p6 calls (GetRailIndexOfVertexuse and GetRailVertex in SplitFilletGeomAtSideEdge, GetRailVertex/SetUpRailPoint in SplitFilletGeom) and SmFilletGeom::TopologySplit (blend.fillet_geom_p3); FilletBrep::rail_edgeuse_intersect drops its FilletGeomRef argument, re_calc_fillet_geom its geometry_id resolver. Numbers unchanged: 400 cases, 315 pass, 0 failed, 85 deferred; blend.fillet_corner_p3's geom_p6(33) deferrals now run (592 pass, 0 failed); adjust_tangent_corner's SplitFilletGeomAtSideEdge is wired through a new CornerEnv::solvers table; its one case (gen0067) is now rejected: the model's geometries have no solver and upstream dereferences NULL (shim refuses; corner_p3 592 pass, 357 deferred, 56 rejected). After merging main 5c3adfbe (#264 blend.fillet_geom_p5): 400 cases, 309 pass, 0 failed, 91 deferred; 6 generated cases (gen0044/0056/0093/0147/0281/0380) moved from pass to deferred at SmSurface::DropCurve (intersect.surface_drop_lib_p3), reached now that #264's p1/p2 solves name their objects as upstream does; TopologySplit's MakeRailEdgeuse/MakeFilletEdge call p5's (FilletBrep::make_rail_edgeuse_on)."
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_intersector"
upstream = ["source/SMLib/inc/SmFilletIntersector.h", "source/SMLib/src/SmFilletIntersector.cpp"]
rust_module = "blend::fillet_intersector"
depends_on = ["blend.fillet_geom_p1", "blend.fillet_solver_p1", "curve.crv_on_surf", "curve.hermite_curve", "geom.extent1d", "geom.extent2d", "geom.vector2d", "geom.vector3d", "intersect.adv_surface_intersector", "intersect.surface_intersector_p1", "surface.surface_p2", "topology.edge"]
soft_depends_on = ["curve.curve_p2", "curve.curve_p3", "geom.geom_utility_p1", "geom.object", "geom.solution_array", "nurbs.b_spline_curve_p1", "surface.surface_p1", "topology.edgeuse_p1"]
est_lines = 1708
layer = 50
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "12 fns; largest: SmFilletIntersector::ComputeNextPoint, SmFilletIntersector::FlushCurve, SmFilletIntersector::TestSpanAccuracy, sm_FlushCrv; cycle back-edges (call into later units; stub or co-port): blend.fillet_solver_p2(2), blend.fillet_solver_p4(2), blend.fillet_solver_p3(1); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; PARTIAL (PR #179): difftest cases=1286 passed=908 deferred=378 (PR #192 after #168: the 33 ComputePointValuesDelta cases that deferred at SmConstantRadiusFS::SetupOffsetValues run and pass, with the runner writing the op's points back to the arena as the shim's references do; blend.fillet_solver_p2 37, _p3 120, _p4 59, curve.crv_on_surf 162: SmCrvOnSurf over an SmPlane is a dispatch gap); FlushCurve of 2+ points is not run in C++ (dereferences the unset m_pExecutive and NULL fillet geometry rails) and is covered by unit tests only Re-verified after merging main (surface.offset_surface green): FilletSolverOps::rail_surface_evaluate_1st_derivatives (GetSurface(rail)->Evaluate1stDerivatives) now evaluates the ported SmOffsetSurface of ConstantRadiusAssistedFs (no UNPORTED(surface.offset_surface) left); cases=1213 passed=803 failed=0 deferred=410, --perturb 803/803. Review fixes: FilletSolverOps::step_solve takes rdStep in/out and its flags as an out-param kept on failure; 73 review fixtures (fixtures/blend.fillet_intersector/review_cases.json); cases=1286 passed=875 failed=0 deferred=411 (_p3 120: rv_next_clipped_step pins the C++ rescaled step)."
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_solver_p2"
upstream = ["source/SMLib/src/SmFilletSolver.cpp"]
rust_module = "blend::fillet_solver::p2"
depends_on = ["blend.fillet_executive_p1", "blend.fillet_geom_p1", "blend.fillet_solver_p1", "curve.curve_p2", "geom.axis2_placement", "geom.extent1d", "geom.extent2d", "geom.local_solve_nd", "geom.object", "geom.solution_array", "geom.vector3d", "intersect.point_class", "intersect.surface_intersector_p1", "nurbs.b_spline_curve_p1", "surface.surf_of_revolution_p1", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1", "topology.vertex"]
soft_depends_on = ["curve.curve_p1", "curve.curve_p4", "curve.curve_p5", "curve.curve_p6", "curve.line", "geom.tol", "geom.vector2d", "intersect.curve_class_p1", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_surface_p1", "nurbs.b_spline_surface_p2", "surface.offset_surface", "surface.plane_p1", "surface.surf_of_revolution_p2", "surface.surf_of_revolution_p3", "surface.surface_p8", "topology.edgeuse_p3", "topology.face_p2", "topology.proto_topology_p1", "topology.vertexuse"]
est_lines = 1939
layer = 59
tests = ["prog_test:my_test_parallel_projection", "prog_test:my_test_tsurf_projection", "prog_test:my_test_surface_interface", "prog_test:my_test_ssi", "prog_test:my_test_tsurf_section", "prog_test:my_test_planar_section"]
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "10 fns; largest: SmFilletSolver::CreateCliffRollOverSideFG, SmFilletSolver::CalcTorusFilletGeom, sm_FindRolloverSideEdge, SmFilletSolver::CalcCylinderFilletGeom; cycle back-edges (call into later units; stub or co-port): blend.fillet_geom_p2(3), blend.fillet_geom_p5(2), blend.fillet_executive_p2(1), blend.fillet_geom_p6(1); unit-SCC #22 (220 units); 150 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_solver_p3"
upstream = ["source/SMLib/src/SmFilletSolver.cpp"]
rust_module = "blend::fillet_solver::p3"
depends_on = ["blend.fillet_geom_p1", "blend.fillet_solver_p1", "curve.curve_p2", "curve.iso_curve", "geom.extent1d", "geom.extent2d", "geom.local_solve_nd", "geom.object", "geom.solution_array", "geom.tol", "geom.vector2d", "geom.vector3d", "intersect.curve_class_p1", "intersect.surface_intersector_p1", "surface.offset_surface", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1", "topology.vertex"]
soft_depends_on = ["blend.fillet_executive_p1", "blend.fillet_standard_solver_p1", "curve.curve_p1", "geom.a_object", "geom.local_solve1d", "intersect.point_class", "surface.surface_p4", "surface.surface_p6", "topology.edgeuse_p2", "topology.face_p2", "topology.loopuse", "topology.vertexuse"]
est_lines = 1112
layer = 59
tests = ["prog_test:my_test_parallel_projection", "prog_test:my_test_tsurf_projection", "prog_test:my_test_surface_interface", "prog_test:my_test_ssi", "prog_test:my_test_tsurf_section", "prog_test:my_test_planar_section"]
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "7 fns; largest: SmFilletSolver::StepSolve, SmFilletSolver::ProcessFullRollOver, SmFilletSolver::SplitAndTrimFilletSurface, sm_RefineRailCurveClassification; cycle back-edges (call into later units; stub or co-port): blend.fillet_solver_p2(6), blend.fillet_geom_p5(2), blend.fillet_geom_p2(1); unit-SCC #22 (220 units); 150 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_solver_p4"
upstream = ["source/SMLib/src/SmFilletSolver.cpp"]
rust_module = "blend::fillet_solver::p4"
depends_on = ["blend.fillet_geom_p1", "blend.fillet_intersector", "blend.fillet_solver_p1", "curve.curve_p2", "geom.extent1d", "geom.solution_array", "geom.vector2d", "geom.vector3d", "intersect.surface_intersector_p1", "nurbs.b_spline_curve_p1", "surface.offset_surface", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1"]
soft_depends_on = ["curve.curve_p1", "curve.curve_p4", "curve.curve_p5", "curve.curve_p6", "geom.axis2_placement", "geom.geom_utility_p1", "intersect.surface_intersector_p4", "nurbs.b_spline_curve_p2", "surface.surface_p7", "topology.edgeuse_p3", "topology.vertex", "topology.vertexuse"]
est_lines = 1404
layer = 51
tests = ["prog_test:my_test_parallel_projection", "prog_test:my_test_tsurf_projection", "prog_test:my_test_surface_interface", "prog_test:my_test_ssi", "prog_test:my_test_tsurf_section", "prog_test:my_test_planar_section"]
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "2 fns; largest: SmFilletSolver::CalcFilletGeom, SmFilletSolver::ComputePointValues; cycle back-edges (call into later units; stub or co-port): blend.fillet_solver_p2(3), blend.fillet_solver_p3(2), blend.fillet_geom_p3(1), blend.fillet_geom_p4(1), blend.fillet_geom_p5(1); unit-SCC #22 (220 units); 150 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.fillet_solver_p5"
upstream = ["source/SMLib/src/SmFilletSolver.cpp"]
rust_module = "blend::fillet_solver::p5"
depends_on = ["blend.fillet_geom_p1", "blend.fillet_solver_p1", "curve.curve_p2", "geom.object", "geom.solution_array", "intersect.curve_class_p1", "surface.offset_surface", "topology.edge"]
soft_depends_on = ["curve.curve_p1", "geom.extent1d", "geom.tol", "geom.vector3d", "intersect.curve_class_p2", "intersect.curve_class_p4", "intersect.point_class", "query.face_p2", "surface.surf_of_revolution_p1", "surface.surf_of_revolution_p2", "surface.surface_p2", "topology.edgeuse_p1", "topology.edgeuse_p2", "topology.face_p2", "topology.vertex"]
est_lines = 848
layer = 50
tests = ["SM_API_test:TestSmCircularFillet", "SM_API_test:TestSmChamferFillet", "SM_API_test:TestSmFilletEdges", "SM_API_test:TestSmFilletEdgesPerEdge", "SM_API_test:TestSmVariableRadiusFillet", "SM_API_test:TestSmSetBevelCorners"]
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "2 fns; largest: SmFilletSolver::ProcessRollOver, SmFilletSolver::TestRollOver; cycle back-edges (call into later units; stub or co-port): blend.fillet_solver_p3(3), blend.fillet_geom_p2(2), blend.fillet_geom_p3(2), blend.fillet_geom_p5(2), blend.fillet_solver_p2(2), blend.fillet_executive_p1(1); unit-SCC #22 (220 units); 25 upstream test entry points reach this unit"
@@ -0,0 +1,12 @@
id = "blend.fillet_standard_solver_p1"
upstream = ["source/SMLib/inc/SmFilletStandardSolver.h", "source/SMLib/src/SmFilletStandardSolver.cpp"]
rust_module = "blend::fillet_standard_solver::p1"
depends_on = ["blend.fillet_solver_p1", "curve.curve_p2", "geom.axis2_placement", "geom.extent1d", "geom.extent2d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_curve_p1", "nurbs.b_spline_curve_p2", "nurbs.b_spline_surface_p1", "nurbs.b_spline_surface_p2", "surface.offset_surface", "surface.surface_p1", "surface.surface_p2", "surface.surface_p7", "topology.edgeuse_p1"]
soft_depends_on = ["blend.fillet_custom_solver", "curve.curve_p1", "curve.curve_p4", "curve.curve_p5", "curve.curve_p6", "geom.matrix", "nurbs.b_spline_curve_p3", "nurbs.b_spline_surface_n_lib_p1", "nurbs.b_spline_surface_n_lib_p2", "surface.surface_p3", "surface.surface_p4", "surface.surface_p5", "topology.edge", "topology.edgeuse_p3", "topology.face_p2", "topology.loopuse"]
est_lines = 2336
layer = 50
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PARTIAL (PR #168): difftest 3839 cases (3359 fixture incl. 709 review_adversarial and 2625 second-review cases: review2_cd_init 960, review2_jac_ext 1560, review2_closed_torus_base 105; + 480 generated), 3786 pass at max_rel_err 0, 0 failed, 42 deferred (blend.fillet_executive_p1 16: SmFilletLaw::Evaluate in SmVariableRadiusFS::SetupOffsetValues; edge-use constructor cases on upstream solids whose import is inexact or that need a new UV trim curve: surface.cone_p1 11, topology.brep_p10 6 (SmBrep::MakeTopologyFromData; topology.brep_p7 before the 2026-10-19 merge of main), intersect.surface_drop_lib_p3 6, surface.sphere 2, surface.surf_of_extrusion_p2 1), 11 rejected by the shim's dry run (UB-202, UB-203, HANG-34); --perturb SENSITIVE 3786/3786; --fuzz 1000 FUZZ-PASS after the second review (crSurface1 of SmConstantDistanceFS::LoadInitialValues is now an InitialSurface naming the solver's own rail, as upstream's callers pass *GetSurface(lRailIndex): 72 cd_init cases disagreed before; 18 G1 blend-curve skins of the review cases are UB-203b and not fixtures; plan/findings.md); earlier --fuzz 5000 FUZZ-PASS (0 crashes, 0 differs; review fixes: runner bounds Jacobian size and derivative count, plane domains built as given, FFI rejects reversed plane domains under the solvers' offset surfaces; UB-186 not detected by the shim, UB-187 guarded, 2 review cases kept out of fixtures, plan/findings.md); 5000-seed run 5025 cases, 4485 pass, 0 failed, 408 deferred, 132 rejected. Generators compared on ruled, revolved and skinned circular / blend-curve sections (approximated and exact arcs, mirror, complement, point and skipped sections, G1, synchronised knot counts, scales 1e-6..1e6), EvaluateBaseCurve (B-spline, SmLine, Hermite; snapping, extension, reuse), SetupOffsetExtension (planes, closed and singular B-splines), the SmConstantRadiusFS surface constructor, SetupOffsetValues and LoadJacobian, SmConstantDistanceFS SetupOffsetValues, LoadJacobian and LoadInitialValues (with and without rbDoSurf2Calcs) on the ported SmOffsetSurface (surface.offset_surface, wired after the merge of main), SmVariableRadiusFS queries, and the SmConstantRadiusFS edge-use constructor on topology.edgeuse_p1 B-reps (SmEdgeuse::EvaluateBinormal of topology.edgeuse_p3 wired; successful constructions on box_with_large_fillet.smb, the tangent exit on laminas; second shim blend_fillet_standard_solver_p1_eu.cpp). Not compared: SmVariableRadiusFS::SetExtensionFlags (calls SmFilletSolver::SetExtensionFlags, wired in PR #192: VariableRadiusFs::set_extension_flags(b: &Brep), which stops at SmFilletExecutive::GetFilletCornerOfVertex, blend.fillet_executive_p1). PR #192 (merged main after this unit): the co-ported SmFilletSolver members (FilletSolverData), SmFilletSolverType, SmFilletSurfaceGeneratorType, fillet_solver_is_kind_of and GuessSphereSolve's SmFilletSphereSolveENFO members are replaced by blend.fillet_solver_p1's FilletSolver (ConstantDistanceFs::solver, CurveBasedFs::solver; rails through FilletSolver::surface), FilletSolverType, FilletSurfaceGeneratorType (re-exported), FilletSolver::is_kind_of and FilletSphereSolveEnfo (GuessSphereSolve::new takes the solver); FilletSurfaceGenerator::Circular/BlendCurve hold this unit's CircularCrossSectionFsg/BlendCurveCrossSectionFsg. Wired the SmConstantRadiusFS edge-use constructor stub of blend.fillet_custom_solver (ConstantRadiusAssistedFs::from_edgeuse, now taking the kernel and the B-rep mutably). Fixed nlib.srf_adv_p5 (derivative strip left swapped when N_AdjustDerivSrf's extension fails, plan/findings.md). Plan notes: 51 fns; largest: SmCircularCrossSectionFSG::CreateSurfaceFromCurves, SmBlendCurveCrossSectionFSG::CreateSurfaceFromCurves, SmConstantDistanceFS::LoadJacobian, SmConstantDistanceFS::LoadInitialValues; cycle back-edges (call into later units; stub or co-port): blend.fillet_executive_p1(7); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; CO-PORTED in blend.fillet_custom_solver (PR #78): SmConstantRadiusFS::m_dFilletRadii (and the SmConstantRadiusAssistedFS base) -> solidcore::blend::fillet_custom_solver::ConstantRadiusAssistedFs::fillet_radii"
@@ -0,0 +1,12 @@
id = "blend.fillet_standard_solver_p2"
upstream = ["source/SMLib/src/SmFilletStandardSolver.cpp"]
rust_module = "blend::fillet_standard_solver::p2"
depends_on = ["blend.fillet_executive_p1", "blend.fillet_geom_p1", "blend.fillet_solver_p1", "blend.fillet_solver_p3", "blend.fillet_standard_solver_p1", "curve.curve_p2", "geom.extent1d", "geom.extent2d", "geom.local_solve_nd", "geom.matrix", "geom.object", "geom.solution_array", "geom.vector2d", "geom.vector3d", "intersect.surface_intersector_p1", "nurbs.b_spline_curve_p1", "surface.offset_surface", "surface.surface_p2", "topology.edge", "topology.edgeuse_p1"]
soft_depends_on = ["blend.fillet_intersector", "curve.curve_p1", "curve.curve_p4", "curve.curve_p5", "curve.curve_p6", "geom.geom_utility_p1", "geom.tol", "intersect.curve_class_p4", "intersect.surface_intersector_p4", "nurbs.b_spline_surface_p1", "query.face_p2", "surface.surface_p1", "surface.surface_p4", "surface.surface_p5", "surface.surface_p7", "topology.edgeuse_p3", "topology.face_p2", "topology.loopuse", "topology.vertex", "topology.vertexuse"]
est_lines = 1989
layer = 60
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "17 fns; largest: SmConstantRadiusFS::LoadInitialValues, SmVariableRadiusFS::LoadJacobian, SmVariableRadiusFS::ReCalcFilletGeom, SmSurfaceSurfaceFS::CalcFilletGeom; cycle back-edges (call into later units; stub or co-port): blend.fillet_geom_p5(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "blend.hcr"
upstream = ["source/SMLib/inc/SmHCR.h", "source/SMLib/src/SmHCR.cpp"]
rust_module = "blend::hcr"
depends_on = ["curve.curve_p2", "geom.axis2_placement", "geom.extent1d", "geom.extent3d", "geom.solution_array", "geom.tol", "geom.tree", "geom.vector3d", "intersect.curve_class_p1", "intersect.point_class", "intersect.ray_tracer", "surface.surface_p2", "topology.brep_p1", "topology.edge", "topology.edgeuse_p1", "topology.face_p2"]
soft_depends_on = ["curve.curve_p1", "curve.curve_p5", "curve.curve_p6", "curve.curve_p9", "geom.a_object", "geom.context", "geom.extent2d", "geom.grid", "geom.object", "intersect.curve_class_p2", "intersect.curve_class_p3", "intersect.curve_class_p4", "intersect.curve_class_p7", "nurbs.b_spline_surface_n_lib_p2", "nurbs.b_spline_surface_p1", "nurbs.b_spline_surface_p2", "query.brep", "surface.surface_p1", "topology.brep_p2", "topology.brep_p3", "topology.brep_p4", "topology.brep_p5", "topology.edgeuse_p3", "topology.face_p1", "topology.face_p4", "topology.loopuse", "topology.shell", "topology.topology", "topology.vertex", "topology.vertexuse"]
est_lines = 1875
layer = 49
tests = ["SM_API_test:TestSmCreateSilhouetteCurves", "prog_test:my_test_tsurface_point_extrema", "prog_test:my_test_one_tess", "prog_test:my_test_tsurface_tsurface_solve", "prog_test:my_test_ppu", "prog_test:my_sweep_null_region_counts"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "14 fns; partial (PR #191): 434 cases (34 fixtures: hints 3/-1/big/fractional and fa >= fb / fa == fb, fixtures/blend.hcr), 394 pass, 0 fail, 40 deferred (topology.edge 27, topology.face_p3 7, surface.surface_p2 3, topology.vertex 2, intersect.surface_drop_lib_p3 1) after the maintainer merges of main with topology.brep_p1 and intersect.curve_class_p2 partial (SmCurveClassification::UpdatePointClass wired to curve_class_p2; its 35 deferrals now run: 28 pass, 7 move on to topology.edge / topology.vertex). With topology.brep_p1 alone: 366 pass, 68 deferred (GetInfiniteRegion, GetEdges, GetFaces, GetSurfaces, AddDeletedSurface wired to topology::brep::p1; the PR's m_bEditingEnabled co-port dropped for brep_p1's; the runner now sets each face surface's owner to its face as the upstream build does, without which GetSurfaces selected nothing and the 2 IsPointVisible cases failed; they now defer at surface.surface_p2 / topology.face_p3); before that merge 309 pass, 125 deferred (topology.brep_p1 67); --perturb SENSITIVE 309/309 (pre-merge); probe 3000 seeds clean (before the review round). The FFI guard accepts every int64 hint (C++: 0 none, 1 visible, other invisible) and either order of fa/fb (SmExtent1d swaps). The invisible-hint fixtures read the scene's infinite region (topology.brep_p1, wired at the merge). SmEdgeuse::EvaluateBinormal is wired to topology.edgeuse_p3 (on the scene itself, bUse3DOnly FALSE), and SmBrep::GetEdges without a filter to topology::brep::p1::edges. Of the 309 passes, 259 compare values (construction state, 1-interval classifications, single-piece ComputeEdgeVisibility, silhouette lists; status/flag records for the wire, lamina and listed early-outs) and 50 are both-errored (24 inexact_geometry, 25 rejected UB-169 guard cases, 1 rejected fixture). Classifications with 2 or more intervals: 21 generated (crossing wire-loop fixtures), all deferred: InsertPointClass splits through InsertAt / EditIntervalMin / EditIntervalMax (intersect.curve_class_p2, deferred before its merge; see the counts above); likewise the 13 multi-piece ComputeEdgeVisibility cases. The scene B-rep's SmBrep copy + Transform (topology.brep_p3) and its box (query.brep) are stubbed in Hcr::with_transform (FindAndSetInfiniteRegion is wired to topology.brep_p5 since PR #285); the runner imports the C++ scene and uses Hcr::from_scene. ComputeSilhouettes / ComputeGlobalVisibility / IsPointVisible start with topology.brep_p1 queries (only IsPointVisible is generated; it defers). SmFace::FindIfRectangularTrim is wired to topology.face_p1 (IsPointVisible's surface set; not reached while IsPointVisible defers on topology.brep_p1). CO-PORTED SmCurveClassification constructor (see intersect.curve_class_p4). Upstream defects UB-169, UB-170. hazards: ptr-hash (GetSilhouetteEdges sorted by id) Re-run after wiring stale stubs (PR #285): 434 cases, 396 pass, 0 fail, 38 deferred, max_rel_err 0. API EXTENDED in sweep.topology_sweep (PR #222): Hcr::scene_brep_mut exposes the retained session scene for mutable topology-source borrows without cloning its identities."
+12
View File
@@ -0,0 +1,12 @@
id = "boolean.api_brep"
upstream = ["source/SM_API/src/SmApiBrep.cpp"]
rust_module = "boolean::api_brep"
depends_on = ["boolean.merge_p3"]
soft_depends_on = ["boolean.merge_p1", "boolean.merge_p2", "boolean.merge_p4", "geom.context", "topology.brep_p2"]
est_lines = 410
layer = 58
tests = ["SM_API_test:TestSmMaterialCensus", "SM_API_test:TestSmPiecewiseMerge", "SM_API_test:TestSmBooleanLists", "SM_API_test:TestApiMergeBrepsInvalidOperation", "SM_API_test:TestMergeBrepsOperation", "SM_API_test:TestSmMergeBreps"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "partial (PR #81): difftest cases=284 passed=142 deferred=142 (blocked_by boolean.merge_p2(81): SmMerge::SmMerge for SmApiBoolean/Union/Difference/Intersection/Merge/WithOptions; boolean.merge_p3(61): SmMerge::merge_breps / BooleanLists / BooleanTrees); compared: SmApiValidateBooleanOperands (EXTRACT_SEPARATE), SmApiMergeBreps list/operation validation incl. non-consumption; NULL/aliased operands are unrepresentable with owned Breps; C++ shim runs real box/sphere booleans for the deferred cases (record = status, faces/edges/vertices/regions/manifold) so they compare once merge lands; Rust operands are empty Breps until primitive.api_primitives (SmApiCreateBox/Sphere) is ported; 12 fns; largest: SmApiMergeBreps, SmApiBoolean, SmApiBooleanDifference, SmApiBooleanIntersection; entry points: SmApiBoolean, SmApiBooleanDifference, SmApiBooleanIntersection, SmApiBooleanLists, SmApiBooleanMerge, SmApiBooleanTrees, SmApiBooleanUnion, SmApiBooleanWithOptions, SmApiMergeBreps; 13 upstream test entry points reach this unit Re-run with boolean.merge_p3 wired (PR #245): 287 cases, 151 matched, 0 failed, 136 deferred (boolean.merge_p2 114, topology.brep_p3 21, topology.brep_p2 1); with_values=151/no_values=0 (integer status/list records, no geometric-success comparison). Perturb 151/151; fuzz 2000 PASS with 0 differs/crashes/panics/timeouts. Seven old deferrals now compare empty-first-list or stack-underflow status records; new empty-forest/unreachable-leaf cases match, defined null-leaf output remains deferred at IsManifoldSolid. Re-run in PR #149 (merge with main through 39ceb995, #283): 287 cases, 151 pass, 0 fail, 136 deferred (boolean.merge_p2 114, topology.brep_p3 21, primitive.primitive_creation_p1 1): the Trees record deferral (the Rust operands are empty stand-ins; create_box / create_sphere stop at SmPrimitiveCreation) is retagged from topology.brep_p2 (IsManifoldSolid) to primitive.primitive_creation_p1. Re-run in PR #229 (boolean.merge_p2 wired, merge with main through e5f3e441): 287 cases, 151 pass, 0 fail, 136 deferred (boolean.merge_p4 114, topology.brep_p3 21, primitive.primitive_creation_p1 1): the two-B-rep entry points construct the merge through merge_p3's DependencyMerge (MergeState::with_breps, its computed tolerance through topology.brep_p2), call SmBrep::IsManifoldSolid (topology.brep_p2) and stop at merge_p3's SmMerge::ManifoldBoolean stub (boolean.merge_p4) directly or through NonManifoldBoolean; they take the kernel mutably (the driver's mark locks). After #287 (merge with main through 7b57d8de): 287 cases, 151 pass, 0 fail, 136 deferred (query.brep 114, topology.brep_p3 21, primitive.primitive_creation_p1 1): the constructor builds #287's MergeEngine, so the 114 run merge_p4's ManifoldBoolean on it and stop at SmBrep::CalculateBoundingBox (query.brep)."
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
id = "boolean.merge_p2"
upstream = ["source/SMLib/src/SmMerge.cpp"]
rust_module = "boolean::merge::p2"
depends_on = ["boolean.merge_p1", "boolean.topology_intersector_p1", "boolean.topology_intersector_p2", "geom.extent3d", "geom.object", "geom.vector3d", "heal.stitch_p1", "topology.brep_p1", "topology.brep_p2", "topology.edge", "topology.edgeuse_p1", "topology.face_p2", "topology.face_p4", "topology.loopuse"]
soft_depends_on = ["curve.curve_p2", "geom.tol", "heal.stitch_p2", "query.edge", "query.face_p1", "surface.surface_p2", "topology.brep_p3", "topology.brep_p5", "topology.brep_p6", "topology.brep_p7", "topology.edgeuse_p3", "topology.face_p3", "topology.shell", "topology.vertex", "topology.vertexuse"]
est_lines = 1967
layer = 54
tests = ["prog_test:my_test_bbu", "SM_API_test:TestSmMaterialCensus", "SM_API_test:TestSmPiecewiseMerge", "SM_API_test:TestSmBooleanLists", "SM_API_test:TestKernelMergeBrepsInvalidInput", "SM_API_test:TestApiMergeBrepsInvalidOperation"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PARTIAL (PR #229): 45 cases (29 upstream-referenced fixtures + 16 generated), 30 bit-identical passes, zero failures, 15 deferred (topology.face_p3 4, topology.face_p4 4, topology.brep_p3 3, surface.sphere 1, topology.brep_p1 1, topology.brep_p9 1, topology.face_p2 1); no absolute floors; --seeds 1000: 631 pass / 398 deferred / 0 fail; --perturb SENSITIVE 631/631; --fuzz 5000 clean (differs=0 crashes=0 panics=0 timeouts=0). Compared: the SmMerge B-rep constructor (given/default tolerances, 20 deg angle, options, m_bManifoldBoolean / m_bIntersectionLoopClosed, EFF_ZERO boundary, NaN/inf), MergeEdge (null edge use, mated edges with tolerance matching; both operand snapshots), MakeFaceuse (mated-face fast path with infinite-region swap, SM_ERR orientation/region failures). After merging main with topology.brep_p2 (#149) its 4 stubs are wired (the constructor's GetMinEdgeBBoxSize, MergeAddedTopology's SmBrep::Notify PRE_EDIT / POST_EDIT and IsManifoldSolid as required MergeBrep methods, api_brep's IsManifoldSolid), so computed tolerances, new shell vertices (MakeShellVertexTopology via brep_p9) and MergeAddedTopology without added topology compare; the shared merge_p5 snapshot now numbers records by the shim's native walk (merge_p1 runner's Canon::of_native), so a created shell vertex compares by its place in the topology. Deferred: new wire edges (MakeWireEdge), MakeFace (wired; SmFace::SetTolerance, face_p3), and the other MergeAddedTopology/MergeAddedFace cases (SmFace::GetEdges, face_p4, or later calls; C++ still runs each). MergeEdge/MakeFaceuse work on concrete Breps with Relations; MergeAddedTopology/MergeAddedFace are generic over handles through MergeBrep (IntersectorBrepP2 plus required methods for the ported callees, Unported defaults for face_p4 / brep_p3); its stitch (stitch_p1/p2) and intersector (topology_intersector_p2) calls are wired. Relations gains face mates, relate_edges and relate_faces (in boolean/topology_intersector/p1.rs); MergeState gains manifold_boolean / intersection_loop_closed. Back-edges wired: boolean.merge_p5 (MergeEdge, both drivers), boolean.api_brep (SmMerge::SmMerge), heal.stitch_p1 (SmApiStitch(pBrep, pFace)), topology.brep_p7 (CopyFaces with the merge), boolean.merge_p3 (DependencyMerge and the runner's Pool construct; the runner's process_wires), boolean.merge_p4 (KernelManifoldIntersector::make_faceuse). SmFace::CalculateBoundingBox calls query.face_p1 (bTight = FALSE). MergeContext / merge_edge_with / make_faceuse_with serve callers whose two B-reps share one kernel. Known difference: partial outputs of failed stitch/intersector calls are not handed back (findings.md). Upstream issues: UB-176 confirmed (MergeAddedTopology route), UB-167 (constructor), WR-197. 5 fns; largest: SmMerge::MergeAddedTopology, SmMerge::MakeFaceuse, SmMerge::MergeEdge, SmMerge::SmMerge; cycle back-edges (call into later units; stub or co-port): blend.fillet_executive_p1(1); unit-SCC #22 (220 units); 105 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "boolean.merge_p3"
upstream = ["source/SMLib/src/SmMerge.cpp"]
rust_module = "boolean::merge::p3"
depends_on = ["boolean.merge_p2", "boolean.merge_p4", "boolean.merge_p5", "boolean.topology_intersector_p1", "geom.context", "geom.object", "topology.brep_p1", "topology.brep_p3"]
soft_depends_on = ["boolean.topology_intersector_p2", "geom.a_object", "geom.attribute", "geom.tol", "primitive.primitive_creation_p1", "surface.surface_p1", "surface.surface_p2", "topology.brep_p2", "topology.brep_p4", "topology.brep_p5", "topology.brep_p7", "topology.brep_p8", "topology.shell", "topology.topology_traverser"]
est_lines = 1152
layer = 57
tests = ["SM_API_test:TestSmMaterialCensus", "SM_API_test:TestSmPiecewiseMerge", "SM_API_test:TestSmBooleanLists", "SM_API_test:TestKernelMergeBrepsInvalidInput", "SM_API_test:TestApiMergeBrepsInvalidOperation", "SM_API_test:TestMergeBrepsOperation"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PARTIAL (PR #245): all 5 functions ported; PR #287 update: 387 cases (131 fixtures, 33 of them family-6 engine-probe cases of DependencyMerge::with_engine against a context-only native SmMerge, NER/controls only; + 256 generated), 215 matched / 0 failed / 172 deferred, with_values=159; perturb 215/215; fuzz 2000 PASS (668 ran, 1332 rejected, 0 differs/crashes/panics/timeouts); valgrind clean on 8 family-6 programs. Counts below are as of #245 except the deferral split. Opus-fix verification: 354 cases (98 fixtures + 256 generated), 182 matched / 0 failed / 172 deferred; with_values=126 (103 leaf identity/order/null + limited Rust B-rep digest cases, 23 empty forests), no_values=56 (54 native error statuses, 2 explicit UB-190 guard-only refusals; 180 operation comparisons + 2 guard self-checks). Rust digest compares face/edge/vertex counts and ordered vertex positions, not full graph/adjacency/curve/surface parity; earlier C++ payload echo coverage claim corrected. Zero geometric-success comparisons. Deferred: boolean.merge_p2 87 (40 of them NonManifoldBoolean cases: ManifoldBoolean is wired to boolean.merge_p4 through DependencyMerge's constructed engine, which SmMerge::SmMerge builds), boolean.topology_intersector_p2 48, topology.brep_p3 37. Perturb 182/182 detected; fuzz 2000 PASS (708 ran, 1292 rejected, 0 differs/crashes/panics/timeouts); Valgrind 50 programs/10 per family, baseline equal, 0 memory errors (leak checking disabled for retained unknown failed-call objects). All three boolean.api_brep back-edges wired. All family success results now serialized from Rust; PiecewiseMerge is generic over PiecewiseAccess with no kernel engine implementation yet (merge_p2/p4). Pool uses canonical intersector/attributes/marks, owner-tagged dependencies, and no silent subset stub. No surface-list or SSI skip-relation parity claimed. UB-188/WR-196 are source-only notes; UB-190 records piecewise imprinting lifetime defect, guarded only for multi-surface other operands. Empty B-rep constructor defaults are explicit topology.brep_p3 stubs (no Brep::new substitution), with full downstream tails. Opus fixes verified on main #130: fmt/own include rustfmt, workspace/CPP checks, clippy x2, 1402 kernel tests, 4 serializer/adapter tests, 2 merge_p3 FFI tests, wasm and native gates pass; 213-unit matrix passes (114 PASS/99 PARTIAL, zero failures, zero green units with deferred cases). Latest-main 154853c7 (includes 46ddc4ff) merged cleanly; post-merge fmt/own include rustfmt, workspace/CPP checks, clippy x2, 1410 kernel tests, 4 adapter tests, 2 merge_p3 FFI tests (+ 1 API test), wasm and default merge_p3/api_brep difftests pass; pulled reports unchanged. Full-matrix/perturb/fuzz/Valgrind evidence is from reviewed f0957fc5. Prior case outcomes unchanged; payload now reads actual Rust state. 5 fns; largest: SmMerge::PiecewiseMerge, SmMerge::BooleanLists, SmMerge::BooleanTrees, SmMerge::merge_breps; unit-SCC #22 (220 units); 102 upstream test entry points reach this unit Re-run in PR #149 (merge with main through 39ceb995, #283): 354 cases, 182 pass, 0 fail, 172 deferred (unchanged; no case reaches the wired SmBrep::Notify / SetTolerance sites, which follow merge_p2 / merge_p4 / topology_intersector_p2 / brep_p3 calls): the arena-only boolean_lists' component CopyFaces notifies through brep_p2's ArenaNotifyState (overseer ruling, reversing the module's 'defers at that boundary'), and the runner pool's SetTolerance / Notify adapters call topology.brep_p2. Re-run in PR #229 (boolean.merge_p2 wired, merge with main through 7b57d8de, after #287): 387 cases, 222 pass, 0 fail, 165 deferred (query.brep 80, boolean.topology_intersector_p2 48, topology.brep_p3 37). SmMerge::SmMerge now builds #287's engine: DependencyMerge::construct fills it through MergeEngine::from_merge (MergeState::with_breps: options, flags, the computed tolerances), and ManifoldBoolean before construct is InvalidInput. The runner's Pool constructs the same engine and runs ManifoldBoolean on it with its B-reps moved in and back; family 3 constructs first, as the shim's MergeAccess does. All 87 former boolean.merge_p2 deferrals now pass (7) or stop at SmBrep::CalculateBoundingBox (query.brep) inside merge_p4's ManifoldBoolean (80)."
+16
View File
@@ -0,0 +1,16 @@
id = "boolean.merge_p4"
upstream = ["source/SMLib/src/SmMerge.cpp"]
rust_module = "boolean::merge::p4"
depends_on = ["boolean.merge_p1", "boolean.merge_p2", "boolean.merge_p5", "boolean.topology_intersector_p1", "boolean.topology_intersector_p2", "geom.a_object", "geom.attribute", "geom.context", "geom.object", "intersect.point_class", "topology.brep_p1", "topology.brep_p2", "topology.edge", "topology.edgeuse_p1", "topology.face_p2", "topology.shell"]
soft_depends_on = ["curve.curve_p2", "geom.extent1d", "geom.tol", "geom.vector3d", "query.brep", "topology.brep_cache", "topology.brep_p3", "topology.brep_p4", "topology.brep_p5", "topology.brep_p7", "topology.brep_p9", "topology.face_p4", "topology.topology", "topology.topology_traverser", "topology.vertex"]
est_lines = 2590
layer = 56
tests = ["prog_test:my_test_bbu", "SM_API_test:TestSmMaterialCensus", "SM_API_test:TestSmPiecewiseMerge", "SM_API_test:TestSmBooleanLists", "SM_API_test:TestKernelMergeBrepsInvalidInput", "SM_API_test:TestApiMergeBrepsInvalidOperation"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PR #201 integration extends the production adapter with borrowed caller topology/curve identities and reserved region source-list handles while preserving the existing namespace-backed API. Actual notification records are restored with partial edits on Result exits and unwind; attributes and live contexts remain caller-owned. The automatic-tolerance constructor still belongs to boolean.merge_p2 (#229); borrowed cache access stops at the genuine query.brep bounding-box call and awaits live-kernel cache plumbing. Late consumption before cache/transform errors follows native ordering; operand slots, not Result alone, determine retained Rust ownership. Existing 311-case report is byte-identical, and 30/30 perturbations are detected; latent caller-key tests do not certify successful constructive Booleans. Historical port evidence follows: 1 fn, SmMerge::ManifoldBoolean; PR #243 partial. Full control-flow tail and scoped inverse transform; explicit two-context marks/editing and shared caller AttributeStore. No success path compared yet: all valid pairs stop at merge_p1 CalculateBoundingBox / query.brep. Null errors compare status plus post-state, including surviving graphs. KernelManifoldIntersector implements all 16 methods: shared MergeState<Relations>, canonical mates, caller notification records/attributes, all four merge_p1 stages and the merge_p5 paired-kernel wire API. Common lists share the generic intersector helper; source-region keys resolve real arenas. Focused adapter tests are separate from Boolean success coverage. CloseIntersectionLoop is a live units.json/unused callgraph gap (SmMerge.cpp:2958), co-ported into boolean.topology_intersector_p2 by PR #281, which also wires it here: KernelManifoldIntersector::close_intersection_loop calls TopologyIntersector::close_intersection_loop over the ArenaPair (the trait method now takes the caller AttributeStore and has no default). The callback retains PR #201 caller notification keys and namespace-aware cache configuration. PointClassify caller logic stays outside its stub. CopyFaces is wired to brep_p7; no incoming UNPORTED(boolean.merge_p4), shared Relations face storage/map-access extensions only, no dependency algorithm co-ports, no absolute floors. Difftest: 311 cases, 30 null-error state matches, 278 query.brep deferrals, 3 native constructor rejections, 0 failed; with_values=30 no_values=0; real Boolean successes=0 (status-as-data makes cases_both_errored=0). Fuzz 2000: rejected=203 malformed=866 ran=931 differs=0 crashes=0 panics=0 timeouts=0. Perturb 30/30; fmt/include rustfmt, checks x2, clippy x2, 1414 tests (eight adapter regressions), wasm pass after main 154853c7 (progress-only). Three requested adapter mutants each fail their intended assertion and were restored byte-identically; production unchanged from CLEAN 0ceda887. Its coordinate/error-state regressions and 405-case full-leak Valgrind baseline comparison pass (0 errors/lost bytes). Its full green gate passed: 214 units, failed=0; every reported partial matches the plan and no plan-green unit deferred. Re-run in PR #149 (merge with main through 39ceb995, #283): 311 cases, 30 pass, 0 fail, 278 deferred (query.brep 278; unchanged): IsSheet / IsOrientedSheet (in the other B-rep's kernel) and DeleteStaleCaches call topology.brep_p2; ArenaPair implements brep_arena and BrepGlue (GlueVertices through p5::glue_with_notifications)."
# Latest-main integration: merge_p2 (#229) adds the required make_faceuse adapter,
# using shared mates/records, primary kernel and other context; process_wires passes
# a TopologyCopy. Configuration now reuses the landed MergeState::with_breps;
# options/flags/relations are preserved, and the current p4 report is unchanged.
+12
View File
@@ -0,0 +1,12 @@
id = "boolean.merge_p5"
upstream = ["source/SMLib/src/SmMerge.cpp"]
rust_module = "boolean::merge::p5"
depends_on = ["boolean.merge_p1", "boolean.merge_p2", "boolean.topology_intersector_p1", "geom.object", "intersect.point_class", "topology.edge"]
soft_depends_on = ["curve.curve_p2", "geom.a_object", "geom.extent1d", "geom.tol", "geom.vector3d", "query.brep", "topology.brep_cache", "topology.brep_p1", "topology.brep_p4", "topology.edgeuse_p1", "topology.face_p2", "topology.shell", "topology.topology", "topology.topology_traverser", "topology.vertex"]
est_lines = 475
layer = 55
tests = ["prog_test:my_test_bbu", "SM_API_test:TestSmMaterialCensus", "SM_API_test:TestSmPiecewiseMerge", "SM_API_test:TestSmBooleanLists", "SM_API_test:TestKernelMergeBrepsInvalidInput", "SM_API_test:TestApiMergeBrepsInvalidOperation"]
status = "partial"
claimed_by = ""
claimed_at = ""
notes = "PARTIAL (PR #161): 140 cases, 108 bit-identical passes, zero failures, 32 deferred on query.brep (SmBrep::Point3DClassify); no absolute floors. ProcessWiresAndShellVertices ported with explicit operands, caller-owned marks and shared mutable mate maps; real SmMerge/Relate oracle on native-order raw graphs, all 11 operations, reversed/shared marks, mapped face edges, closed/sub-domain/tiny/huge wires, isolated vertices, and solid box fixtures. Deletion adapters remain Unported in topology.brep_p4; edge copies call boolean.merge_p2's MergeEdge (wired in PR #229); vertex copies delegate to boolean.merge_p1; no attached Brep cache yet. No incoming UNPORTED back-edges. Known UB-1 part-container inputs rejected before C++; guard regression included. Review regressions: unmated marked wires pass for the seven non-keep operations; null keep entries excluded only for Union/Intersection/Merge/PartialMerge; nonidentity mates preserve order; both runners reject duplicate Relate targets; generated operands, marks and mate permutations vary independently. Mutable bidirectional relation state is shared with the copy adapter. 1 fns; largest: SmMerge::ProcessWiresAndShellVertices; unit-SCC #22 (220 units); 105 upstream test entry points reach this unit PR #163 wires MergeVertex to boolean.merge_p1, shares mutable topology_intersector::p1::Relations with both operand directions, and passes the notification store/context. Newly created mates wait on full intersector Relate; classification remains the first deferred dependency in existing cases. TOUCHED by boolean.topology_intersector_p1 (PR #146): process_wires_and_shell_vertices takes other: &mut Brep (merge_vertex -> relate_vertices raises both vertex tolerances; upstream mutates its non-const m_pOther member); runner and tests pass it mutably. TOUCHED by boolean.merge_p4 (PR #243): process_wires_and_shell_vertices_with_kernels reuses the existing collection/copy phases with each operand mark context and live source-context notifications; the original API remains available. Reverified 140 cases: 108 passed, 0 failed, 32 query.brep deferrals."
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
id = "boolean.topology_intersector_p3"
upstream = ["source/SMLib/src/SmTopologyIntersector.cpp"]
rust_module = "boolean::topology_intersector::p3"
depends_on = ["boolean.topology_intersector_p1", "boolean.topology_intersector_p2", "curve.curve_p2", "geom.extent3d", "geom.tol", "intersect.curve_class_p1", "intersect.point_class", "topology.edge", "topology.edgeuse_p1", "topology.face_p2"]
soft_depends_on = ["curve.curve_p4", "curve.curve_p6", "geom.extent1d", "geom.object", "geom.vector3d", "intersect.curve_class_p3", "intersect.curve_class_p4", "intersect.curve_class_p5", "intersect.curve_class_p6", "intersect.curve_class_p7", "intersect.surface_drop_lib_p1", "nurbs.b_spline_curve_p1", "query.face_p1", "query.face_p2", "surface.surface_p1", "surface.surface_p2", "topology.brep_p4", "topology.face_p4", "topology.loopuse"]
est_lines = 1849
layer = 52
tests = ["prog_test:my_test_bbu", "SM_API_test:TestSmSurfaceSurfaceFillet", "SM_API_test:TestSmMaterialCensus", "SM_API_test:TestSmPiecewiseMerge", "SM_API_test:TestSmBooleanLists", "SM_API_test:TestKernelMergeBrepsInvalidInput"]
status = "todo"
claimed_by = ""
claimed_at = ""
notes = "3 fns; largest: SmTopologyIntersector::MergeCurveClasses, SmTopologyIntersector::MergeCoincidentSurfaces, SmTopologyIntersector::MergeCurveOnSurfaces; unit-SCC #22 (220 units); 110 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.composite_curve_p1"
upstream = ["source/SMLib/inc/SmCompositeCurve.h", "source/SMLib/src/SmCompositeCurve.cpp"]
rust_module = "curve::composite_curve::p1"
depends_on = ["curve.curve_p1", "curve.curve_p2", "curve.curve_p3", "curve.curve_p6", "curve.curve_p8", "geom.a_object", "geom.attribute", "geom.axis2_placement", "geom.extent1d", "geom.extent3d", "geom.geom_utility_p1", "geom.object", "geom.polar_box", "geom.pseudo_box", "geom.solution_array", "geom.tol", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_curve_p1"]
soft_depends_on = ["geom.extent2d", "nurbs.b_spline_curve_p2", "nurbs.b_spline_curve_p3"]
est_lines = 1700
layer = 21
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.composite_curve_p1-a1"
claimed_at = "2026-10-13T06:02:42Z"
notes = "GREEN (promoted by curve.curve_p5: 3093 cases, 0 deferred after its stubs were wired); PARTIAL: difftest 3093 cases (93 fixture: my_test_cci_self composites/offset rebuild, the disabled BuildCompositesFromCurves square, edge cases + 3000 generated), 2781 pass bit-identical (max_rel_err 0), 312 deferred (curve.curve_p5 312: AssertValid of the joined ApproximateCurve result reaches LocalPropertyAnalysis; corner chamfer / classify solves); 30k-seed run clean; --perturb SENSITIVE; SmCompositeCurve joins Curve as CurveKind::Composite; sm_FlushCrv co-ported (call graph lists it unused); no UNPORTED(curve.composite_curve_p1) stubs to wire; upstream OOB reads (GetKnots, ApproximateCurve NULL join, chamfer sSolutions[0]) in findings.md. 46 fns; largest: SmCompositeCurve::ComputeProjectedLoopOrientation, sm_CreateCorner, SmCompositeCurve::BuildCompositesFromCurves, sm_CurveClassify; cycle back-edges (call into later units; stub or co-port): curve.curve_p5(4); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.composite_curve_p2"
upstream = ["source/SMLib/inc/SmCompositeCurve.h", "source/SMLib/src/SmCompositeCurve.cpp"]
rust_module = "curve::composite_curve::p2"
depends_on = ["curve.composite_curve_p1", "curve.curve_p1", "curve.curve_p2", "curve.curve_p4", "curve.curve_p7", "curve.curve_p8", "curve.offset_curve", "geom.a_object", "geom.extent1d", "geom.object", "geom.solution_array", "geom.vector3d", "topology.database_io"]
soft_depends_on = ["geom.geom_utility_p1", "geom.tol", "nurbs.b_spline_curve_p1", "nurbs.b_spline_curve_p2"]
est_lines = 1345
layer = 22
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-curve.composite_curve_p2-a1"
claimed_at = "2026-10-13T06:41:55Z"
notes = "GREEN (promoted by curve.curve_p5: 661 cases, 0 deferred after its stubs were wired); difftest 661 cases (361 pass, 300 deferred on curve.curve_p5); 10 fns; largest: SmCompositeCurve::CreateOffsetsOfManyCurves, SmCompositeCurve::IntersectAndTrimOffsets, sm_CheckBowTies, SmCompositeCurveSegment::ReadFromDB; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.conic"
upstream = ["source/SMLib/inc/SmConic.h", "source/SMLib/src/SmConic.cpp"]
rust_module = "curve::conic"
depends_on = ["curve.curve_p2", "geom.extent1d", "geom.solution_array", "geom.vector2d", "geom.vector3d", "topology.database_io"]
soft_depends_on = ["geom.polynomial", "geom.tol"]
est_lines = 859
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.conic-a1"
claimed_at = "2026-10-13T01:00:34Z"
notes = "difftest green: 3240 cases (240 fixture incl. all 15 smCurveTest.cpp IntersectConic asserts + 3000 generated), 0 deferred; wired SmCurve::ReadFromDB(SmConic_TYPE) and CurveKind::Conic into curve.curve_p2 (still partial: curve_p5, curve.line). 19 fns; largest: SmConic::Evaluate, SmConic::InvertPointOnConic, SmConic::IntersectConic, SmConic::IntersectImplicitConic; cycle back-edges (call into later units; stub or co-port): curve.curve_p5(2); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.crv_in_volume"
upstream = ["source/SMLib/inc/SmCrvInVolume.h", "source/SMLib/src/SmCrvInVolume.cpp"]
rust_module = "curve::crv_in_volume"
depends_on = ["curve.curve_p2", "geom.extent1d", "geom.object", "geom.tol", "geom.vector3d", "topology.database_io"]
soft_depends_on = ["geom.axis2_placement", "geom.context", "geom.extent3d", "geom.vector2d"]
est_lines = 949
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "partial"
claimed_by = "swarm-curve.crv_in_volume-a1"
claimed_at = "2026-10-13T01:00:34Z"
notes = "difftest 2030 cases (1855 pass, 175 deferred: intersect.curve_class_p4 175; surface.volume_p1 and surface.volume_p2 wired); 27 fns; largest: SmCrvInVolume::GetKnots, SmCrvInVolume::Evaluate, SmCrvInVolume::ReadFromDB, SmCrvInVolume::GenerateMults; cycle back-edges (call into later units; stub or co-port): surface.volume_p1(14), curve.curve_p5(3), intersect.curve_class_p1(2), surface.volume_p2(2), intersect.curve_class_p4(1), intersect.curve_class_p8(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit Re-run (PR #137, constructor stub retagged UNPORTED(intersect.curve_class_p2): SmCurveClassification::ReSet): 2030 cases, 1855 pass, 175 deferred (intersect.curve_class_p2 175), 0 failed, --perturb SENSITIVE 1855/1855."
+12
View File
@@ -0,0 +1,12 @@
id = "curve.crv_on_surf"
upstream = ["source/SMLib/inc/SmCrvOnSurf.h", "source/SMLib/src/SmCrvOnSurf.cpp"]
rust_module = "curve::crv_on_surf"
depends_on = ["curve.curve_p2", "curve.curve_p3", "curve.curve_p6", "geom.extent1d", "geom.extent2d", "geom.object", "geom.solution_array", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_curve_p1", "topology.database_io"]
soft_depends_on = ["curve.line", "curve.tangent_field", "geom.axis2_placement", "geom.context", "geom.tol", "nurbs.b_spline_curve_p2"]
est_lines = 1728
layer = 19
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "partial"
claimed_by = "swarm-curve.crv_on_surf-a1"
claimed_at = "2026-10-13T04:49:20Z"
notes = "PARTIAL: difftest 2094 cases (94 fixture: smTopoTest my_check_loop_uv_gap SmBSplineCurve::CreateLineSegment UV edges on the bulge patch with owner 1 (eval, approx, cached breaks, drops, copies, edits, self gap), smMergeTest plane SM_SP_UMAX boundary via the UV-line constructor for owner flags 0-3, smTopoTest face trim curves on Surface.sms / DropCurveSurface.sms + 2000 generated op programs incl. ReadFromDB records from upstream WriteToDB), 1602 pass bit-identical (max_rel_err 0), 492 deferred (intersect.curve_class_p4 294: SmCurveClassification of uncached breaks; surface.surface_p7 148: SmSurface::EvaluateNormal; surface.surface_p1 50: Evaluate2ndDerivatives); --perturb SENSITIVE; CurveKind::CrvOnSurf (UV curve + BSplineSurface by value); ApproximateCurve / DropPoint / CalculateBoundingBox dispatch to the override (Curve::approximate_curve_base, drop_point_base); smsurf_LiftSecond/ThirdDerivative co-ported (surface.surface_p2); wired SmCurve::ReadFromDB(SmCrvOnSurf_TYPE) (curve.curve_p2) and SmTangentField base read (curve.tangent_field 266 -> 264 deferred); 3 UNPORTED(curve.crv_on_surf) stubs stay (global_solver node owner, SmTangentField::ApproximateCurve, tangent field as curve kind: see findings); DeformToEndPointTargets branch retagged surface.surface_p5. 38 fns; largest: SmCrvOnSurf::SurfaceCurveMaxDistanceBetween, SmCrvOnSurf::Evaluate, SmCrvOnSurf::GetKnots, SmCrvOnSurf::SetAll; cycle back-edges (call into later units; stub or co-port): surface.surface_p2(14), surface.surface_p1(4), curve.curve_p5(3), intersect.curve_class_p1(2), surface.surface_p7(2), curve.curve_p1(1), intersect.curve_class_p4(1), intersect.curve_class_p8(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; PR #150 integration handoff: generic-Surface SmCrvOnSurf construction remains unported; CurveKind::CrvOnSurf stores only BSplineSurface. The p5 generic-surface deferral names this missing type/dispatch extension, not an unported existing method. This partial unit status does not certify that extension. Re-run (PR #137, constructor stub retagged UNPORTED(intersect.curve_class_p2): SmCurveClassification::ReSet): 2094 cases, 1787 pass, 307 deferred (intersect.curve_class_p2 307), 0 failed, --perturb SENSITIVE 1787/1787."
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_cache"
upstream = ["source/SMLib/inc/SmCurveCache.h", "source/SMLib/src/SmCurveCache.cpp"]
rust_module = "curve::curve_cache"
depends_on = ["curve.curve_p2", "geom.extent1d", "geom.extent3d", "geom.object", "geom.tol", "geom.vector3d", "nlib.math", "nurbs.b_spline_curve_p1", "nurbs.nurbs_crv"]
soft_depends_on = ["geom.geom_utility_p1", "geom.local_solve1d", "geom.pseudo_box", "geom.tree", "nlib.knots", "nurbs.b_spline_curve_p2"]
est_lines = 1474
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.curve_cache-a1"
claimed_at = "2026-10-13T01:00:33Z"
notes = "GREEN (promoted by curve.curve_p5: 638 cases, 0 deferred after its stubs were wired); PARTIAL: difftest 638 cases (38 fixture: lines, cubics, C0 quadratic, closed, degenerate, 2D, rational arc and Hermite curves through Tessellate with every option, sub/beyond/disjoint/reversed intervals, GetAnalyticCurve, type queries + 600 generated), 635 pass bit-identical (max_rel_err 0), 3 deferred (curve.curve_p5 2: SmCurve::IsArc, curve.line 1: SmLine in GetAnalyticCurve); co-ported SmFindCurveDistanceExtremaEFO::Evaluate (curve.curve_p4) and SmCurve::IsLine (curve.curve_p5, curve::curve::p5::is_line_base); wired curve_p2 span stubs, SmTree::GetOwnerObject and the IsLine stub of nurbs.b_spline_curve_p2; 24 fns; largest: SmCurveCache::Tessellate, sm_ComputeConstants, SmCurveCache::BuildTree, sm_ComputeParentData; cycle back-edges (call into later units; stub or co-port): curve.curve_p4(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; after curve.line: 638 cases, 636 pass, 2 deferred (curve.curve_p5 2)"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_p1"
upstream = ["source/SMLib/src/SmCurve.cpp"]
rust_module = "curve::curve::p1"
depends_on = ["curve.curve_cache", "curve.curve_p2", "curve.curve_p3", "curve.curve_p4", "geom.a_object", "geom.extent1d", "geom.global_solver", "geom.object", "geom.solution_array", "geom.tol", "geom.tree", "geom.vector3d", "nurbs.b_spline_curve_p1"]
soft_depends_on = ["curve.hermite_curve", "geom.extent3d", "geom.geom_utility_p1", "geom.pseudo_box"]
est_lines = 2097
layer = 18
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "partial"
claimed_by = "swarm-curve.curve_p1-a1"
claimed_at = "2026-10-13T03:57:21Z"
notes = "PARTIAL: difftest 3083 cases (83 fixture re-expressing the smCurveTest my_test_point_extrema / my_test_drop_point line and circle solves, the SmApiCreateRectangle / SmApiCreateRegularPolygon edges through Tessellate / TessellateByBisection / GlobalPointSolve / ApproximateCurve and edge cases + 3000 generated), 2493 pass bit-identical (max_rel_err 0), 590 deferred (curve.curve_p5 590: LocalPropertyAnalysis 310, SmFindCCNormalENFO::Evaluate 163, SmCCIntersectENFO::Evaluate 73, IsArc 44); --perturb SENSITIVE; 12,083-case run clean; co-ported SmCurve::IsLine dispatch and CacheMakeOrValidate cache build (curve.curve_p5); SolutionObject::natural_interval added for IdenticalSolutions; wired UNPORTED(curve.curve_p1) in nurbs.b_spline_curve_p1 (TessellateByBisection: unit now green), nurbs.b_spline_curve_p2 (ApproximateCurve), curve.hyperbola (GlobalPointSolveSTEP: 70 -> 0 curve_p1 deferred), curve.ellipse_p2 (line GlobalPointSolve; the ellipse one now waits on curve.ellipse_p1); curve.curve_p4 / curve.ellipse_p2 curve_p1 deferrals now pass or wait on curve.ellipse_p1 (findings.md). 8 fns; largest: SmCPGlobalSolver::LocalSolve, SmCurve::TessellateByBisection, SmCurve::ClassifyIntersectingRangeSolution, SmCurve::GlobalPointSolve; cycle back-edges (call into later units; stub or co-port): curve.curve_p5(2); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit UPDATE after topology.brep_p1 (PR #145): re-run 3083 cases, 3057 pass, 0 fail, 26 deferred (geom.solution_array 26: its SmTol::GetZoneTol3d(SmObject*) stub, formerly tagged topology.brep_p1, now self-tagged: the tolerance arms are ported but need a &Brep the array does not hold)."
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_p2"
upstream = ["source/SMLib/inc/SmCurve.h", "source/SMLib/src/SmCurve.cpp"]
rust_module = "curve::curve::p2"
depends_on = ["curve.hermite_curve", "geom.a_object", "geom.extent1d", "geom.extent3d", "geom.geom_utility_p1", "geom.global_solver", "geom.object", "geom.solution_array", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_curve_p1"]
soft_depends_on = ["geom.axis2_placement", "geom.extent2d", "geom.geom_utility_p2", "geom.pseudo_box", "geom.tol", "geom.tree", "nurbs.b_spline_curve_p2"]
est_lines = 2302
layer = 13
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.curve_p2-a1"
claimed_at = "2026-10-13T00:14:00Z"
notes = "GREEN (promoted by curve.curve_p5: 3021 cases, 0 deferred after its stubs were wired); 79 fns; largest: SmCurvePropertyGS::BranchMayContainAnswers, SmCurve::SurfaceMaxDistanceBetween, SmCurve::EvaluateContinuity, sm_FlushCrv; cycle back-edges (call into later units; stub or co-port): curve.curve_cache(4), surface.surface_p2(3), curve.ellipse_p1(2), curve.composite_curve_p2(1), curve.conic(1), curve.crv_in_volume(1), curve.crv_on_surf(1), curve.hyperbola(1), curve.iso_curve(1), curve.line(1), curve.offset_curve(1), curve.parabola(1), curve.projected_curve(1), curve.tangent_field(1), surface.surface_p5(1), surface.surface_p7(1), topology.topology(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; PARTIAL: difftest 3018 cases (18 fixture re-expressing the prog_test/SM_API_test line and circle curves, ApproximateLength(ivl, 20), circle seam continuity, Hermite base defaults, ReadFromDB dispatch + 3000 generated over B-spline, Hermite and arc curves, the static helpers via verbatim shim copies and the solver box tests), 3012 pass bit-identical (max_rel_err 0), 6 deferred (curve.curve_p5 5: SmCurve::IsArc, curve.line 1: SmLine in CreateAnalyticCurve); --perturb SENSITIVE; introduces curve::curve::Curve (CurveKind enum + owner) and CurveEvaluate; wired UNPORTED(curve.curve_p2) in curve.hermite_curve (93 -> 0, green), nurbs.b_spline_curve_n_lib (57 -> 0, green), nurbs.b_spline_curve_p1 (60 -> 4), nurbs.b_spline_curve_p2 (317 -> 150), nurbs.b_spline_curve_p3 (391 -> 359); geom.tools / geom.solution_array / geom.tol stubs stay (opaque handles, see findings.md); after curve.line (SmLine::ReadFromDB wired): 3021 cases, 3016 pass, 5 deferred (curve.curve_p5 5) Review PR #106 recertification: 3021 cases, 3021 pass, 0 deferred, 0 failed, max_rel_err=0.0; deferred: none."
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_p3"
upstream = ["source/SMLib/src/SmCurve.cpp"]
rust_module = "curve::curve::p3"
depends_on = ["curve.curve_p2", "curve.curve_p4", "geom.extent1d", "geom.global_solver", "geom.local_solve1d", "geom.local_solve_nd", "geom.matrix", "geom.object", "geom.solution_array", "geom.vector3d", "nurbs.b_spline_curve_p1"]
soft_depends_on = ["curve.curve_cache", "curve.projected_curve", "geom.geom_utility_p1", "geom.pseudo_box", "geom.tol", "geom.tree", "nurbs.b_spline_curve_p2"]
est_lines = 2072
layer = 17
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-curve.curve_p3-a1"
claimed_at = "2026-10-13T03:19:00Z"
notes = "GREEN (PR #119): difftest 3076 cases (76 fixtures plus 3000 generated), all pass bit-identically, zero deferred. Wiring mass.integrator resolves the remaining 85 FindParameterAtArcLength / curved Length cases. Co-ported SmCurve::IsLinear (curve.curve_p5) and SmCCTangentIntENFO::Evaluate; curve.curve_p5 calls are wired. 9 fns; largest: SmCurvePropertyGS::LocalSolve, SmCurve::LocalPointSolve, SmCurve::LocalCurveSolve, SmCurve::LocalCurveIntersect; cycle back-edges (call into later units; stub or co-port): curve.curve_p5(7); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_p4"
upstream = ["source/SMLib/src/SmCurve.cpp"]
rust_module = "curve::curve::p4"
depends_on = ["curve.curve_p2", "geom.a_object", "geom.assert_array", "geom.extent1d", "geom.matrix", "geom.object", "geom.solution_array", "geom.tol", "geom.vector3d"]
soft_depends_on = ["curve.ellipse_p2", "curve.line", "geom.geom_utility_p1", "geom.polar_box", "nurbs.b_spline_surface_p1"]
est_lines = 2377
layer = 16
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-curve.curve_p4-a1"
claimed_at = "2026-10-13T02:46:08Z"
notes = "GREEN: difftest 3259 cases, 3259 passed, 0 deferred: the 13 cases deferred on SmCurve::GetNaturalInterval (solution handles of the curve's global solves that reported no natural interval: HasPlaneCrossings' plane intersection, TrimGap's curve/curve intersection) pass since the handles carry the curves' natural intervals and the plane's UV domain; PARTIAL: difftest 3259 cases (259 fixture: TestSmCreateRectangle / far 1e-9 rectangle and TestSmCreateRegularPolygon / far 1.5e-6 pentagon edges through FixChainCurvesList, IsClosed, IsDegenerate, polar box, snap; my_test_reversed_line_join line pairs (chain, AnalyticCurveIntersect, AssertValid); my_test_drop_point unit circle through every SmCurvePropertyEFO property, SmCPDistAtENFO, sm_GetProjDist; tangent/extrema equations; filter cases + 3000 generated), 3210 pass bit-identical (max_rel_err 0), 49 deferred (surface.surface_p8 49: SmSurface::GlobalCurveIntersect in HasPlaneCrossings; curve.ellipse_p1 wiring cleared the 25 ellipse intersections); 30,259-case run clean; --perturb SENSITIVE; FixChainCurvesList duplicate deletion is a use after free upstream (not difftested, findings.md); SmFindCurveDistanceExtremaEFO::Evaluate co-ported earlier by curve.curve_cache; wired UNPORTED(curve.curve_p4) in nurbs.b_spline_curve_p2 (IsDegenerate, IsClosed: 94 -> 10 deferred) and nurbs.b_spline_curve_p3 (SmCurve::AssertValid: 200 -> 172 deferred); 20 fns; largest: SmCurvePropertyEFO::Evaluate, SmCCTangentIntENFO::StaticEvaluate, sm_FilterSolution, SmCurve::FixChainCurvesList; cycle back-edges (call into later units; stub or co-port): surface.surface_p8(1); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_p5"
upstream = ["source/SMLib/inc/SmCurve.h", "source/SMLib/src/SmCurve.cpp"]
rust_module = "curve::curve::p5"
depends_on = ["curve.curve_cache", "curve.curve_p2", "curve.curve_p4", "geom.a_object", "geom.extent1d", "geom.extent2d", "geom.geom_utility_p1", "geom.local_solve1d", "geom.matrix", "geom.object", "geom.tol", "geom.vector3d", "nurbs.b_spline_curve_p1"]
soft_depends_on = ["curve.composite_curve_p1", "curve.conic", "curve.crv_in_volume", "curve.crv_on_surf", "curve.ellipse_p2", "curve.hermite_curve", "curve.hyperbola", "curve.iso_curve", "curve.line", "curve.offset_curve", "curve.parabola", "curve.projected_curve", "curve.tangent_field", "geom.axis2_placement", "geom.solution_array", "geom.vector2d", "nurbs.b_spline_curve_p3"]
est_lines = 2299
layer = 22
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-curve.curve_p5-a1"
claimed_at = "2026-10-13T06:41:49Z"
notes = "GREEN: difftest 3097 cases, 3097 passed, 0 deferred: the 2 cases deferred on SmCurve::GetNaturalInterval (CrvsCleanup -> TrimGap's GlobalCurveIntersect handles) pass since the handles carry the curves' natural intervals; PARTIAL: difftest 3097 cases (97 upstream-derived + edge-case fixtures: TestSmCreateRectangle/RegularPolygon edges, my_test_reversed_line_join lines, closest-point inversions, Newton Jacobians; plus 3000 generated over 16 ops), 3095 pass bit-identical, 2 deferred (curve.curve_p2 2: GetNaturalInterval through a solution handle); mass.integrator wired in PR #119: all 28 curved Length cases now pass; 20000-seed run clean; --perturb detects all; wired all 13 UNPORTED(curve.curve_p5) stubs, promoting 12 units to green; upstream CrvsCleanup/TrimGap crash next to a closed curve not generated (see findings); 19 fns; largest: SmFindCCNormalENFO::Evaluate, SmCCIntersectENFO::Evaluate, SmCurve::IsArc, SmCurve::LocalPropertyAnalysis; cycle back-edges (call into later units; stub or co-port): curve.ellipse_p1(2), mass.integrator(2); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_p6"
upstream = ["source/SMLib/src/SmCurve.cpp"]
rust_module = "curve::curve::p6"
depends_on = ["curve.curve_p2", "curve.curve_p3", "curve.curve_p4", "geom.extent1d", "geom.extent3d", "geom.global_solver", "geom.object", "geom.polar_box", "geom.pseudo_box", "geom.solution_array", "geom.tol", "geom.vector2d", "geom.vector3d", "nurbs.b_spline_curve_p1"]
soft_depends_on = ["curve.line", "geom.extent2d", "nurbs.b_spline_curve_n_lib"]
est_lines = 2376
layer = 18
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-curve.curve_p6-a1"
claimed_at = "2026-10-13T03:57:16Z"
notes = "GREEN (promoted by curve.curve_p5: 3136 cases, 0 deferred after its stubs were wired); PARTIAL: difftest 3136 cases (136 fixture: SM_API_test rectangle/hexagon edges (boxes, planarity, simple/global coincidence, gaps, drops), my_test_reversed_line_join line pairs x16 (simple coincidence, gaps, drops, GlobalPointSolveSTEP), smCurveTest DeformToEndPointTargets B-spline and line steps, my_test_drop_point-style drops, circle boxes, edge cases + 3000 generated), 3048 pass bit-identical (max_rel_err 0), 88 deferred (curve.curve_p5 88: SmFindCCNormalENFO::Evaluate in precise gaps, sm_IsPointSolutionAcrossClosedSeamBoundary in split recombination, LocalPropertyAnalysis/IsArc inside global solves); 30k-seed run clean; --perturb SENSITIVE; wired curve.curve_p1 (GlobalPointSolve, Tessellate, ApproximateCurve) at merge; ellipse GlobalCoincidenceChecker stub retagged UNPORTED(curve.ellipse_p1) (SmEllipse not a CurveKind; curve.ellipse_p2 stays partial, 1 case moved to ellipse_p1); geom.tools stubs kept (opaque handles, findings.md); GlobalCoincidenceChecker recursion bounded at 200 splits. 8 fns; largest: SmCurve::GlobalCoincidenceChecker, SmCurve::SimpleCoincidenceChecker, SmCurve::CurveMaxDistanceBetween, SmCurve::CalculateBoundingBox; cycle back-edges (call into later units; stub or co-port): curve.curve_p1(5), curve.crv_on_surf(3), curve.curve_p5(2), surface.surface_p1(1), surface.surface_p2(1), surface.surface_p5(1); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; GAP (PR #155): DeformToEndPointTargets dropped the pOptSurfCrvOnSurf / pOptCrvOrientation branch (it needs SmSurface::DropPoint); callers defer a curve on surface with a gap target as UNPORTED(curve.curve_p6) (topology.brep_p7 MakeFaceWithCurves)"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_p7"
upstream = ["source/SMLib/src/SmCurve.cpp"]
rust_module = "curve::curve::p7"
depends_on = ["curve.curve_cache", "curve.curve_p2", "curve.curve_p3", "curve.curve_p4", "curve.curve_p6", "geom.a_object", "geom.extent1d", "geom.extent3d", "geom.geom_utility_p1", "geom.global_solver", "geom.object", "geom.pseudo_box", "geom.solution_array", "geom.vector3d"]
soft_depends_on = ["curve.projected_curve", "geom.axis2_placement", "geom.tol", "geom.tree"]
est_lines = 1666
layer = 19
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-curve.curve_p7-a1"
claimed_at = "2026-10-13T04:46:38Z"
notes = "GREEN (promoted by curve.curve_p5: 3027 cases, 0 deferred after its stubs were wired); PARTIAL: difftest 3027 cases (27 fixture: SM_API_test TestSmCreateRectangle / TestSmCreateRegularPolygon edge pairs, my_test_reversed_line_join segments, arc plane intersection / classification with comb, edge cases: coincident, tolerance-limit gaps, degenerate Hermite, self-intersecting loop, projected / perspective, sub-interval + 3000 generated: whole SolveIt and single leaf-pair LocalSolve for intersect, intersection test and the three projected intersections, GlobalPropertyAnalysis over all 29 properties with/without comb), 1716 pass bit-identical (max_rel_err 0), 1311 deferred (curve.curve_p5 1311: LocalCurveIntersect -> SmCCIntersectENFO::Evaluate, LocalPropertyAnalysis); --perturb SENSITIVE; co-ported sm_FindAdditionalCcTangentGuess (curve.curve_p5); wired UNPORTED(curve.curve_p7) in curve.curve_p2 (CciGlobalSolver::local_solve, solver now carries curves + kernel) and nurbs.b_spline_curve_p3 (AssertValid GlobalPropertyAnalysis: its 116 deferred moved to curve.curve_p5); no unit promoted. 2 fns; largest: SmCCIGlobalSolver::LocalSolve, SmCurve::GlobalPropertyAnalysis; cycle back-edges (call into later units; stub or co-port): curve.curve_p5(2); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_p8"
upstream = ["source/SMLib/src/SmCurve.cpp"]
rust_module = "curve::curve::p8"
depends_on = ["curve.curve_p1", "curve.curve_p2", "curve.curve_p4", "curve.curve_p6", "curve.curve_p7", "geom.a_object", "geom.extent1d", "geom.extent3d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector3d"]
soft_depends_on = ["curve.curve_cache", "geom.global_solver", "geom.tree"]
est_lines = 1670
layer = 20
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-curve.curve_p8-a1"
claimed_at = "2026-10-13T05:23:28Z"
notes = "GREEN (promoted by curve.curve_p5: 3058 cases, 0 deferred after its stubs were wired); PARTIAL: difftest 3058 cases (58 fixture: SM_API_test TestSmCreateRectangle / TestSmCreateRegularPolygon edge pairs and my_test_reversed_line_join line pairs (with and without the coincidence check), edge cases: line/line and B-spline line crossings, overlaps, self intersections, polyline vertex touch, parabola tangency, parallel gaps at the tolerance limit, coincident cubics, degenerate Hermite, looping self intersection, disjoint boxes + 3000 generated: crossings, tangent lines, coincident partners, self intersections, closed and looping curves), 1968 pass bit-identical (max_rel_err 0), 1090 deferred (curve.curve_p5 1090: SmCCIntersectENFO::Evaluate, sm_IsPointSolutionAcrossClosedSeamBoundary, SmCurve::IsArc); --perturb SENSITIVE; wired UNPORTED(curve.curve_p8) in nurbs.b_spline_curve_p3 (TrimGap); 1 fns; largest: SmCurve::GlobalCurveIntersect; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.curve_p9"
upstream = ["source/SMLib/src/SmCurve.cpp"]
rust_module = "curve::curve::p9"
depends_on = ["curve.curve_cache", "curve.curve_p2", "curve.curve_p3", "curve.curve_p4", "curve.curve_p5", "curve.curve_p6", "curve.curve_p7", "curve.curve_p8", "geom.a_object", "geom.extent1d", "geom.extent3d", "geom.geom_utility_p1", "geom.geom_utility_p2", "geom.global_solver", "geom.object", "geom.pseudo_box", "geom.solution_array", "geom.vector3d"]
soft_depends_on = ["curve.line", "geom.tol", "geom.tree", "nurbs.b_spline_curve_p1"]
est_lines = 1783
layer = 23
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = ""
claimed_at = ""
notes = "GREEN: difftest 3093 cases (93 fixture + 3000 generated), 0 deferred, max_rel_err 0 (bit-identical); 30,093-case run clean. Shim covers SmEllipse (kind 3) as well as B-spline, Hermite and line. Wired SmCCGlobalSolver::LocalSolve stub in curve.curve_p2 (CcGlobalSolver now carries its curves and kernel). 8 fns; largest: SmCCGlobalSolver::LocalSolve, SmCurve::GlobalCurveSolve, sm_SolveMinSignedAngle, SmCurve::CalculateTightBoundingBox; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.ellipse_p1"
upstream = ["source/SMLib/inc/SmCircle.h", "source/SMLib/src/SmCircle.cpp", "source/SMLib/src/SmEllipse.cpp"]
rust_module = "curve::ellipse::p1"
depends_on = ["curve.curve_p1", "curve.curve_p2", "curve.curve_p4", "curve.ellipse_p2", "geom.assert_array", "geom.axis2_placement", "geom.extent1d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector3d", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_curve_p1", "nurbs.b_spline_curve_p2", "nurbs.b_spline_curve_p3", "topology.database_io"]
soft_depends_on = ["geom.geom_utility_p1", "geom.polynomial", "nlib.crv_basic", "nlib.crv_common", "nurbs.b_spline_surface_p1", "nurbs.nurbs_crv"]
est_lines = 1930
layer = 19
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.ellipse_p1-a1"
claimed_at = "2026-10-13T04:34:25Z"
notes = "GREEN (promoted by curve.curve_p5: 2028 cases, 0 deferred after its stubs were wired); PARTIAL: difftest 2028 cases (28 fixture: my_test_analytic_curves circle/ellipse (CreateCanonical, AdjustSTEPInterval, GlobalPointSolveSTEP, ReverseParameterization), smSurfaceTest cylinder circle inside-out, smTopoTest CreateCanonical + AdjustSTEPInterval / EditParameterization circles, smCurveTest circle copy constructor, edge cases: non-positive radius, collinear / 2D / closed 3-point circles, joins (overlap, flipped normal, non-ellipse), circle offsets, skewed ConvertTo2D, 2D construction, Trim modes; + 2000 generated programs over constructors, CreateCanonical and ReadFromDB records), 1896 pass bit-identical (max_rel_err 0), 132 deferred (curve.curve_p5 132: LocalPointSolve / LocalPropertyAnalysis / SmCurve::IsArc); --perturb SENSITIVE; SmEllipse and SmCircle join Curve as CurveKind::Ellipse (Curve methods whose ellipse override rebuilds the polar converter take &Kernel); wired UNPORTED(curve.ellipse_p1) in curve.curve_p2 (ReadFromDB), curve.ellipse_p2 (GlobalPointSolve, GlobalCoincidenceChecker), nurbs.b_spline_curve_p2 (CreateAnalyticCurve SmCircle), nurbs.b_spline_surface_p2 (sweep circle). 39 fns; largest: SmEllipse::MakeNurb, SmPolarConversion::ConvertToPolarParameter, SmEllipse::JoinWith, SmEllipse::Trim; cycle back-edges (call into later units; stub or co-port): surface.surf_of_extrusion_p1(1), surface.surf_of_revolution_p1(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.ellipse_p2"
upstream = ["source/SMLib/inc/SmEllipse.h", "source/SMLib/src/SmEllipse.cpp"]
rust_module = "curve::ellipse::p2"
depends_on = ["curve.curve_p2", "curve.line", "geom.axis2_placement", "geom.extent1d", "geom.geom_utility_p1", "geom.object", "geom.solution_array", "geom.tol", "geom.vector3d", "nurbs.b_spline_curve_p1"]
soft_depends_on = ["geom.geom_utility_p2"]
est_lines = 1916
layer = 15
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.ellipse_p2-a1"
claimed_at = "2026-10-13T02:16:47Z"
notes = "GREEN (promoted by curve.curve_p5: 2102 cases, 0 deferred after its stubs were wired); PARTIAL: difftest 2102 cases (102 fixture: my_test_analytic_curves circle/ellipse, my_test_drop_curve_near_seam circle (inside-out), smCurveTest circle/circle and line/circle intersection configurations re-expressed as SmEllipse, edge cases: inside-out, negative/near-0/180/360 domains, tiny arcs, skewed axes, pOptNurb, SetSTEPInterval+SetUp, transforms, DropPointFast seams/sub-intervals + 2000 generated op programs), 2005 pass bit-identical (max_rel_err 0), 97 deferred (curve.curve_p5 97: LocalPropertyAnalysis and the curve solvers' Newton equations; curve.ellipse_p1 wiring cleared GlobalPointSolve, ConvertTo2D and GlobalCoincidenceChecker); 30k-seed run clean; --perturb SENSITIVE; co-ported SmEllipse constructor + MakeNurb from curve.ellipse_p1 (Ellipse not yet a CurveKind variant); wired UNPORTED(curve.ellipse_p2) in curve.line (Line::intersect_with_ellipse takes &Ellipse; curve.line deferred 2 -> 1). 44 fns; largest: SmEllipse::IntersectWithEllipse, SmPolarConversion::SetUpPolarConversion, SmEllipse::IntersectWithLine, SmEllipse::DropPointFast; cycle back-edges (call into later units; stub or co-port): curve.curve_p5(3), curve.curve_p1(2), curve.curve_p3(2), curve.curve_p6(1), curve.ellipse_p1(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.hermite_curve"
upstream = ["source/SMLib/inc/SmHermiteCurve.h", "source/SMLib/src/SmHermiteCurve.cpp"]
rust_module = "curve::hermite_curve"
depends_on = ["geom.extent1d", "geom.extent3d", "geom.pseudo_box", "geom.vector3d", "topology.database_io"]
soft_depends_on = ["geom.geom_utility_p1", "geom.polar_box", "geom.tol"]
est_lines = 383
layer = 6
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.hermite_curve-a1"
claimed_at = "2026-10-12T21:03:28Z"
notes = "18 fns; largest: SmHermiteCurve::Evaluate, SmHermiteCurve::CalculateBoundingBox, SmHermiteCurve::ReadFromDB, SmHermiteCurve::GetKnots; cycle back-edges (call into later units; stub or co-port): curve.curve_p2(3), curve.curve_p5(3); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; difftest green: 2131 cases, 0 deferred, max_rel_err 0 (SmCurve::IsKindOf wired by curve.curve_p2)"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.hyperbola"
upstream = ["source/SMLib/inc/SmHyperbola.h", "source/SMLib/src/SmHyperbola.cpp"]
rust_module = "curve::hyperbola"
depends_on = ["curve.curve_p2", "geom.axis2_placement", "geom.extent1d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector3d", "nurbs.b_spline_curve_p1", "nurbs.b_spline_curve_p2", "topology.database_io"]
soft_depends_on = ["geom.geom_utility_p1"]
est_lines = 468
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.hyperbola-a1"
claimed_at = "2026-10-13T01:00:33Z"
notes = "GREEN (promoted by curve.curve_p5: 2062 cases, 0 deferred after its stubs were wired); difftest: 2062 cases, 1960 pass, 102 deferred (curve.curve_p1 70: SmCurve::GlobalPointSolve; curve.curve_p5 32: SmCurve::EvaluateSTEPPoint); wired UNPORTED(curve.hyperbola) in curve.curve_p2 (SmCurve::ReadFromDB). 22 fns; largest: SmHyperbola::MakeNurb, SmHyperbola::ReadFromDB, SmHyperbola::STEPInversion, SmHyperbola::EvaluateSTEP; cycle back-edges (call into later units; stub or co-port): curve.curve_p1(1), curve.curve_p5(1), surface.surf_of_extrusion_p1(1), surface.surf_of_revolution_p1(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.iso_curve"
upstream = ["source/SMLib/inc/SmIsoCurve.h", "source/SMLib/src/SmIsoCurve.cpp"]
rust_module = "curve::iso_curve"
depends_on = ["curve.curve_p2", "geom.extent1d", "geom.extent2d", "geom.object", "geom.vector3d", "topology.database_io"]
soft_depends_on = ["geom.tol", "geom.vector2d"]
est_lines = 310
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.iso_curve-a1"
claimed_at = "2026-10-13T01:17:13Z"
notes = "GREEN: difftest 2874 cases, 2874 pass bit-identical, 0 deferred (SmSurface::CalculateContinuities wired by surface.surface_p6, PR #92). Earlier: PARTIAL: difftest 2874 cases (874 fixture: Surface.sms / offset_nurb.sms / DropCurveSurface.sms iso curves at domain ends, interior knots, outside the domain with and without clamping, bilinear patch and NURB-less surface edge cases, all ten SmSurfParamType values, equality near SM_IS_ZERO, ReadFromDB streams + 2000 generated), 2589 pass bit-identical (max_rel_err 0), 285 deferred (SmBSplineSurface::Evaluate back-edge wired 2026-10-12 in style review batch #5: 355 formerly deferred now pass; surface.surface_p6 120: SmSurface::CalculateContinuities; surface.surface_p2 101: SmSurface::ReadFromDB; curve.line 64: SmLine ctor in CreateUVIsoLine); --perturb SENSITIVE; base surface held as BSplineSurface (the only ported SmSurface); EvaluatePoint wired to nurbs.b_spline_surface_n_lib_p1; wired SmCurve::ReadFromDB(SmIsoCurve_TYPE) in curve.curve_p2 (still deferred on SmSurface::ReadFromDB, no counts changed); CurveKind::Iso. 16 fns; largest: SmIsoCurve::Evaluate, SmIsoCurve::ReadFromDB, SmIsoCurve::SmIsoCurve, SmIsoCurve::CreateUVIsoLine; cycle back-edges (call into later units; stub or co-port): surface.surface_p2(8), curve.curve_p5(2), curve.line(1), surface.surface_p1(1), surface.surface_p6(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; after curve.line wiring (SmLine in CreateUVIsoLine): 2874 cases, 2653 pass, 221 deferred (surface.surface_p2 101, surface.surface_p6 120) EXTENDED in surface.surface_point_solve_p3 (PR #106): IsoCurve::from_surface stores a concrete Surface, preserving plane/revolution/STEP virtual evaluation; read dispatch now retains all supported surface kinds. Equality is fallible, propagating surface comparison errors. PR #106: the general Surface constructor and database reader reject owned-geometry nesting beyond 64 levels before recursive dispatch; the B-spline constructor remains infallible."
+12
View File
@@ -0,0 +1,12 @@
id = "curve.line"
upstream = ["source/SMLib/inc/SmLine.h", "source/SMLib/src/SmLine.cpp"]
rust_module = "curve::line"
depends_on = ["curve.curve_p2", "geom.assert_array", "geom.extent1d", "geom.extent2d", "geom.extent3d", "geom.object", "geom.pseudo_box", "geom.solution_array", "geom.tol", "geom.vector3d", "nurbs.b_spline_curve_n_lib", "nurbs.b_spline_curve_p1", "nurbs.b_spline_curve_p2", "nurbs.b_spline_curve_p3", "topology.database_io"]
soft_depends_on = ["geom.axis2_placement", "geom.geom_utility_p1", "geom.geom_utility_p2", "geom.polar_box", "nurbs.nurbs_crv"]
est_lines = 1884
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = ""
claimed_at = ""
notes = "GREEN (promoted by curve.curve_p5: 2103 cases, 0 deferred after its stubs were wired); PARTIAL: difftest 2103 cases (103 fixture: my_test_reversed_line_join x16, smTopoTest canonical lines + AdjustSTEPInterval, my_test_analytic_curves line, my_test_bsplinecurve_nlib line deform/copy, SM_API TestSmCurves/TestSmBrep lines, edge cases: degenerate/zero-vector/inside-out/infinite/2D lines, ReadFromDB ASCII+binary v30/v33/2D/rational, line/line intersections incl. overlap ranges, drop/GPS/STEP inversion, trims, joins, deform, offset, transform, AssertValid + 2000 generated programs of up to 6 ops), 2102 pass bit-identical (max_rel_err 0), 1 deferred (curve.curve_p4 1: SmCurve::AssertValid; IntersectWithEllipse wired by curve.ellipse_p2); 40k-seed run clean; --perturb SENSITIVE; co-ported SmCurve::EvaluateSTEPPoint for lines; wired UNPORTED(curve.line) in curve.curve_p2 (ReadFromDB), nurbs.b_spline_curve_p2 (CreateAnalyticCurve), nurbs.b_spline_curve_p3 (unreachable JoinWith branch dropped), curve.iso_curve (CreateUVIsoLine); fixed nurbs.b_spline_curve_n_lib DeformToEndPointTargets to ignore DegreeElevate status as upstream (see findings). 62 fns; largest: SmLine::IntersectWithLine, SmLine::GlobalPointSolveSTEP, SmLine::JoinWith, SmLine::Tessellate; cycle back-edges (call into later units; stub or co-port): curve.curve_p5(6), curve.ellipse_p2(1), surface.surf_of_extrusion_p1(1), surface.surf_of_revolution_p1(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; after curve.curve_p7: the 1 deferred case is now blocked by curve.curve_p5"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.offset_curve"
upstream = ["source/SMLib/inc/SmOffsetCurve.h", "source/SMLib/src/SmOffsetCurve.cpp"]
rust_module = "curve::offset_curve"
depends_on = ["curve.curve_p2", "geom.extent1d", "geom.object", "geom.vector3d", "topology.database_io"]
soft_depends_on = ["geom.tol"]
est_lines = 492
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.offset_curve-a1"
claimed_at = "2026-10-13T01:00:33Z"
notes = "20 fns; largest: SmOffsetCurve::Evaluate, SmOffsetCurve::ReadFromDB, SmOffsetCurve::EvaluatePoint, SmOffsetCurve::Trim; cycle back-edges (call into later units; stub or co-port): curve.curve_p5(3); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; GREEN: difftest 2808 cases (808 fixture: TestSmOffsetCurve curve/line/vertical-line offsets, smTopoTest nested zero offsets, rational arc cusp, parabola evolute, degenerate ends, Hermite bases, reversed/trimmed/copied/compared curves, ReadFromDB ASCII+binary streams from upstream WriteToDB + 2000 generated), 0 deferred, bit-identical (max_rel_err 0); --perturb SENSITIVE. Wired: SmCurve::ReadFromDB(SmOffsetCurve_TYPE); CreateSimpleOffset now defers on SmCurve::ApproximateCurve (curve.curve_p1)"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.parabola"
upstream = ["source/SMLib/inc/SmParabola.h", "source/SMLib/src/SmParabola.cpp"]
rust_module = "curve::parabola"
depends_on = ["curve.curve_p2", "geom.axis2_placement", "geom.extent1d", "geom.object", "geom.solution_array", "geom.tol", "geom.vector3d", "nurbs.b_spline_curve_p1", "nurbs.b_spline_curve_p2", "topology.database_io"]
soft_depends_on = ["geom.geom_utility_p1"]
est_lines = 441
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.parabola-a1"
claimed_at = "2026-10-13T01:00:33Z"
notes = "difftest green: 3044 cases, 3044 pass bit-identical (max_rel_err 0), 0 deferred; GlobalPointSolveSTEP wired to SmCurve::GlobalPointSolve (curve.curve_p1) at merge (206 formerly deferred cases now pass); SmCurve::EvaluateSTEPPoint (curve.curve_p5) co-ported; surf_of_extrusion_p1/surf_of_revolution_p1 GetGenDirParamExtent stubs remain (no case reaches them); CurveKind::Parabola dispatches SmBSplineCurve methods on its base like Hyperbola; wired UNPORTED(curve.parabola) in curve.curve_p2 (ReadFromDB). 22 fns; largest: SmParabola::MakeNurb, SmParabola::ReadFromDB, SmParabola::Transform, SmParabola::EvaluateSTEP; cycle back-edges (call into later units; stub or co-port): curve.curve_p1(1), curve.curve_p5(1), surface.surf_of_extrusion_p1(1), surface.surf_of_revolution_p1(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.projected_curve"
upstream = ["source/SMLib/inc/SmProjectedCurve.h", "source/SMLib/src/SmProjectedCurve.cpp"]
rust_module = "curve::projected_curve"
depends_on = ["curve.curve_p2", "geom.axis2_placement", "geom.object", "geom.vector3d", "topology.database_io"]
soft_depends_on = []
est_lines = 569
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.projected_curve-a1"
claimed_at = "2026-10-13T01:00:34Z"
notes = "difftest: 2727 cases, 0 deferred (green); wired curve.curve_p2 SmProjectedCurve::ReadFromDB back-edge. 25 fns; largest: SmProjectedCurve::ReadFromDB, SmProjectedCurve::Evaluate, SmProjectedCurve::Transform, SmProjectedCurve::EvaluatePoint; cycle back-edges (call into later units; stub or co-port): curve.curve_p5(2); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "curve.tangent_field"
upstream = ["source/SMLib/inc/SmTangentField.h", "source/SMLib/src/SmTangentField.cpp"]
rust_module = "curve::tangent_field"
depends_on = ["curve.curve_p2", "geom.extent1d", "geom.vector3d", "topology.database_io"]
soft_depends_on = ["geom.vector2d"]
est_lines = 319
layer = 14
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-curve.tangent_field-a1"
claimed_at = "2026-10-13T01:00:35Z"
notes = "GREEN (promoted by surface.surface_p1 after the surface_p7 merge: difftest 655 cases, 655 pass, 0 deferred); 12 fns; largest: SmTangentField::EvaluatePoint, SmTangentField::Create, SmTangentField::ReadFromDB, SmTangentField::Evaluate; cycle back-edges (call into later units; stub or co-port): curve.crv_on_surf(5), surface.surface_p7(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.a_object"
upstream = ["source/SMLib/inc/NLI_Math.h", "source/SMLib/inc/SmAObject.h", "source/SMLib/inc/SmCacheMgr.h", "source/SMLib/inc/SmSAGObject.h", "source/SMLib/src/SmAObject.cpp", "source/SMLib/src/SmCacheMgr.cpp", "source/SMLib/src/SmSAGObject.cpp"]
rust_module = "geom::a_object"
depends_on = ["geom.assert_array", "geom.attribute", "geom.object"]
soft_depends_on = ["geom.tol", "geom.transform"]
est_lines = 935
layer = 6
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-geom.a_object-a1"
claimed_at = "2026-10-12T20:54:39Z"
notes = "PARTIAL: re-run in PR #154 (topology.shell, region lookup from PR #80): 2040 cases, 1909 pass, 0 failed, 131 deferred (query.brep 131), max_rel_err 0; the 37 SmRegion::IsVoid cases pass through notify_with_regions. Earlier: PARTIAL: difftest 2040 cases (8 upstream-derived + 32 edge-case fixtures + 2000 generated: types, NLI helpers, notify/attribute/cache scripts), 1872 pass bit-identical, 168 deferred (query.brep 131: SmBrep::CalculateBoundingBox reached through the now-ported SmBrepCache (PR #115); topology.shell 37: SmRegion::IsVoid in SM_NO_REG_PROPAGATION; SmSAGObject::Notify wired by topology.topology); 50k-seed run clean; no UNPORTED(geom.a_object) stubs to wire (attribute-list methods stay co-ported in geom.attribute); 36 fns; largest: SmAObject::Notify, SmAObject::AssertValid, SmSAGObject::CacheMakeOrValidate, SmSAGObject::Notify; cycle back-edges (call into later units; stub or co-port): query.poly(13), topology.proto_topology_p1(9), blend.fillet_geom_p1(5), topology.brep_cache(3), topology.shell(3), surface.cone_p1(2), topology.loopuse(2), topology.topology(2), curve.composite_curve_p1(1), curve.conic(1), curve.crv_in_volume(1), curve.crv_on_surf(1), curve.curve_cache(1), curve.curve_p2(1), curve.ellipse_p1(1), curve.ellipse_p2(1), curve.hermite_curve(1), curve.hyperbola(1), curve.iso_curve(1), curve.line(1), curve.offset_curve(1), curve.parabola(1), curve.projected_curve(1), curve.tangent_field(1), nurbs.b_spline_curve_p1(1), nurbs.b_spline_surface_p1(1), query.tess(1), surface.b_spline_volume(1), surface.bend_volume(1), surface.curve_bounded_surface(1), surface.offset_surface(1), surface.plane_p1(1), surface.sphere(1), surface.srf_in_volume(1), surface.surf_of_extrusion_p1(1), surface.surf_of_revolution_p1(1), surface.surface_cache_p2(1), surface.surface_p1(1), surface.surface_p2(1), surface.torus(1), surface.trim_srf_cache(1), surface.twist_volume(1), surface.unbend_volume(1), surface.volume_p1(1), topology.brep_p4(1), topology.edge(1), topology.edgeuse_p1(1), topology.edgeuse_p2(1), topology.face_p1(1), topology.vertex(1), topology.vertexuse(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; UNCOVERED (PR #154 review): geom_a_object.cpp never calls SmRegion::SetIsVoid, so other_solid = false (a_object.rs region propagation, SmAObject.cpp:310) is compared only on the solid side GREEN after query.brep (PR #329): the B-rep box is ported, so the cache builds; 0 deferred."
+12
View File
@@ -0,0 +1,12 @@
id = "geom.assert_array"
upstream = ["source/SMLib/inc/SmAssertArray.h", "source/SMLib/src/SmAssertArray.cpp"]
rust_module = "geom::assert_array"
depends_on = []
soft_depends_on = ["geom.tol", "geom.vector2d"]
est_lines = 373
layer = 2
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.assert_array-a1"
claimed_at = "2026-10-12T19:48:02Z"
notes = "10 fns; largest: SmAssertReport::SmAssertReport, SM_GetAssertLabelList, SmAssertArray::AddUniqueDeleteDuplicate, SmAssertArray::Contains; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; difftest: 3734 cases (fixtures, every label-table entry, generated reports and AddUniqueDeleteDuplicate/Contains/SetLastAdd sequences), all bit-identical, 0 deferred"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.attribute"
upstream = ["source/SMLib/inc/SmAttribute.h", "source/SMLib/src/SmAttribute.cpp"]
rust_module = "geom::attribute"
depends_on = ["topology.database_io"]
soft_depends_on = []
est_lines = 920
layer = 1
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-geom.attribute-a1"
claimed_at = "2026-10-12T19:38:43Z"
notes = "GREEN: PR #80 region lookup integration; 2029/2029 native comparisons, zero failures/deferrals, max_rel_err=0; all 2029 perturbations detected. merge_with_regions resolves actual typed regions and optional B-rep identities through RegionLookup; the legacy merge entry point explicitly requires context for merge-region attributes. Earlier port notes: 90 fns; largest: SmMergeRegionAttribute::Merge, SmAttribute::Split, SmColorAttribute::PropagateRegionsThroughBooleans, SmAttributeData::ReadIndexedAttributesFromDB; cycle back-edges (call into later units; stub or co-port): geom.a_object(14), geom.object(11), query.brep(6), geom.vector3d(4), query.tess(4), topology.shell(3), curve.composite_curve_p1(2); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; PARTIAL: difftest 2029 cases (29 fixture + 2000 generated), 1991 pass bit-identical, 38 deferred (topology.shell 38: SmRegion::GetBrep in SmMergeRegionAttribute::Merge); 200k-seed run clean; SmAObject attribute-list methods co-ported into AttributeStore (CO-PORT(geom.a_object)), SmObject::IsKindOf co-ported (geom.object); region_type::VOID / INFINITE arms of merge-with-regions (PR #154 review): script ops 32 SetIsVoid(0/1/2) and 33 MakeInfinite (the object becomes the infinite region of a fresh SmBrep; skipped once any attribute exists) mirrored by RegionScene::set_is_void / make_infinite; generated cases that create merge-region attributes first draw those ops, so the add_region classification is compared on the void, UNSURE and infinite sides (mutating the INFINITE arm fails generated cases). Missing region context is Unported(topology.shell), not InvalidInput"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.axis2_placement"
upstream = ["source/SMLib/inc/SmAxis2Placement.h", "source/SMLib/src/SmAxis2Placement.cpp"]
rust_module = "geom::axis2_placement"
depends_on = ["geom.vector3d"]
soft_depends_on = ["geom.tol"]
est_lines = 479
layer = 3
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.axis2_placement-a1"
claimed_at = "2026-10-12T20:00:41Z"
notes = "GREEN: difftest 4048 cases, all bit-identical, 0 deferred (AreCoaxial wired to geom.geom_utility_p1); 30 fns; largest: SmAxis2Placement::RotateAboutAxis, SmAxis2Placement::AreCoaxial, SmAxis2Placement::GetMatrix, SmAxis2Placement::GetMirrorMatrix; cycle back-edges (call into later units; stub or co-port): geom.geom_utility_p1(1); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.context"
upstream = ["source/SMLib/inc/SmContext.h", "source/SMLib/inc/SmTopoTypes.h", "source/SMLib/src/SmContext.cpp", "source/SM_API/src/SmApiGeneral.cpp"]
rust_module = "geom::context"
depends_on = []
soft_depends_on = ["geom.tol"]
est_lines = 355
layer = 2
tests = ["prog_test:my_test_crv_projected_max", "prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix"]
status = "green"
claimed_by = "swarm-geom.context-a1"
claimed_at = "2026-10-12T19:48:04Z"
notes = "green: 2013 difftest cases (13 fixtures + 2000 generated scripts), 0 deferred, all bit-identical; wired UNPORTED(geom.context) in geom.tol (Option<&Context> overloads; geom.tol stays green). 30 fns; largest: SmNewMarkAndLock::LockMark, SmNewMarkAndLock::UnlockMark, SmContext::NewMark, SmContext::SmContext; entry points: SmApiCreateContext, SmApiGetOrCreateContext; unit-SCC #22 (220 units); 320 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.extent1d"
upstream = ["source/SMLib/inc/SmExtent1d.h", "source/SMLib/inc/SmExtentNd.h", "source/SMLib/src/SmExtent1d.cpp", "source/SMLib/src/SmExtentNd.cpp"]
rust_module = "geom::extent1d"
depends_on = []
soft_depends_on = ["geom.tol"]
est_lines = 974
layer = 2
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.extent1d-a1"
claimed_at = "2026-10-12T19:48:21Z"
notes = "GREEN: difftest 3091 cases (91 fixture from my_test_extent1d/header examples/edge cases + 3000 generated), all bit-identical, 0 deferred, max_rel_err 0; --perturb SENSITIVE. Wired back-edges: SmExtent3d::Get{U,V,W}Interval/Set{U,V}Interval (geom.extent3d intervals cases no longer deferred), SmTol::MapTo1d(SmTol3d&,SmVector3d&,const SmExtent1d&) and SmTol::GetScaledZero(const SmExtent1d&) (geom.tol, +5 fixtures and a map_to_1d op). Unowned dead fns (OnlySnapValue, Maximum/MinimumDistance, AreOverlapping, ContainsValueRelative, AnyBounds, AssertValid, Dump) not ported. 56 fns; largest: SmExtent1d::IntersectPeriodic, SmExtent1d::ContainsPeriodicValue, SmExtentNd::ClampVector, SmExtent1d::ApproximateUnbounded; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.extent2d"
upstream = ["source/SMLib/inc/SmExtent2d.h", "source/SMLib/src/SmExtent2d.cpp"]
rust_module = "geom::extent2d"
depends_on = ["geom.extent1d", "geom.vector2d"]
soft_depends_on = ["geom.extent3d", "geom.tol", "geom.vector3d"]
est_lines = 766
layer = 3
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.extent2d-a1"
claimed_at = "2026-10-12T20:02:32Z"
notes = "55 fns; largest: SmExtent2d::IntersectWithInfiniteLine, SmExtent2d::ClipLine2d, SmExtent2d::Inversion, SmExtent2d::ClassifyPoint2d; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; GREEN: difftest 3069 cases (69 fixture + 3000 generated), all bit-identical, 0 deferred, max_rel_err 0; 30k-seed run clean; only the 55 owned fns ported (rest of SmExtent2d is in unused_functions.txt); wired UNPORTED(geom.extent2d) SmTol::GetScaledZero(const SmExtent2d&) in geom/tol.rs (geom.tol still green, 3440 cases)"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.extent3d"
upstream = ["source/SMLib/inc/SmExtent3d.h", "source/SMLib/src/SmExtent3d.cpp"]
rust_module = "geom::extent3d"
depends_on = []
soft_depends_on = []
est_lines = 1122
layer = 0
tests = ["prog_test:my_test_extent3d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle"]
status = "green"
claimed_by = "swarm-geom.extent3d-a1"
claimed_at = "2026-10-12T19:22:46Z"
notes = "GREEN: difftest 3086 cases, all bit-identical, 0 deferred (Circumscribe wired by geom.pseudo_box); geom.extent1d intervals wired; co-ports sm_sqrt/sm_asin/GetMaxDimension (geom.vector3d). 67 fns; largest: SmExtent3d::IntersectLine, SmExtent3d::Circumscribe, SmExtent3d::ApproximateUnbounded, SmExtent3d::ComputeConeBoundTo; cycle back-edges (call into later units; stub or co-port): geom.vector3d(51), geom.extent1d(9), geom.pseudo_box(4); unit-SCC #22 (220 units); 318 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.geom_utility_p1"
upstream = ["source/SMLib/src/SmGeomUtility.cpp"]
rust_module = "geom::geom_utility::p1"
depends_on = ["geom.axis2_placement", "geom.extent1d", "geom.matrix", "geom.tol", "geom.vector2d", "geom.vector3d"]
soft_depends_on = ["geom.polynomial"]
est_lines = 2178
layer = 4
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.geom_utility_p1-a1"
claimed_at = "2026-10-12T20:09:08Z"
notes = "GREEN: difftest 4185 cases (185 fixture + 4000 generated), all bit-identical, 0 deferred; wired UNPORTED(geom.geom_utility_p1) in geom.axis2_placement (now green) and geom.geom_utility_p2 (now green); 45 fns; largest: smgu_LineCoPlanarCircleIntersect, smgu_BestFitLineToPoints, smgu_CircleCoPlanarCircleIntersect, smgu_TransformPointToStartPlane; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.geom_utility_p2"
upstream = ["source/SMLib/src/SmGeomUtility.cpp"]
rust_module = "geom::geom_utility::p2"
depends_on = ["geom.tol", "geom.vector3d"]
soft_depends_on = ["geom.matrix", "geom.vector2d"]
est_lines = 1617
layer = 3
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.geom_utility_p2-a1"
claimed_at = "2026-10-12T20:00:30Z"
notes = "16 fns; largest: smgu_SphereCircleSphereCircleIntersect, smgu_EvaluateCurveContinuity, smgu_SegmentSegmentIntersect, smgu_SegmentSegmentPerpspectiveIntersect; cycle back-edges (call into later units; stub or co-port): geom.geom_utility_p1(28); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; GREEN: difftest 3270 cases (70 fixture + 3200 generated), all bit-identical, 0 deferred (p1 back-edges wired by geom.geom_utility_p1)"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.global_solver"
upstream = ["source/SMLib/inc/SmGlobalSolver.h", "source/SMLib/src/SmGlobalSolver.cpp"]
rust_module = "geom::global_solver"
depends_on = ["geom.extent1d", "geom.extent3d", "geom.solution_array", "geom.vector3d"]
soft_depends_on = ["geom.geom_utility_p1", "geom.object", "geom.tol", "geom.tree", "geom.vector2d"]
est_lines = 1775
layer = 5
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "partial"
claimed_by = "swarm-geom.global_solver-a1"
claimed_at = "2026-10-12T20:41:08Z"
notes = "24 fns; largest: SmGlobalSolver::BranchMayContainAnswers, SmGlobalSolver::AddSortedSolution, sm_CombineMinMax, SmGlobalSolver::FindBestSubdivisionNode; cycle back-edges (call into later units; stub or co-port): blend.fillet_intersector(3), intersect.adv_surface_intersector(3), intersect.surface_drop_curve(3), intersect.surface_intersector_p1(3), intersect.surface_silhouette(3), intersect.surface_tracer(3), intersect.topology_solver_p1(3), surface.surface_p2(3), curve.crv_on_surf(2), curve.curve_cache(1); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; difftest partial: 620 cases (20 fixtures + 600 generated), 611 pass, 9 deferred (curve.curve_p2 9: SmCurve::GetNaturalInterval via IdenticalSolutions on line solutions), max_rel_err 0; 20k-seed run clean; no UNPORTED(geom.global_solver) stubs existed to wire"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.grid"
upstream = ["source/SMLib/inc/SmGrid.h", "source/SMLib/src/SmGrid.cpp"]
rust_module = "geom::grid"
depends_on = ["geom.extent3d", "geom.object", "geom.vector3d"]
soft_depends_on = ["geom.tree"]
est_lines = 876
layer = 4
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "partial"
claimed_by = "swarm-geom.grid-a1"
claimed_at = "2026-10-12T20:21:29Z"
notes = "CO-PORTED in intersect.ray_tracer (PR #48): PARTIAL: difftest 615 cases (15 fixture + 600 generated), 613 pass bit-identical, 2 deferred (surface.surface_cache_p3 1: SmSurfaceGridElement::Init needs the patch data of a bare tree node; surface.surface_p2 1: ExpandHierarchy via smsurf_GetSurfaceCache, a DISPATCH GAP (the element holds a handle, no store turns it into the Surface); retagged by surface.surface_cache_p1, then by surface.surface_p1 in PR #43); 30k-seed run clean; no UNPORTED(geom.grid) stubs existed. 23 fns; largest: SmGrid::Setup3DDDA, SmGrid::Step3DDDA, SmSurfaceHierarchyElement::ExpandHierarchy, SmGrid::AddElement; cycle back-edges (call into later units; stub or co-port): geom.extent2d(2), surface.surface_cache_p1(2), surface.surface_p2(2), geom.polar_box(1), geom.pseudo_box(1), surface.surface_cache_p3(1), surface.surface_p7(1); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.hash_table"
upstream = ["source/SMLib/inc/SmHashTable.h"]
rust_module = "geom::hash_table"
depends_on = ["geom.extent3d", "geom.tol", "geom.vector3d"]
soft_depends_on = []
est_lines = 593
layer = 3
tests = ["prog_test:my_test_closed_sphere_properties", "prog_test:my_test_squeeze_edge_tracks_removal", "prog_test:my_test_missing_poles_refreshes_all_faces", "SM_API_test:TestSmHealBrep", "SM_API_test:TestSmHeal", "prog_test:my_test_MakeFace", "pt_TestFiles/MakeFace/ApproximateSphere.smp"]
status = "green"
claimed_by = "swarm-geom.hash_table-a1"
claimed_at = "2026-10-12T20:00:27Z"
notes = "GREEN: difftest 619 cases (19 fixture incl. SmHealData::Cache_CoinVertices replays on Points.pts/FitCrvPoints.pts/PointSet + 600 generated), 0 deferred, bit-identical; a 10,019-case run was also clean; upstream IncMaxItemCount use-after-free and FindCoincidentPairs head-only/aliasing quirks in findings.md. 12 fns; largest: SmObjsInVoxels::Add, SmObjsInVoxels::FindCoincidentPairs, SmObjsInVoxels::IncMaxItemCount, SmObjsInVoxels::MapPointToVoxel; unit-SCC #22 (220 units); 59 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.local_solve1d"
upstream = ["source/SMLib/inc/SmLocalSolve1d.h", "source/SMLib/src/SmLocalSolve1d.cpp"]
rust_module = "geom::local_solve1d"
depends_on = ["geom.extent1d"]
soft_depends_on = ["geom.tol"]
est_lines = 1294
layer = 3
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.local_solve1d-a1"
claimed_at = "2026-10-12T20:02:32Z"
notes = "12 fns; largest: SmLocalSolve1d::SolveIt, SmLocalSolve1d::SolveOscillating, SmLocalSolve1d::SolveByBrent, SmLocalSolve1d::SolveByBisection; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; difftest: 3316 cases (316 fixture + 3000 generated), bit-identical, 0 deferred"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.local_solve_nd"
upstream = ["source/SMLib/inc/SmLocalSolveNd.h", "source/SMLib/src/SmLocalSolveNd.cpp"]
rust_module = "geom::local_solve_nd"
depends_on = ["geom.matrix"]
soft_depends_on = []
est_lines = 860
layer = 3
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.local_solve_nd-a1"
claimed_at = "2026-10-12T19:58:04Z"
notes = "15 fns; largest: SmLocalSolveNd::SolveIt, SmEvalNFunctionsObject::ComputeJacobian, SmLocalSolveNd::SmLocalSolveNd, SmEvalNFunctionsObject::Evaluate; cycle back-edges (call into later units; stub or co-port): geom.extent1d(4); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; GREEN: difftest 3043 cases (43 fixture + 3000 generated), 0 deferred, max_rel_err 0 (bit-identical, full Evaluate trace compared); 30k-seed run clean; back-edges into geom.extent1d resolved by its merge; wired SmTol::GetScaledZero(SmEvalNFunctionsObject) in geom.tol"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.matrix"
upstream = ["source/SMLib/inc/SmMatrix.h", "source/SMLib/src/SmMatrix.cpp"]
rust_module = "geom::matrix"
depends_on = []
soft_depends_on = ["geom.tol"]
est_lines = 816
layer = 2
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.matrix-a1"
claimed_at = "2026-10-12T19:48:03Z"
notes = "20 fns; largest: SmMatrix::EigenSystemJacobiSolver, SmMatrix::LUDecompose, SmMatrix::SolveLinearSystem, SmMatrix::Compute3x3EigenVectors; cycle back-edges (call into later units; stub or co-port): geom.vector3d(2); unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; GREEN: difftest 4044 cases (44 fixture + 4000 generated), 0 deferred, max_rel_err 0 (bit-identical); 100k-seed run clean; back-edges sm_sqrt/SmVector3d::Set (geom.vector3d) co-ported as private helpers"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.object"
upstream = ["source/SMLib/inc/SmObject.h", "source/SMLib/inc/SmShape.h", "source/SMLib/src/SmObject.cpp", "source/SMLib/src/SmShape.cpp", "source/SMLib/src/SmThreadLocalStorage.cpp"]
rust_module = "geom::object"
depends_on = ["geom.context", "geom.extent3d", "geom.tree"]
soft_depends_on = ["geom.attribute"]
est_lines = 673
layer = 3
tests = ["prog_test:my_test_polynomial", "SM_API_test:TestSmPrincipalDirectionPairing", "prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point"]
status = "green"
claimed_by = "swarm-geom.object-a1"
claimed_at = "2026-10-12T20:05:41Z"
notes = "GREEN (shape follow-up to PR #329): SmShape::SmShape ported over a caller BrepStore (B-rep, face and edge boxes, marked tree loading); the runner builds shapes on the shared fixture B-rep (SmApiCreateBox solid) with the import given upstream's GetFaces/GetEdges/GetVertices orders. difftest 624 cases (24 fixture + 600 generated), 624 pass bit-identical, 0 deferred, --perturb SENSITIVE 624/624, --seeds 2000: 2024/2024. Before: 593 pass, 31 deferred (query.face_p1 11, topology.brep_p1 10, topology.vertex 6, topology.edge 4: every non-empty SmShape). NotifyCallback::execute added to geom.context (stays green); UNPORTED(geom.object) note in geom.tol retagged to topology.topology (SmTol object overloads need topology/curve/surface object types). 38 fns; largest: SmShape::SmShape, SmObject::Notify, SmThreadLocalStorage::SetBeenThroughNew, SmThreadLocalStorage::GetBeenThroughNew; cycle back-edges (call into later units; stub or co-port): query.poly(24), topology.proto_topology_p1(20), blend.fillet_solver_p1(16), blend.fillet_standard_solver_p1(12), blend.fillet_geom_p1(10), query.brep(7), blend.fillet_custom_solver(6), blend.fillet_executive_p1(6), geom.a_object(6), geom.grid(6), intersect.point_class(6), intersect.ray_tracer(6), query.tess(6), topology.edge(5), topology.topology(5), curve.composite_curve_p1(4), surface.cone_p1(4), topology.brep_p1(4), topology.loopuse(4), topology.shell(4), curve.curve_p2(3), surface.surface_p1(3), surface.surface_p2(3), topology.vertex(3), blend.fillet_corner_p1(2), boolean.merge_p1(2), boolean.topology_intersector_p1(2), curve.conic(2), curve.crv_in_volume(2), curve.crv_on_surf(2), curve.curve_cache(2), curve.ellipse_p1(2), curve.ellipse_p2(2), curve.hermite_curve(2), curve.hyperbola(2), curve.iso_curve(2), curve.line(2), curve.offset_curve(2), curve.parabola(2), curve.projected_curve(2), curve.tangent_field(2), geom.solution_array(2), geom.transform(2), intersect.curve_class_p1(2), nurbs.b_spline_curve_p1(2), nurbs.b_spline_surface_p1(2), surface.b_spline_volume(2), surface.bend_volume(2), surface.curve_bounded_surface(2), surface.offset_surface(2), surface.plane_p1(2), surface.sphere(2), surface.srf_in_volume(2), surface.surf_of_extrusion_p1(2), surface.surf_of_revolution_p1(2), surface.surface_cache_p1(2), surface.surface_cache_p2(2), surface.torus(2), surface.trim_srf_cache(2), surface.twist_volume(2), surface.unbend_volume(2), surface.volume_p1(2), sweep.topology_sweep(2), topology.brep_cache(2), topology.brep_data(2), topology.brep_p4(2), topology.edgeuse_p1(2), topology.edgeuse_p2(2), topology.face_p1(2), topology.face_p4(2), topology.vertexuse(2), curve.curve_p6(1), query.edge(1), query.face_p1(1), topology.face_p2(1); unit-SCC #22 (220 units); hazards: thread_local; 321 upstream test entry points reach this unit PR #125: non-empty face Shape construction now names the actual first missing query, SmFace::CalculateBoundingBox (query.face_p1); 624 cases, 593 compared bit-identical, 31 deferred, perturb 593/593. UPDATE after topology.brep_p1 (PR #145): SmBrep::GetInfiniteRegion is ported, so the SmShape(breps) stub now names its first missing callee, SmBrep::CalculateBoundingBox (query.brep); re-run 624 cases, 593 pass, 0 fail, 31 deferred (query.face_p1 11, query.brep 10, topology.vertex 6, topology.edge 4)."
+12
View File
@@ -0,0 +1,12 @@
id = "geom.periodic_extent1d"
upstream = ["source/SMLib/inc/SmPeriodicExtent1d.h", "source/SMLib/src/SmPeriodicExtent1d.cpp"]
rust_module = "geom::periodic_extent1d"
depends_on = ["geom.tol"]
soft_depends_on = []
est_lines = 406
layer = 2
tests = ["prog_test:my_test_trimming_tools", "SM_API_test:TestSmTrimSurfaceWith3dCurves", "prog_test:my_test_closed_sphere_properties", "prog_test:my_test_squeeze_edge_tracks_removal", "prog_test:my_test_missing_poles_refreshes_all_faces", "SM_API_test:TestSmHealBrep"]
status = "green"
claimed_by = "swarm-geom.periodic_extent1d-a1"
claimed_at = "2026-10-12T00:00:00Z"
notes = "green: 4054 difftest cases (54 fixture + 4000 generated), 0 deferred, all bit-identical; 17 fns; largest: SmPeriodicExtent1d::AddInterval, SmPeriodicExtent1d::IsContainedBy, SmPeriodicExtent1d::SetMinMax, SmPeriodicExtent1d::AreDisjoint; unit-SCC #22 (220 units); 100 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.point_set"
upstream = ["source/SMLib/inc/SmPointSet.h", "source/SMLib/src/SmPointSet.cpp"]
rust_module = "geom::point_set"
depends_on = ["geom.extent3d", "geom.pseudo_box", "geom.tol", "geom.vector3d"]
soft_depends_on = ["geom.geom_utility_p1", "geom.geom_utility_p2"]
est_lines = 694
layer = 6
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.point_set-a1"
claimed_at = "2026-10-12T21:03:27Z"
notes = "16 fns; largest: SmPointSet3d::SetUpTightPseudoBox, SmPointSet3d::SetUpAxes, SmPointSequence::PointContainment, SmPointSet3d::SetUpBBoxes; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit; difftest: 2029 cases (29 fixtures + 2000 generated), 0 deferred, bit-identical"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.polar_box"
upstream = ["source/SMLib/inc/SmPolarBox.h", "source/SMLib/src/SmPolarBox.cpp"]
rust_module = "geom::polar_box"
depends_on = ["geom.extent2d", "geom.vector2d", "geom.vector3d"]
soft_depends_on = ["geom.tol"]
est_lines = 979
layer = 4
tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join", "SM_API_test:TestSmCreateRectangle", "SM_API_test:TestSmCreateRegularPolygon"]
status = "green"
claimed_by = "swarm-geom.polar_box-a1"
claimed_at = "2026-10-12T20:15:15Z"
notes = "green: 3030 difftest cases (30 fixture programs + 3000 generated), bit-identical, 0 deferred; 19 fns; largest: SmPolarBox::AddVector3d, SmPolarBox::AreDisjoint, SmPolarBox::ComputePolarCoord, SmPolarBox::EvaluateNormalized; unit-SCC #22 (220 units); 317 upstream test entry points reach this unit"
+12
View File
@@ -0,0 +1,12 @@
id = "geom.polynomial"
upstream = ["source/SMLib/src/SmPolynomial.cpp"]
rust_module = "geom::polynomial"
depends_on = ["geom.vector3d"]
soft_depends_on = []
est_lines = 386
layer = 3
tests = ["prog_test:my_test_polynomial", "SM_API_test:TestSmPrincipalDirectionPairing", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"]
status = "green"
claimed_by = "swarm-geom.polynomial-a1"
claimed_at = "2026-10-12T20:00:26Z"
notes = "4 fns; largest: SmPolynomial::SolveQuarticEqn, SmPolynomial::SolveQuadraticEqn, SmPolynomial::SolveCubicEqn, sm_AddSolution; unit-SCC #22 (220 units); 319 upstream test entry points reach this unit; GREEN: difftest 6038 cases (38 fixture from my_test_polynomial + edge cases, 6000 generated), all bit-identical, 0 deferred, perturb SENSITIVE; no UNPORTED(geom.polynomial) stubs to wire"

Some files were not shown because too many files have changed in this diff Show More