Skills
TC Parent Child Rollup
Skill
tc-parent-child-rollup. Standing rule for authoring in Teamcenter - every object rolls up to a parent, and it must roll up through the carrier the DOCUMENTATION reads, not only the one the Relations tab reads. Covers which carrier each family needs, the two-carrier trap where having one looks like success, and how to verify rollup so a demo does not open on a flat list. Use before authoring any requirement, logical block, function, simulation request or verification request, and for any "why is the Content tab empty" or "why will Configurator not filter this" investigation.
Standing rule, set by Chris 2026-08-15. Nothing authored into Teamcenter is left loose. Requirements roll up to a Requirement Specification. Logical blocks and functions roll up to their parent. Simulation Requests and Verification Requests roll up to theirs. A flat list of correctly-typed objects is not a data model, and it is not what a customer is shown.
The rule has a second half that is easy to miss and is where the work actually is: the rollup must be visible in the DOCUMENTATION, not only in the Relations tab.
Run status: EXERCISED on vm2606 (TC 2606) 2026-08-15. Every state below was read back from a call.
★★ "Has a parent" means TWO different things, and one of them looks like success
This is the same two-carrier trap tc-requirement-spec-content documents for
specifications, generalised, because it applies to every family.
| carrier | what it drives | how to read it |
|---|---|---|
a GRM relation (IMAN_specification, Seg0Realize, Seg0Allocate, FND_TraceLink) |
Relations tab, Relations Tree and Graph, expandGRMRelations* |
getProperties(rev, ["<relation>"]) |
| occurrences in a structure | Content tab, Documentation panel, exports, trace link matrix, variant conditions, Product Configurator | structure_revisions non-empty, then getOccurrences4 |
They are independent. An object can be perfectly parented by relation and have zero occurrence structure. The Relations tab looks healthy, and the Content tab shows only a root node.
⇒ Before saying anything is or is not parented, read BOTH. One being empty tells you which half is missing, never that the object is loose.
★ The cheap tell: structure_revisions on the parent revision. Non-empty means a BOM
view exists and occurrences are possible. Empty means there is no structure to hang
anything in, and every occurrence-side reader will return nothing while every relation
reader returns everything.
The two instrument errors this trap produces, both real
- A BOM window plus
expandPSAllLevelsreturned 0 for a specification whose 22 requirements were correctly attached. That zero was reported as "this spec has no structure". It was an instrument error: the call reads occurrences and the requirements were onIMAN_specification. Nothing was wrong with the load. - The reverse also happens. A relation read comes back full and gets reported as "the structure is built", when the Content tab and any export are empty.
Both are the same mistake: one carrier read, two carriers assumed.
What each family needs
| Family | Parent | Relation carrier | Occurrences needed? |
|---|---|---|---|
| Requirement | Requirement Specification | IMAN_specification |
YES. Documentation panel, ReqIF/Word export, trace link matrix, variant conditions |
| Verification Requirement | its Verification spec | IMAN_specification |
YES, same reasons |
Logical block (Fnd0LogicalBlock) |
parent block, up to a system root | Seg0Realize |
yes for Content tab and Configurator; relation alone gives the graph but not the document |
Function (Functionality) |
a parent function or a function root | Seg0Realize for decomposition, Seg0Allocate to the realising block |
yes, same |
| Simulation Request, Verification Request | the item under verification | typed trace link (IAV0*) |
follow the family's own spec |
| Seg0 mission layer | mission to phases | Seg0MissionMadeupOfRel |
ordering needs a separate setProperties, see below |
★ createRelations cannot order anything. A mission built only from relations is a
SET, not a SEQUENCE. seg0PhaseOrder is written with the info/vecNameVal body
afterwards, and nothing warns you that the order is missing.
★★★ The verification family: THREE carriers, and two of them look like the answer
Measured on vm2606 2026-08-16 while auditing whether every family had a top node. The answer was yes, and I got it wrong twice first. Both wrong answers came from reading one carrier and assuming it was the only one, which is this skill's own trap turned on me.
| edge | carrier | notes |
|---|---|---|
| Verification Requirement -> its spec | occurrences | IMAN_specification on that spec reads 1, not 37. The relation carrier is not the one in use |
| Verification Request -> Verification Requirement | Crt0ValidationLink ("Analysis Request Link") |
NOT IMAN_specification, which reads 0 |
| Simulation Request -> its request | crt0ParentVldnContract on the child |
inverse is crt0ChildrenStudies on the request |
| Test -> its request | Crt0ValidationLink |
Crt0TestRevision has NO crt0ParentVldnContract |
★★ crt1OwningObject is a SELF-REFERENCE and it will fool you. It is called "Owning
Object", it was populated on 37 of 37 verification requests, and on all 37 it points at the
object itself. A property that is present everywhere and means nothing reads far more like
a parent than an empty one does. Compare the target uid to the object's own uid before
believing any "owning" property.
★★★ One family, two different parent carriers, and only the type descriptor says so.
Crt0SimStudyRevision has crt0ParentVldnContract; Crt0TestRevision does not. Writing it
anyway returned HTTP success with partial error 38015, Unable to find a property with name Crt0TestRevision/crt0ParentVldnContract. The call did not raise, and a read-back of
the property is what exposed 0 of 6 written.
⇒ Two rules fall out of that, and the second is the expensive one:
- Read
partialErrorson everysetProperties. The operation reports success at the call level while storing nothing, and this is the second time that has bitten in this workspace. - Do not reason from a sibling type. "Tests and Simulation Requests are the same
family, so the same property just was not set" was a confident, wrong diagnosis reported
to Chris before the descriptor was read. Diff the two types'
propertyDescriptorswhenever siblings behave differently, exactly astc-decision-managementrecords for<Type>CreIat create time.
How to place occurrences
Use tc-requirement-spec-content. Both calls are captured from Active Workspace and are
absent from the SOA kit: getOccurrences4 to open the structure and mint the runtime
ids, then addObject5 to place the object. parentElement and productContext are
SR:: runtime ids minted per session and cannot be hardcoded.
★★★ Verify from a SEPARATE PROCESS
Re-opening a structure after writing and counting children passes whether or not anything was committed, because the re-open runs in the same session and reads the same working context the writes were staged in. Committed and staged return identical counts. That produced a confident, wrong "verified by re-open" report.
⇒ A re-read is only independent if it crosses the boundary the write might not have crossed. For a session-scoped working context, that boundary is the PROCESS.
# session A
python spec_content.py --profile vm2606 --spec-rev <uid> --add-all
# session B, fresh login, different process
python -c "...open_structure(...)"
Two more silent successes in this area
- Adding an object that is already a child succeeds and changes nothing. No error, no partial error. A wrong "already present" test re-adds rows while the count refuses to move and every call reports OK.
displayNamecomes back numbered (1 VM-MSP2-SR-001-DYNAMIC), so an exact-set membership test against your own names classes every row as missing. Match on uid.
Why this is a rule and not a preference
Four things break when an object is parented by relation only, and all four are things a customer sees:
- The Documentation panel is empty or shows the root only. The demo opens on a flat list instead of a document with numbered paragraphs.
- Export is empty. ReqIF and Word walk occurrences.
- The trace link matrix comes back empty with no error. See
tc-traceability-matrix. - Variant conditions cannot be applied, so Product Configurator can never filter it.
⚠ This is the one that blocks silently and late:
setVariantExpressionson a Requirement returns79005 does not support the Variant Configurable Behavior, and conditioning the product structure instead needs a product structure with occurrences to condition. If there is none, there is nothing to configure and no error says so.
★ And the Documentation panel reads body_text, not object_desc. A requirement
whose real text is in object_desc renders whatever is in body_text instead, which on
a metadata-carrying load is a metadata string on every row. Copy the text into
body_text, do not swap: a swap moves the metadata into Description, which is worse.
The check to run before declaring a family done
getProperties(<parent revision>, ["<relation>", "structure_revisions", "<known-fake>"])
Carry a known-fake property in the same call. It separates "the property exists and is empty" from "the property is not returned at all", which is the difference between a missing link and a wrong property name.
Then, from a second process, count the occurrences. Report both numbers. A family is done when both carriers agree, and not before.
Related
tc-requirement-spec-content, tc-traceability-matrix, tc-relations-traceability,
tc-bom-structure, tc-object-authoring, tc-verify-and-cleanup,
diagnose-silent-failure.
Generated from skills/tc-parent-child-rollup/SKILL.md in the tc-automation-skills library, which is the canonical copy and also serves as the agent skill set for Teamcenter work.