TeamcenterKnowledge

Skills

TC Requirement Spec Content

Skill tc-requirement-spec-content. Put requirements INSIDE a Teamcenter specification so Active Workspace, the Content tab, exports and Product Configurator can all see them. Covers the two different things "in a spec" can mean and why having only one of them looks like success, the two undocumented Active Workspace calls that actually place content (getOccurrences4 then addObject5), the five payload members whose absence returns a fault naming nothing, and the verification mistake that makes an unpersisted structure report as built. Use whenever authoring requirements, verification requirements or any spec content, and before any trace link matrix or variant work.

Standard practice: a requirement is authored INTO a specification, never left loose. A requirement outside a spec has no document position, no numbering, cannot be exported to Word or ReqIF, cannot be baselined as a deliverable, and, the one that silently kills downstream work, cannot carry variant conditions, so Product Configurator can never filter it. Treat "which specification does this go in" as part of creating a requirement, not as a later tidy-up.

Run status: EXERCISED on vm2606 (TC 2606) 2026-08-15. Every claim below came back from a call. Reference implementation: se-process-skills/demos/jpo-f35/ stage1b-verification-matrix/spec_content.py.


★★ "In a spec" means TWO different things, and having one looks like success

carrier what it drives how to read it
IMAN_specification relation Relations tab, Relations Tree/Graph getProperties(specRev, ["IMAN_specification"])
occurrences in the spec structure Content tab, exports, trace link matrix, variant conditions getOccurrences4 (below)

They are independent. A specification can have all its requirements attached by IMAN_specification and zero occurrences: the Relations tab looks perfectly healthy, the Content tab shows only the root node, and a Full-Rollup trace link matrix comes back empty.

That exact state existed on a demo tier for two days and was read three different wrong ways before anyone looked at both carriers:

  • A BOM window plus expandPSAllLevels returned 0 for a spec that had 22 requirements correctly attached. That zero was reported as "this spec has no structure", which was an instrument error, not a fact.
  • Later the same spec reported 22 from the same call. The reading changed; the data had not.

Before concluding anything about spec content, read BOTH carriers. One of them being empty tells you which half is missing, not that the spec is empty.


The two calls that place content

Neither is in the SOA WSDL/SDK kit. Both were captured from Active Workspace's own traffic (see tc-capture-awc-calls) and then replayed headlessly.

1. Open the structure and mint the runtime ids

Internal-ActiveWorkspaceBom-2022-06-OccurrenceManagement/getOccurrences4

The only member that identifies the spec is inputData.product.uid, which is the spec REVISION. Everything else is defaults and NULLTAGs, and every NULLTAG is required: omitting them returns 214022 JSON parsing naming nothing.

{"inputData": {
  "config": {"effectivityDate":"0001-01-01T00:00:00","unitNo":-1,
             "productContext":NT,"revisionRule":NT,"occurrenceScheme":NT,
             "sourceContext":NT,"changeContext":NT,"appliedArrangement":NT,
             "closureRule":NT,"viewType":NT,"serializedRevRule":"",
             "effectivityGroups":[],"endItem":NT,
             "variantRules":[],                 <-- the Product Configurator slot
             "svrOwningProduct":NT,"effectivityRanges":[]},
  "cursor": {"startReached":false,"endReached":false,"startIndex":0,"endIndex":0,
             "pageSize":250,"startOccUid":"","endOccUid":"","cursorData":[]},
  "focusOccurrenceInput": {"element":NT,"cloneStableIdChain":""},
  "filter": {"searchFilterCategories":[],"searchFilterMap":{},
             "fetchUpdatedFilters":false,"recipe":[],
             "searchFilterFieldSortType":"Priority","searchSortCriteria":[]},
  "requestPref": {"expandedNodes":[],"includePath":["true"],
                  "loadTreeHierarchyThreshold":["50"],"savedSessionMode":["ignore"],
                  "startFreshNavigation":["true"],"displayMode":["Tree"],
                  "showExplodedLines":["false"],"calculateFilters":["false"],
                  "viewType":[""],"useGlobalRevRule":["false"],
                  "defaultClientScopeUri":["Awb0OccurrenceManagement"]},
  "expansionCriteria": {"expandBelow":false,"levelNExpand":0,
                        "loadTreeHierarchyThreshold":0,"scopeForExpandBelow":""},
  "sortCriteria": {"propertyName":"","sortingOrder":""},
  "product": {"uid":"<spec REVISION uid>"},
  "parentElement": "AAAAAAAAAAAAAA"        <-- a bare STRING, not an object
}}

Response keys, pinned off a real 200 because the XSD does not declare them. Four plausible guesses at these names were all wrong:

you want it is called
root element SR:: uid parentOccurrence.occurrenceId
product context SR:: uid rootProductContext.uid
the children AW displays parentChildrenInfos[].childrenInfo[]

2. Place the object

Internal-ActiveWorkspaceBom-2025-06-OccurrenceManagement/addObject5

{"input": {
  "addObjectIntent": "", "numberOfElements": 1, "fetchPagedOccurrences": true,
  "sortCriteria": {"propertyName":"","sortingOrder":""},
  "requestPrefMap": {"defaultClientScopeUri":["Awb0OccurrenceManagement"],
                     "displayMode":["Tree"],"structExpanded":["true"]},
  "addObjectParentChildrenList": [{
    "parentElement":  {"uid":"<parentOccurrence.occurrenceId>",
                       "type":"Arm0RequirementSpecElement"},
    "siblingElement": NT, "actualParent": NT,
    "productContext": {"uid":"<rootProductContext.uid>",
                       "type":"Awb0ProductContextInfo"},
    "structExpanded": true,
    "objectsToAddList": [{
      "createInput": {"boName":" ","propertyNameValues":{},"compoundCreateInput":{}},
      "objectToAdd": {"uid":"<the REVISION to place>","type":"<its type>"}}]}]}}

★★ Those five siblings of addObjectParentChildrenList are NOT optional. A first capture truncated them away; sending only the list returns 214022 JSON parsing, which names nothing and reads like a malformed list.

parentElement and productContext are SR:: runtime ids, not database uids. They are minted per session by call 1 and cannot be constructed, guessed, or reused from an earlier run. A script that hardcodes one works once and then fails in a way that looks like a permissions problem.


★★★ Verify from a SEPARATE PROCESS, not a second call

This is the mistake worth the whole skill.

Re-opening the structure after the writes and counting the 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 "37 children, verified by re-open" report. The correct check is a new process with its own login:

python spec_content.py --profile vm2606 --spec-rev <uid> --add-all   # session A
python -c "...open_structure(...)"                                   # session B, fresh login

⇒ Generalise it: 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, not the call.


Other things that return success and do nothing

  • Adding an object that is already a child succeeds silently and changes nothing. No error, no partial error. If your "already present" test is wrong you will re-add the same rows and the count will refuse to move while every call reports OK.
  • displayName comes back numbered (1 VM-MSP2-SR-001-DYNAMIC), so an exact-set membership test against your own names classes every row as missing. Substring match, or compare on the underlying uid.
  • tc_find_items only runs the Item Name saved query. A RequirementSpec has no naming rule, so its id lives in item_id and a name lookup returns a bare nFound 0 that reads as "no such object". Run the Item ID query too.

★★ A multi-property write fails as a UNIT and still reports success

setProperties sending four properties in one call, with one of them over its maxLength, returned success, no partial errors, and stored NONE of the four. The property that mattered silently kept its previous value.

The symptom is a read-back that disagrees intermittently, which looks exactly like a caching or replication lag, and treating it as one is the wrong fix. Measured on vm2606 2026-08-15: three description strings at 134 to 145 characters against a cap of 128 took the whole update down with them.

Checking the property you care about is not enough. Check every property in the same call, before writing, against caps read off the tier. And when a read-back disagrees, rule out a rejected write before reaching for "it must be cached".

Text fields truncate silently

object_desc on a requirement revision is 240 characters; the verification assessment form's iav0VerifApproach is 240 and iav0VerifMethodDesc is 128. Over-long text is cut without an error and a truncated description still looks like a description. Read maxLength from getTypeDescriptions2 and check the composed string before writing. enrich_rows.py in the reference implementation does this and refuses the run.

★★ A multi-item addObject5 call can silently double-write

Measured on vm2606, 2026-08-16: one addObject5 call placing two objects in a single objectsToAddList array (both under one addObjectParentChildrenList entry) reported numChildredAdded: 2 but actually created four occurrences — two of each object, the second pair's displayName suffixed " x2" (Teamcenter's own duplicate-disambiguation naming). The response itself hinted at this (newElementInfos came back as two separate groups, each listing both objects) but was ambiguous enough that trusting it at face value would have reported success on broken data. Independently confirmed as real, committed duplication — not a same-session display artifact — via getOccurrences4 from a fresh session (numberOfChildren: 4) and cross-checked a second, independent way with the raw BOM-window path (createOrReConfigureBOMWindows + expandPSAllLevels), which also returned 4 distinct Fnd0RequirementBOMLine children.

After any multi-item addObject5 call, verify the raw occurrence count with a second instrument (the BOM-window path below), not just by trusting numChildredAdded or re-reading getOccurrences4 in the same session. If in doubt, add objects one at a time in separate calls rather than batching multiple items into one objectsToAddList.

Removing a duplicate or wrong occurrence

Spec structure is BOM occurrence structure under the hood, so the ordinary physical-structure removal call from tc-bom-structure applies unmodified to Fnd0RequirementBOMLine occurrences:

Bom-2008-06-StructureManagement/removeChildrenFromParentLine
{"bomlines":[{"uid":"<child BOMLine uid>","type":"BOMLine"}, ...]}

Takes the child occurrence BOMLine uid(s) directly, not the parent. Get those uids from a BOM-window expandPSAllLevels read (below), not from the SR:: runtime ids getOccurrences4/addObject5 use — they're a different id space. Must be followed by Cad-2008-06-StructureManagement/saveBOMWindows to commit (unsaved changes survive a reopen in the same window pool but are not durable — the same trap the tc-bom-structure skill documents for ordinary structure) and closeBOMWindows to release the window. Verify by last_mod_date on the parent item/revision advancing, and by re-reading occurrence count from a fresh session afterward — same discipline as the write itself.

Cross-checking getOccurrences4 with the raw BOM-window path, used both to catch the duplication above and to confirm the fix:

Cad-2019-06-StructureManagement/createOrReConfigureBOMWindows
{"input":[{"clientId":"win1","item":{"uid":"<spec revision uid>","type":"RequirementSpec Revision"},"bomViewType":""}]}

then Cad-2007-01-StructureManagement/expandPSAllLevels on the returned window line. ⚠ A malformed shape here returns output: [], which reads exactly like "structure genuinely empty" — before trusting an empty result, confirm the payload shape against a call that's already worked in the same session, don't conclude absence from one attempt.

★★ On TC 2512 the child rows carry NO underlying object uid. Only displayName.

EXERCISED 2026-09-02 on sgt-demo-sandbox.plmfederal.com (Teamcenter 2512, 25120.2603), placing 32 requirements into spec 034666. The recipe above worked unchanged, including every NULLTAG, so this is an addition rather than a correction.

The note above says to match "on displayName substring, or compare on the underlying uid". On this tier the second option does not exist. A getOccurrences4 child row is exactly this and nothing more:

{"occurrenceId": "SR::N::Arm0RequirementElement..Fnd0RequirementBOMLine..9....",
 "stableId": "<specRevUid>:<occUid>",
 "displayName": "1 CS-01 Crane hook attachment, single lifting eye on centreline",
 "numberOfChildren": 0,
 "underlyingObjectType": "Requirement Revision",
 "position": 32,
 "occurrence": {"uid": "AAAAAAAAAAAAAA", "className": "unknownClass", ...}}

occurrence.uid is NULLTAG, and there is no underlyingObjectUid member at all. stableId is specRev:occurrence, not specRev:requirementRevision, so it does not give you the object either.

The failure this produces looks like data loss, not like an instrument fault. A verifier that harvests uids from these rows collects one value, AAAAAAAAAAAAAA, and then reports present=0 missing=32 for a structure that is completely correct. That happened here on the first verification run, immediately after 32 successful adds, and the two numbers sitting side by side in the same output (children=32 and missing=32) are what exposed it. Had the run placed nothing, the same code would have printed the same missing=32, so that verifier could not distinguish total success from total failure.

⇒ Two rules fall out:

  1. Match on displayName substring, and treat the uid path as unavailable unless you have confirmed on your tier that a uid is actually populated. Remember the number prefix: "1 CS-01 ...", so label in name, never name == label.
  2. Cross-check identity through the BOM-window path, which uses a different id space and does carry real ids. bl_item_item_id on the child occurrence lines returned REQ-002825 .. REQ-002856, 32 distinct, 0 missing, 0 unexpected. That is the check that proves the things in the spec are your objects rather than 32 of something else, which displayName matching alone only makes likely.

★ Run the verifier before the writes as well. A baseline run here reported 0 by both instruments, which proved the instruments could return a number at all and made the after-state attributable to the writes. A verifier that has only ever been run against the expected answer has not been tested.

Related

tc-capture-awc-calls (how both calls were obtained), tc-traceability-matrix (what the occurrences are for), tc-object-authoring, tc-verify-and-cleanup, tc-bom-structure (the removal call and BOM-window cross-check both come from here), diagnose-silent-failure.


Generated from skills/tc-requirement-spec-content/SKILL.md in the tc-automation-skills library, which is the canonical copy and also serves as the agent skill set for Teamcenter work.