Notes-Based Obsolescence Scan — Surfacing Hidden Obsolete Parts

Alex Walker flagged a recurring problem: AFTEC’s OBSOLETE flag is an incomplete signal. Many parts are de facto discontinued, but engineers only discover this when they read the free-text notes attached to the part. These notes — “use 053804 instead”, “AB obsoleted DC coil”, “no longer available” — are the real source of truth. This scan surfaces them at fleet scale.


The Problem

In PRODUCT records, AFTEC has an OBS flag (attribute 8, values O/I). That flag is supposed to signal obsolescence. In practice:

  • Engineers record obsolescence context in free-text notes on the PRODUCT.NOTES record, not by setting the OBS flag
  • The flag is set inconsistently — some truly obsolete parts have never been flagged
  • The notes are rich: they often name the replacement part, cite the vendor’s announcement, and explain the substitution reasoning
  • A BOM exploder looking only at the flag misses most of the real obsolescence

Concrete demonstration: of 530 (job, part) hits with unambiguous replacement language in the notes across the GKN El Cajon fleet, 368 had no OBS flag set. 69 % of the obsolescence is invisible to anything that only reads the flag.

The Scan

Method

For each job:

  1. Fetch BOM via GET /api/bom/dev/job/{job} — recursive explode, unique parts
  2. Batch read PRODUCT.NOTES for all unique parts via POST /api/data/dev/PRODUCT.NOTES/batch
  3. Regex-scan the concatenated notes text for replacement language (discontinued, no longer available, use {part#}, replaced by, superseded, substitute, etc.)
  4. For parts that matched, batch read PRODUCT to check the OBS flag
  5. Enrich hits with manufacturer code and design category via /api/manufacturer/dev/by-part/{pn}
  6. Produce Excel report: one sheet for hidden obsolescence (no OBS flag), one sheet for all hits

Source: PSI.UniData.API/pipeline/notes_obsolescence_scan_batch.py

The batch endpoint

The per-part version of this scan (sequentially calling GET /api/data/dev/PRODUCT.NOTES/1!{pn} for each of ~7,000 parts across 8 machines) ran for 4+ hours before UniData session pool exhaustion jammed the API server. Full details in the deployment/ops lessons section below.

The batch endpoint (POST /api/data/dev/{table}/batch, added in commit cd2e08f) opens one UniData session and reuses the file handle for up to 5,000 key reads per call. The same scan with the batch endpoint:

PhasePer-part scanBatch scan
BOM fetches (8 jobs)~3 min~3 s
PRODUCT.NOTES reads (5,447 keys)~2 h (est.)8.1 s (3 batches × 2-3s)
PRODUCT OBS-flag reads (264 keys)~15 s0.2 s
Manufacturer enrichment (264 hits)~15 s~15 s (still per-part)
Total wall clockNever completed91.9 s

Batch is ~150× faster on the UniData-heavy phases. The remaining bottleneck is manufacturer enrichment — an obvious candidate for a batch MFG endpoint next.

Scope — GKN Aerospace El Cajon Fleet

Eight active machines at GKN’s El Cajon facility:

JobDescriptionUnique parts
1382Fan Blade Peener (roots & foils)924
1383Glass Bead Suction Foil Peen1,019
1384Robotic Shot Peen for Roots and Discs1,634
1795CITS Monitor JetKote III175
1836Std Robot Peen1,939
1962Suction Fan Blade Peen1,200
2096Robotic Shot Peen System2,175
2280IBR Shot Peen1,954
Total5,447 unique

Data quality gotcha — Jobs 1795, 1836, and 1962 have empty CUSTOMER.NO in PROJECT.1287 but are linked to GKN El Cajon via ACCOUNT.NO=0397. Any customer search using only CUSTOMER.NO misses them. See AFTEC Customer Fields.

Top-Line Results

MetricValue
Unique parts scanned5,447
Parts with any PRODUCT.NOTES text987
Parts where notes contained replacement language264
Total (job, part) hits (deduped appearances)530
Already correctly OBS-flagged162
Hidden obsolete — notes say replaced, NO OBS flag368

The 368 hidden-obsolete (job, part) pairs represent ~160 unique parts repeated across the eight machines. Several are used in six or more of the eight machines.

Findings by Category

1. Allen Bradley 100-C Contactor “DC coil renaming” (systemic)

A cluster of identically-worded notes dated 2012-11-06 by JDP:

AB obsoleted DC coil.  "EJ" was "ZJ".  Same footprint [...]

Affected parts:

PartDescription
037903100-C23EJ10 24VDC 15HP contactor
037944700-CF310EJ 24VDC relay 3 N.O. / 1 N.C.
037894100-C09EJ10 24VDC 5HP contactor
038878100-C23EJ400 24VDC 15HP 4-pole
045412100-C43EJ10 24VDC 30HP
039315100-C16EJ10 24VDC 10HP
037945700-CF400EJ 24VDC relay 4 N.O.

Significance: These are the everyday motor contactors on GKN’s robotic peeners. The old “ZJ” coils are gone; the “EJ” replacement is a direct drop-in but the renaming was never reflected with an OBS flag on the old part numbers. Engineers ordering from legacy prints may still specify “ZJ” variants.

2. Allen Bradley 193-1E Overload Relays (E1 Plus line discontinued)

Cluster dated 2021-02-02 by JDP:

"-1EFBB" was "-EEBB" (AB discontinued old E1 Plus line)

Affected parts:

PartDescription
051839193-1EFBB overload, 0.2-1.0 A
048766193-1EFCB overload, 1.0-5.0 A
048767193-1EFDB overload, 3.2-16 A
048768193-1EFEB overload, 5.4-27 A
050245193-1EPB DIN rail adapter

Significance: Every AB overload relay on GKN machines is affected. The replacements are in stock under the new part numbers but the old numbers are still cited on drawings.

3. Allen Bradley 2098 Drive / F-4030 & F-4050 Servo System (retrofit-required)

Available from Elwood, but AB has discontinued 2098 drive.
We should now be [using Kinetix]
PartDescription
026942F-4030-Q-H00AA 4000 RPM servo motor
026481F-4050-Q-H00AN 4000 RPM servo motor with 56C face
050616Y-1003-1-H00AA 115V servo motor
0469732090-U3BB2-DM44 drive-mounted breakout board (non-SERCOS)
0513462090-XXNPY-16S25 25 m power cable (no replacement)

Significance: This is not a cosmetic relabel — the 2098 platform is end-of-life. Any GKN machine still running 2098 servo drives is on borrowed time. Cable part 051346 has no replacement per Rockwell — machines with long power runs may be stranded. Retrofit to Kinetix is the recommended path; this may warrant its own engineering proposal.

4. Grove Gear Reducers — “Gold and Enviroseal no longer available”

Cluster dated 2015-07-28 by SA:

GOLD AND ENVIROSEAL  ARE NO LONGER AVAILABLE.
ORDER ALL GROVE GEAR [standard finish]
PartDescription
039703DHMQ-220-75-1.4375-56C-PV reducer
040624GR-JMQ-826-60-L-56-PV reducer
018741HMQ-220-80-1-1.4375-56C-PV reducer 1-7/16” bore
062554GR-FHMQ818-7.5-HL-56-16 reducer 1” bore

Significance: Not a functional obsolescence; the Gold and Enviroseal surface treatments are discontinued but the underlying reducers remain available. Spares ordering just needs to drop the finish code.

5. Lumberg → Remeke Connector/Cable Equivalents

At least a dozen Lumberg proximity-cable part numbers with identical notes:

Use 0xxxxx for Remeke equivalent.

Examples: 042618, 043931, 045410, 040161, 041026, 043930, 047891, 056820, 056821, 037333, 037894

Significance: PSI has a dual-source strategy — Lumberg is preferred but Remeke is the drop-in. Neither the Lumberg nor the Remeke part is OBS-flagged, so this shows up only in notes. Knowing the equivalence pair is valuable for spares cost optimization (Remeke is often cheaper).

6. FANUC A98L-0031-0025 Battery — fully obsolete

GEF said parts is now obsolete. New battery and new style case [required]

Single part: 038481 — A98L-0031-0025 lithium 6V battery.

Significance: Every FANUC-controlled GKN machine that uses this battery for CMOS/memory backup is at risk. The replacement is a different form factor — replacing it is not drop-in, requires the new case. This is worth a proactive customer-advisory communication.

7. PTI Physical-Level Parts (internal supersessions)

Many PTI-manufactured physical parts (part numbers 7xxxxx, 8xxxxx, 9xxxxx) carry “use [newer PTI part] instead” notes:

Old→ NewReason
713501 SWECO (30”, 3D4”, POLY)910249 with stiff bootshigh-vacuum applications
785155 Suction feeder tube102412not recommended for grit
816453 Rubber lining (std robotic)884069cabinets 80”×53” without grating
884069 Rubber lining (80×53 std robotic)909465cabinets with grating
903071 Rotary lance drive (RLD500)931681latest motor version
865946 Z-axis carriage subassy(replacement noted)junction box (786235) obsoleted
883288 BNS-819 switch/conn L.H.221197 for R.H.connector handedness
805104 Media hopper weldment277314updated weldment
805103 Virgin hopper side271026 + barsinternal revision

Significance: These are engineering internal supersessions, not vendor obsolescence. They don’t impact customer spares orders (both old and new numbers remain valid), but they matter for new-build BOMs — using the old part number pulls an outdated subassembly into the build.

8. Long Tail — One-Off Vendor Substitutions

The remaining ~250 hidden-obsolete hits are one-offs:

  • Schmersal safety switch 031814 — plastic adapter replaced by 045682
  • Hoffman barrier kit F-44BK60 (005130) — use 057766
  • Phoenix receptacle 047482 — obsoleted 2019
  • Hilti KBTZ2 anchor (054689) — discontinued, use KBTZ2
  • Ashcroft gauge 010406 — use 047734 instead
  • Parker 95U-6-062 polyurethane tubing (033735) — obsolete per Parker’s website
  • Marsh gauge 011681 — use 047733
  • Clemco blast hose coupling 046359 — use 055273 for Plicord
  • Enidine shock 002983 — OEM-1.0 obsoleted by vendor
  • McMaster hardware — many small items where supplier changed

Each alone is modest impact. Collectively they represent hundreds of lines of uncoded institutional knowledge.

Implications

For engineering

  • Treat PRODUCT.NOTES as load-bearing. The OBS flag is advisory at best; the real obsolescence status lives in notes. Any tooling that reads AFTEC for component selection must read notes.
  • Update the OBS flag for the 368 (job, part) hidden-obsolete hits so the flag becomes reliable over time. This is a one-shot data cleanup — the spreadsheet has the list.
  • New PTI supersessions (section 7) should be propagated to active BOMs where the old part is still referenced. Roll-forward policy TBD.

For spares / customer service

  • GKN El Cajon spares orders should default to the replacement part unless the customer explicitly requests the original. The spreadsheet is a quote-time cheat sheet.
  • FANUC A98L battery needs a proactive customer advisory — the replacement is not drop-in.
  • AB 2098 servo drives need retrofit planning for affected machines (026942 / 026481 / 050616 are the signal parts).

For tooling (MCP/API)

  • Add a field to the obsolete-parts search response that includes the first replacement-language phrase from the notes, so tool users see the context without another API call.
  • Consider a batch manufacturer-lookup endpoint to close out the remaining ~15s enrichment phase.
  • The regex approach is fast and effective. An AI-augmented pass (Azure OpenAI over regex hits) could additionally extract the replacement part number as structured data — a GPT 5.4 Mini trial on three GKN jobs identified explicit replacement parts for 208 of 256 AI-identified hits. That’s the natural next step.

Operational Lessons

This run surfaced two ops issues worth recording.

UniData session-pool exhaustion

The per-part version of this scan leaked UniData sessions at scale. The first attempt made ~7,000 sequential GET /api/data/dev/PRODUCT.NOTES/{id} calls across six machines over ~4 hours. Eventually every UniData endpoint began returning HTTP 000 (connection timeout). Cause: DataQueryService opens a session per call, and under sustained sequential load, session cleanup was not keeping up. A Restart-Service PSI.UniData.API on PS-PROXY cleared the condition.

Fix: The batch endpoint (one session per batch of up to 5,000 reads) is both much faster and exerts far less pressure on the session pool. Going forward, any “read many records” workload should use batch, not iterate.

Follow-ups:

  • Audit DataQueryService session lifecycle under exception paths
  • Add a semaphore on concurrent UniData operations
  • Add a deep health check (/api/health/deep) that reads a real record with a short timeout, and an external watchdog on PS-PROXY that restarts the service if deep-health fails twice consecutively

GitHub Actions self-hosted runner required interactive session

Deploying the batch endpoint sat queued for over an hour until someone logged into PS-PROXY. The GitHub Actions runner service should run unattended. Likely mis-configured as a console app or service without the required “Log on as a service” rights. Runner needs to be reinstalled with --unattended or have its service account rights fixed.

Next Steps

  1. Populate OBS flags for the 368 identified hidden-obsolete (job, part) hits — one-time data update via AFTEC.
  2. Apply the same scan to other high-value fleets (e.g., AB 9/Series CNC machines from the CNC obsolescence analysis).
  3. Build a batch manufacturer-lookup endpoint — closes the 15 s enrichment gap.
  4. AI-augmented pass — run Azure OpenAI over the regex hits to extract structured replacement-part mappings.
  5. Automate it — nightly scan of recently-edited BOMs, flag new hidden-obsolete hits in a Redbook-style queue.