fix(#810): refman coverage audit for Document/XDE assembly (Pass 3) - #977
Conversation
Census artifact at Scripts/repro/810-refman-document-xde/. 278 OCCT classes across thirteen packages: ok 118, deliberate/recorded 160, under 0, over 35 fixed here plus one deferred to #971. The lane is wider than #810's own seven prefixes (188 headers). Six OCAF/XDE packages are named by no sub-issue of #807 at all, measured by grepping all twelve bodies: TDataXtd_, TNaming_, XCAFDimTolObjects_, XCAFView_, XCAFNoteObjects_ and XCAFPrs_. All six are claimed. Forty-four further OCAF-family packages (~460 headers) are handed off by name in #973 rather than absorbed. Over-coverage was found by two detectors rather than a hand read-through. #928's class-level census contributed 18 candidates at a 47.1% false-positive rate on this lane, close to its own measured 41.0%. A new lane-scoped Class::Member check in the census resolves every attribution against the pinned headers and their ancestors, and found 17 more that #928 structurally cannot see: TNaming_Tool::SameShape and XCAFDoc_AssemblyGraph::NbRoots do not exist, and TDataXtd_Presentation::GetColor, TDataStd_Expression::SetExpressionString and TDocStd_XLink::GetLabelEntry are near-miss spellings of Color, SetExpression and LabelEntry. One more came from reading: docs/thread-safety.md described document creation, in the present tense, as going through a singleton #371 retired. The flagship divergence now reads as a decision. Four Document-Persistence-IO.md entries attributed save, load and create to XCAFApp_Application, whose own header calls GetApplication() "the only valid method" to obtain one. The bridge deliberately does not: #371 replaced it with a private TDocStd_Application per document because the shared instance is what made #341/#344/#349/#353 reachable. That page gains a "Why not XCAFApp_Application" section and occtswift-wrapping-gaps.md carries the reasoning. Two API defects found while checking the transaction entries are filed as #970 rather than fixed here: openNamedTransaction drops its name, and transactionNumber returns a flag. Both reference pages and both Swift doc comments now describe what the code does. Closes #810 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Overview
Issue Details (click to expand)No issues found in the incremental changes. Files Reviewed (8 files)
Previous Review Summaries (2 snapshots, latest commit e835948)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit e835948)Status: No Issues Found | Recommendation: Merge Files Reviewed (4 files)
Previous review (commit f162bb4)Status: No Issues Found | Recommendation: Merge Files Reviewed (11 files)
Reviewed by nemotron-3-ultra-550b-a55b:free · Input: 276.9K · Output: 6.3K · Cached: 2M |
… blind to The method-attribution check shipped in the previous commit anchored its pattern on a closing backtick, so it matched `Class::Member` and silently skipped `Class::Member()`. docs/ writes attributions both ways. The difference contained a real finding: docs/reference/Document-XCAF-Notes.md attributed shapeMapToolExtent to XCAFDoc_ShapeMapTool::Map().Extent(), and the member is GetMap. A detector written to catch "the docs claim something the kernel does not support" was doing exactly that itself. The pattern is now loose. Four new parser self-test cases cover the spellings docs/ actually uses (plain, parenthesised, nested, and one with no backtick at all so the leading anchor cannot be dropped either), and selftest_removal_matrix.py gains a parser half that re-imposes each constraint the pattern deliberately omits: both are load-bearing, 2 of 4 cases each. Two of the docstring's six per-family finding counts were also wrong, written by hand in a block that had been read three times. FAMILY_COUNTS now repeats them as data and main() diffs it against the table, which is CLAUDE.md's own total-beside-a-list rule applied to this file. 35 findings become 36; 24 method-check candidates become 25. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Heads-up from #971, which this PR's census artifact carries as a deferred over-finding: the #971 (and this PR, following it) says void TDocStd_Document::SetModified(const TDF_Label& L) { TDocStd_Modified::Add(L); }
void TDocStd_Document::PurgeModified() { TDocStd_Modified::Clear(Main()); }
const NCollection_Map<TDF_Label>& TDocStd_Document::GetModified() const
{ return TDocStd_Modified::Get(Main()); }and The observation that made both of us conclude otherwise is correct but does not carry: the class Three sites in this diff need the correction:
Whether One more, unrelated to the reversal but in the same neighbourhood: |
…ribe #984 measured what #971 asserted and found the premise backwards. TDocStd_Document::GetModified() is `return TDocStd_Modified::Get(Main());` (TDocStd_Document.cxx:172), so the header line naming the attribute was the correct one and the `Note:` denying it was the defect. This census carried the reversed version twice: - TDocStd_Modified's curated reason said GetModified() is "a different mechanism". It is the same mechanism, reached through the document. - DEFERRED_OVER_FINDINGS pinned the line #984 KEPT rather than the one it deleted, so the check would have fired on a correct tree the moment #984 landed. The deferred list is emptied, not deleted: the mechanism is sound and the comment records both the reversal and the mis-pinned phrase so nobody restores the entry from this PR's history. Also transcribes this PR's CHANGELOG entry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Also resolves the docs/reference/Document-OCAF-Attributes.md conflict against main. #977's audit documented openNamedTransaction's PRE-fix behaviour ("the name is accepted for source compatibility and is not stored anywhere"), which this PR makes false: the name is now held to commit and written to the TDF_Delta. Kept this branch's description on both hunks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…main Resolves conflicts in docs/reference/Document-OCAF-Attributes.md (2 hunks) and Sources/OCCTSwift/Document.swift (3 hunks) against main. All five describe openNamedTransaction. #977's refman audit documented its PRE-fix behaviour, stating the name "is accepted and not recorded" and that TDocStd_Document has no named-transaction API. This PR makes the first half false: the name is held to commit and written to the TDF_Delta via TDF_Delta::SetName, which is what TDocStd_MultiTransactionManager does internally. #977's second half stays true and this branch's text already says it. Kept this branch's side on every hunk. Verified after: zero conflict markers tree-wide, swift build clean, swift-format clean on Document.swift, eight gate scripts green, and 5655 tests / 1466 suites / 0 failures. Worth recording: the first push of this commit carried conflict markers, because `git add -A` stages a conflicted file and no gate script parses Swift or Markdown for them. The build is what catches it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
What & why
Executes #810 (Pass 3 of the refman-audit epic #807): a re-runnable census comparing what OCCTSwift
wraps and documents against what OCCT's pinned kernel declares, for the OCAF/XDE document lane, in
both directions.
Artifact:
Scripts/repro/810-refman-document-xde/refman_census.py, plusselftest_removal_matrix.pyand aREADME.mdcarrying the measurements. Verdicts:ok118,deliberate, recorded160,under0,over36 fixed here plus 1 deferred to #971.Runs from any cwd. Exits 1 on an over-coverage regression, a deferred finding that was quietly
fixed, a method attribution the pinned headers do not support, an unrecorded
under, or lane driftunder
--reverify-lane.The lane is 278 classes, not 188, and the widening is measured
#810 names seven prefixes. Six more OCAF/XDE packages are named by no sub-issue of #807 at all,
established by grepping all twelve bodies (#808 to #818, #820) for every OCAF/XDE-shaped prefix in
the pinned headers:
TDataXtd_TDF_Label, exactly likeTDataStd_TNaming_XCAFDoc_ShapeToolis built onXCAFDimTolObjects_XCAFDoc_Dimension/Datum/GeomToleranceXCAFPrs_DocumentExplorer/DocumentNode/Styleare traversal and style readingXCAFView_XCAFDoc_ViewXCAFNoteObjects_XCAFDoc_NoteAll six are claimed.
TDataXtd_andTNaming_are the 51 classes #810's own review notesflagged as being in limbo; auditing
XCAFDoc_Dimensionwhile its only data-carrying type belongedto nobody would have been the same failure #808 named when it widened
BRep_Toolto the wholeBRep_*package.Forty-four further OCAF-family packages, about 460 headers, are handed off by name in #973, with
their measured bridge usage and three candidate homes (a Pass 3b for
TFunction_/TPrsStd_/TObj_,Pass 4c for the persistence drivers, Pass 4d for
StdPrs_/StdSelect_). They are the persistence,function and presentation-driver layers below the document API, a different surface from the one
#810 describes, and folding them in would have made this table larger than #808 and #809 combined
plus half again without anyone deciding that.
Over-coverage: found by two detectors, not a hand read-through
#808 and #809 both established over-coverage by one unreproducible read-through and pinned only the
conclusions. That gap was #928. This pass ran #928's detector and built a second one for the
half it structurally cannot see.
census-doc-occt-attribution.py --lane ...(#928)check_method_attributions()(new, in the census)Five findings appear in both (a claim can name a class that is not reached and a member that is
not declared), so the union is 37: 36 fixed here, 1 deferred.
#928's 47.1% on this lane is close to its own measured 41.0% over a uniform 40-row sample, which
is the first independent check of that figure. Every one of its 16 false positives falls into a
category its own README already names; the split is in this PR's
README.md.The new check is what found 18 of the 36. #928 asks whether the class a claim names is
reached, so it cannot see that
TNaming_Tool::SameShapenames a memberTNaming_Tool.hxxdoes notdeclare, because
TNaming_Toolis reached elsewhere. The new check resolves everyClass::Memberattribution in the lane against that class's own pinned header and its ancestors. Six families:
TNaming_Tool::SameShape(twice)TNaming_SameShapeIteratorXCAFDoc_AssemblyGraph::NbRootsGetRoots().Extent()XCAFDoc_AssemblyItemId::GetPathLengthGetPath().Size()TDataXtd_Presentation::GetColor/GetTransparency/GetWidth/GetModeColor/Transparency/Width/ModeTDataStd_Expression::SetExpressionString/GetExpressionStringSetExpression/GetExpressionTDocStd_XLink::Set/GetDocumentEntry,Set/GetLabelEntryDocumentEntry/LabelEntryTNaming_Scope::Clear,TDataXtd_PatternStd::SetSignature/Find,XCAFDoc_AssemblyItemRef::RemoveExtraRef/GetPathClearValid,Signature,TDF_Label::FindAttribute,ClearExtraRef,GetItemXCAFDoc_ShapeMapTool::MapGetMap, and see "the detector was blind" belowThe flagship divergence now reads as a decision
Four
docs/reference/Document-Persistence-IO.mdentries attributedsaveOCAF,saveOCAFInPlace,loadOCAFandDocument.create(format:)toXCAFApp_Application, and three more attributeddocumentCount/readingFormats/writingFormatstoCDF_Application, which declares none of them.All seven run on
TDocStd_Application.XCAFApp_Application.hxx's own comment callsGetApplication()"the only valid method to getXCAFApp_Applicationobject", and its constructor is protected, so the refman is telling the truth.OCCTSwift deliberately does the other thing: since v1.15.17 (#371)
OCCTDocument's constructor doesapp = new TDocStd_Application(), because the shared instance is what made the #341 / #344 / #349 /#353 race cluster reachable at all, and upstream maintainer gkv311's review of
OCCT#1396 reaches the same conclusion from
the other side. That divergence now has three places that say so and why:
XCAFApp_Application" section on that page, covering what is lost (nothing:the class adds only
ResourcesName()andInitDocument(), and a ground-truth C++ test confirmedequivalence before the change landed) and what is not fixed (
ocafStoreMutex()stays, because aprivate instance per document is what first makes
Resource_Manager/Storage_Schemaconcurrent,Resource_Manager::Debug and Storage_Schema::ICurrentData() races surfaced by #371 (upstream OCCT#1398) #374);
DELIBERATE_DIVERGENCEentry in the census and a full paragraph indocs/occtswift-wrapping-gaps.md.A second instance of the same divergence, which neither detector can see:
docs/thread-safety.mdstill said, in the present tense, that every document-producing call goes through that singleton. Its
own #371 section, 130 lines below, says otherwise. Corrected to past tense with a forward pointer.
Under-coverage: 155 newly recorded, 0 unrecorded
All 155 gain a reason in
docs/occtswift-wrapping-gaps.md. None needed a code fix:Standard_HEADER_DEPRECATEDat file scope.The file-scope test is what separates this list from a wrong one: grepping for
Standard_DEPRECATEDreturns 56, and five of the extras (TDocStd_Application,TDF_LabelSequence,TDataStd_Real,TDataStd_Variable,XCAFDoc_VisMaterial) are live,wrapped classes carrying a per-method deprecation on one accessor. Filing those as deprecated
aliases would have been wrong in the most misleading direction. Two of the 50's family
(
TDF_LabelSequence,TDF_LabelMap) are still genuinely called and are listed as an outstandingspelling migration, not a gap.
#includes inOCCTBridge_Document.mm. Three of thosesix reach the capability without naming the class, and the entries say so:
TDF_Label::NewChild()is literally
TDF_TagSource::NewChild(*this).grade or datum modifiers survive a round trip but cannot be read; widening
DimensionInfo/GeomToleranceInfo/DatumInfois a public API change rather than a wrap.wrapped
TDF_Delta), 10 abstract bases, 7 package classes, 4 covered by a sibling(including
TDocStd_PathParser, deliberately removed by OSDPath.fileExtension() and PathParser.fileExtension() disagree on dot-inclusion — two OCCT path-parsing classes wrapped as one duplicated public API #499 becauseParse()is wrong forextension-less paths), 2 belonging to Pass 4d (
XCAFPrs_AISObject,XCAFPrs_Texture).Two real enumeration gaps are named rather than buried:
TDocStd_XLinkIterator(links are readableper label but not enumerable per document) and
CDM_ReferenceIterator(cross-document referenceresolution is not exposed at all).
Filed rather than fixed, and why for each
Document.openNamedTransaction(_:)accepts anameand never reads it, andtransactionNumberreturns1/0rather than a transaction number. Both are behaviour changesin a public API (the only named-transaction API in OCCT 8.0.1 is
TDocStd_MultiTransactionManager::CommitCommand(name), which is not wrapped), so they get theirown issue. Both reference entries and both
///doc comments inDocument.swiftarecorrected here to describe what the code does, with a
- Warning:and a runnable snippet each.OCCTBridge_Document.h:490's comment saysOCCTDocumentIsLabelModifiedworks "viaTDocStd_Modifiedon root" and then, on the next line, that it does not. A two-line fix behind ameasured 1,714-line
clang-formatreformat, because the file is grandfathered onScripts/style-manifest-bridge.txtandcheck-style-manifest.pyrequires bringing it fully cleanin the same PR. Same trade Bring OCCTBridge_Modeling.h/.mm into clang-format compliance (deferred from PR #912) #917 tracks for
OCCTBridge_Modeling.mmand PR fix(#809): refman coverage audit for Selection/Construction (Pass 2b) #923 deferred. It iscarried in
DEFERRED_OVER_FINDINGS, whose check is inverted: the census fails if the bad textever disappears without the entry moving to
KNOWN_OVER_FINDINGS.Closes #810
CHANGELOG entry
Refman coverage audit, Pass 3: Document/XDE assembly (#810)
Scripts/repro/810-refman-document-xde/refman_census.pyenumerates every OCCT class underTDocStd_*,TDF_*,TDataStd_*,TDataXtd_*,TNaming_*,XCAFDoc_*,XCAFApp_*,XCAFDimTolObjects_*,XCAFNoteObjects_*,XCAFView_*,XCAFPrs_*,CDF_*andCDM_*(278 classes) and verdicts each against
Sources/OCCTBridgeanddocs/.Fixed 36 doc attributions across 6 files that named an OCCT class or member the implementation
does not use. Seven attributed OCAF save, load, create and session queries to
XCAFApp_ApplicationorCDF_Application; all seven run onTDocStd_Application, andXCAFApp_Applicationis deliberately not constructed anywhere in the bridge since #371 replacedthe process-wide singleton with a private application per document.
docs/reference/Document-Persistence-IO.mdgains a "Why notXCAFApp_Application" sectionrecording that divergence, and
docs/thread-safety.mdno longer describes document creation, inthe present tense, as going through a singleton retired three releases ago. Eighteen more named a
member the pinned kernel does not declare:
TNaming_Tool::SameShapeandXCAFDoc_AssemblyGraph::NbRootsdo not exist at all, andTDataXtd_Presentation::GetColor,TDataStd_Expression::SetExpressionString,TDocStd_XLink::GetLabelEntry,TDataXtd_PatternStd::SetSignature,XCAFDoc_AssemblyItemRef::RemoveExtraRefandXCAFDoc_ShapeMapTool::Mapare near-miss spellings ofColor,SetExpression,LabelEntry,Signature,ClearExtraRefandGetMap. The restnamed a class nowhere in the call chain, several semantically different from the one that runs:
Document.selectShapeusesTNaming_Selector::Select, which computes a name that survives latermodification, rather than
TNaming_Builder::Select, which records a raw select pair.Document.openNamedTransaction(_:)andDocument.transactionNumbernow document what they do:the
nameargument is accepted and never recorded, andtransactionNumberreturns1or0rather than a transaction number. The underlying API defects are #970.
Recorded 155 previously-unrecorded unwrapped classes in
docs/occtswift-wrapping-gaps.md:deprecated
NCollectiontypedefs, OCAF undo/redo delta records, abstract bases, framework storagerecords, internal helpers, GD&T qualifier enums nothing reads, and capability covered by a wrapped
sibling. No public API change.
SemVer impact
NONE. Documentation corrections only. No public Swift API or bridge C++ symbol was added, removed,
renamed, or changed in behaviour. The one
Sources/edit is two///doc comments on existingdeclarations in
Document.swift, correcting what they claim and adding a- Warning:and arunnable snippet to each.
Checklist
New or changed behavior is covered by a unit test in the same PR (not just manual
verification). N/A: no behaviour change of any kind. The census artifact is the coverage, and
its four detectors were each injected against, below.
Every new test and every new
--self-testcase was run once with its subject broken, and thefailure is reported here.
1. The over-coverage regression check. Run against the tree before this PR's corrections it
reports all 35 findings and exits 1, which is the whole battery failing on its real subject
rather than a constructed case:
After the corrections, exit 0. Whitespace is collapsed on both sides, so re-wrapping a wrong
sentence across a line break still counts.
2. The deferred check, which is inverted. Applied OCCTDocumentIsLabelModified's header comment names TDocStd_Modified, which it does not use #971's own fix to
OCCTBridge_Document.h:STALE: the following deferred findings appear to have been FIXED. Move each entry from DEFERRED_OVER_FINDINGS to KNOWN_OVER_FINDINGS, exit 1. Reverted (headerconfirmed byte-identical to
main), exit 0.3. The under-coverage check. Removed the
TNaming_UsedShapesentry fromdocs/occtswift-wrapping-gaps.md:UNRECORDED under-coverage findings ... TNaming* TNaming_UsedShapes, exit 1. Restored, exit 0.4. The new method-attribution detector. Fourteen
--self-testcases in two halves, andselftest_removal_matrix.pycovers both: it re-imposes each constraint the attribution patterndeliberately omits, and switches off each of
declares_member's four accepting shapes. Everyguard is load-bearing:
Each shape exists because omitting it produced a false report on this lane's real docs, and
SELF_TEST_CASESnames the doc line each one protects:XCAFDoc_AssemblyGraph::NodeTypeis anested enum,
CDF_Directory::myDocumentsis a private field inthread-safety.md's prose aboutthe Uncatchable SIGSEGV in parallel swift test run, right after concurrent OBJ imports — possibly related to #341, unconfirmed #344 race, and
XCAFApp_Application::SaveAsis inherited (which also proves the flagshipfinding is the right kind of defect: the claim is wrong because the class is not constructed,
not because the member is missing).
5. The detector was blind, and the matrix is what found out. The first version of
_ATTRIBUTION_REwas anchored on a closing backtick, so it matched`Class::Member`andsilently skipped
`Class::Member()`.docs/writes attributions both ways. The differencecontained a real finding:
docs/reference/Document-XCAF-Notes.mdattributedshapeMapToolExtenttoXCAFDoc_ShapeMapTool::Map().Extent(), and the member isGetMap. Thatis a detector built to catch "the docs claim something the kernel does not support" doing exactly
that itself. The pattern is now loose, the self-test has a case per spelling (plain,
parenthesised, nested, and one with no backtick at all so the anchor cannot be dropped), and the
matrix has a variant per constraint. 24 candidates became 25 and 35 findings became 36.
6. The family counts are asserted, not typed.
FAMILY_COUNTSrepeats the docstring's sixper-family totals as data and
main()diffs them against the table. Two of the six were wrongwhen written by hand, in a prose block read three times, which is CLAUDE.md's own
total-beside-a-list failure. Proved: setting
applicationto 8 givesFAMILY COUNT DRIFT: ... table has 7, FAMILY_COUNTS says 8and exit 1.The CHANGELOG entry above is complete, and
docs/CHANGELOG.mdis not in this diff.The SemVer impact above is stated, and
docs/SEMVER.mdis not in this diff.Notes for the reviewer
Gates. All seven gates, both censuses and the merge-history audit, plus every
--self-test,run clean:
check-bridge-index,check-null-handle-guards,check-docs-defaults,check-docs-existence,check-borrowed-handles,derive-bridge-header-split --verify,count-operations,check-style-manifest --base origin/main,census-unmeasured-values --self-test,census-doc-occt-attribution --self-test,check-changelog-transcription --self-test,comment-ratio-check --self-test.swift-format lint --strictandswiftlint --strictare clean onDocument.swift, which is off the manifest and therefore heldfully clean. No
swift buildorswift testwas needed: no compiled code changed.The census's own limitation, stated in its docstring rather than left to be found.
deliberate, recordedmeans the class name appears indocs/occtswift-wrapping-gaps.md, notthat the sentence around it is a reason. Five package classes (
TDF,TDataStd,TDataXtd,TNaming,XCAFDoc) matched that test before this pass wrote them an entry, because the file's"What's Wrapped" table lists their toolkits by name. #808 and #809 have the same weakness and
neither says so. Every one of this lane's 160 recorded classes now sits in a bullet written by this
pass and carrying its own reason, so name and reason coincide today; the test still cannot tell the
difference tomorrow.
This PR's own corrections raise #928's count on the lane, from 16 residual false positives to
21 (22 reported, of which one is the deferred #971). Four of the five new ones are the NOISY shape #928's README already documents: a correction
that explains itself names the wrong class again in a contrastive sentence ("
TNaming_Tooldeclares no
SameShapemember in OCCT 8.0.1"), and the detector cannot see a contrast. The fifthis the accessor-chain category. Keeping those sentences is deliberate, since a reader arriving at a
corrected entry needs to be told which class does not have the member; the count is recorded in
this PR's
README.mdso the next pass does not read 22 as 22 defects.Deliberately left undone, each with its issue: #970 (two API defects), #971 (the one
over-coverage finding still in the tree), #973 (the 44 unclaimed packages).
On
Libraries/. The two checks that read the pinned headers (--reverify-lane, themethod-attribution check, and the self-test) report SKIPPED rather than passing silently when
Libraries/OCCT.xcframeworkis absent, which is the normal case in CI. They were run here againsta symlinked xcframework, and
--reverify-lanereports278 classes, matching the pinned headers.