← back to Sample Followup Sweep
fix(fleet): fall back to contacts.json vendor name before the (vid X) placeholder
99d3128e7bdf51763fd242f01a66583258e89faa · 2026-09-22 11:31:34 -0700 · Steve Abrams
Display-only. build-fleet.js name expressions (both the group row and the
alias-stub map) rendered '(vid GREEN)' because GREEN isn't in the NAME map,
even though contacts.json has green -> 'Greenland (bmwallpaper)'. Now falls
back to the contacts name keyed by slug. Helps any vendor with a contacts
name. Regenerated fleet.json: GREEN row label fixed, its 13 items / vid /
slug / aliasVids UNCHANGED. No send, no FileMaker write, no re-attribution.
TK-12013
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBN9bgoXhsUaDnGkXU1T6m
Files touched
M data/fleet.jsonM scripts/build-fleet.js
Diff
commit 99d3128e7bdf51763fd242f01a66583258e89faa
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Sep 22 11:31:34 2026 -0700
fix(fleet): fall back to contacts.json vendor name before the (vid X) placeholder
Display-only. build-fleet.js name expressions (both the group row and the
alias-stub map) rendered '(vid GREEN)' because GREEN isn't in the NAME map,
even though contacts.json has green -> 'Greenland (bmwallpaper)'. Now falls
back to the contacts name keyed by slug. Helps any vendor with a contacts
name. Regenerated fleet.json: GREEN row label fixed, its 13 items / vid /
slug / aliasVids UNCHANGED. No send, no FileMaker write, no re-attribution.
TK-12013
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBN9bgoXhsUaDnGkXU1T6m
---
data/fleet.json | 38 +++++++++++++++++++-------------------
scripts/build-fleet.js | 9 +++++++--
2 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/data/fleet.json b/data/fleet.json
index 2e905e9..9425209 100644
--- a/data/fleet.json
+++ b/data/fleet.json
@@ -8,7 +8,7 @@
{
"slug": "green",
"vid": "GREEN",
- "name": "(vid GREEN)",
+ "name": "Greenland (bmwallpaper)",
"items": [
{
"mfr": "BX10180",
@@ -269,7 +269,7 @@
{
"slug": "ftr",
"vid": "FTR",
- "name": "(vid FTR)",
+ "name": "(unresolved) metallic-leaf vendor — GLM/GLMG SL08/B20 gunmetal/bronze/copper codes",
"items": [
{
"mfr": "SLO1-Multi 979",
@@ -477,7 +477,7 @@
{
"slug": "mdc",
"vid": "MDC",
- "name": "(vid mdc)",
+ "name": "MDC Wallcoverings",
"items": [
{
"mfr": "MSA6008",
@@ -605,7 +605,7 @@
{
"slug": "inn",
"vid": "INN",
- "name": "(vid inn)",
+ "name": "Innovations",
"items": [
{
"mfr": "AUR-04",
@@ -654,7 +654,7 @@
{
"slug": "astsand",
"vid": "ASTSAND",
- "name": "(vid ASTsand)",
+ "name": "Astek",
"items": [
{
"mfr": "wk110 - $20.90 net - 1/12/12)",
@@ -801,7 +801,7 @@
{
"slug": "san",
"vid": "SAN",
- "name": "(vid SAN)",
+ "name": "Sancar (AS Création) — inferred",
"items": [
{
"mfr": "871055",
@@ -850,7 +850,7 @@
{
"slug": "twi",
"vid": "TWI",
- "name": "(vid twi)",
+ "name": "twill (Karin Klein)",
"items": [
{
"mfr": "WP21400",
@@ -1016,7 +1016,7 @@
{
"slug": "1838-wallcoverings",
"vid": "1838",
- "name": "(vid 1838)",
+ "name": "1838 Wallcoverings",
"items": [
{
"mfr": "2008-143-06",
@@ -1116,7 +1116,7 @@
{
"slug": "vah",
"vid": "VAH",
- "name": "(vid VAH)",
+ "name": "Vahallan",
"items": [
{
"mfr": "Impression Camille",
@@ -1145,7 +1145,7 @@
{
"slug": "bar",
"vid": "BAR",
- "name": "(vid bar)",
+ "name": "Barneby Gates",
"items": [
{
"mfr": "Paisley - Hot Pink on Tea Stain",
@@ -1174,7 +1174,7 @@
{
"slug": "poi",
"vid": "POI",
- "name": "(vid POI)",
+ "name": "Pointe (via Justin David private label)",
"items": [
{
"mfr": "FIELDSTONETurfFieldstone",
@@ -1203,7 +1203,7 @@
{
"slug": "paul",
"vid": "PAUL",
- "name": "(vid PAUL)",
+ "name": "Paul Montgomery",
"items": [
{
"mfr": "CHM-KB1($239 net)",
@@ -1298,7 +1298,7 @@
{
"slug": "romo",
"vid": "ROMO",
- "name": "(vid romo)",
+ "name": "Romo",
"items": [
{
"mfr": "8086/04",
@@ -1374,7 +1374,7 @@
{
"slug": "thib",
"vid": "ANNA FRENCH",
- "name": "(vid ANNA FRENCH)",
+ "name": "Thibaut",
"items": [],
"count": 0,
"reReqCount": 0
@@ -1382,7 +1382,7 @@
{
"slug": "thib",
"vid": "ANNA",
- "name": "(vid ANNA)",
+ "name": "Thibaut",
"items": [],
"count": 0,
"reReqCount": 0
@@ -1390,7 +1390,7 @@
{
"slug": "arte-international",
"vid": "ARTE",
- "name": "(vid ARTE)",
+ "name": "Arte (@ Egg & Dart)",
"items": [],
"count": 0,
"reReqCount": 0
@@ -1398,7 +1398,7 @@
{
"slug": "san",
"vid": "AS CREATION",
- "name": "(vid AS CREATION)",
+ "name": "Sancar (AS Création) — inferred",
"items": [],
"count": 0,
"reReqCount": 0
@@ -1406,7 +1406,7 @@
{
"slug": "green",
"vid": "BM",
- "name": "(vid BM)",
+ "name": "Greenland (bmwallpaper)",
"items": [],
"count": 0,
"reReqCount": 0
@@ -1414,7 +1414,7 @@
{
"slug": "1838-wallcoverings",
"vid": "1838 WALLCOVERINGS",
- "name": "(vid 1838 WALLCOVERINGS)",
+ "name": "1838 Wallcoverings",
"items": [],
"count": 0,
"reReqCount": 0
diff --git a/scripts/build-fleet.js b/scripts/build-fleet.js
index ad48faf..6b7addb 100644
--- a/scripts/build-fleet.js
+++ b/scripts/build-fleet.js
@@ -5,6 +5,11 @@ const fs = require('fs');
const path = require('path');
// TK-11255: one shared routing table — see lib/slug-aliases.cjs for why.
const { SLUG_ALIASES, normVid, slugForVid } = require('../lib/slug-aliases.cjs');
+// Display-name fallback: a slug that carries a real vendor name in contacts.json should
+// render THAT name, not the ugly "(vid GREEN)" placeholder, whenever it isn't in NAME.
+// Display-only — never touches vid/items/aliasVids/attribution.
+let contacts = {};
+try { contacts = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'data', 'contacts.json'), 'utf8')); } catch { contacts = {}; }
const src = process.argv[2];
if (!src) { console.error('usage: node scripts/build-fleet.js <fm-result.txt>'); process.exit(1); }
@@ -53,7 +58,7 @@ for (const r of j.records) {
console.error(`intentional add '${vid}': '${slug}', to SLUG_ALIASES. Refusing to write fleet.json.`);
process.exit(1);
}
- g[slug] = g[slug] || { slug, vid, name: NAME[vid] || `(vid ${rawvid})`, items: [] };
+ g[slug] = g[slug] || { slug, vid, name: NAME[vid] || (contacts[slug] && contacts[slug].name) || `(vid ${rawvid})`, items: [] };
// Keep the aliased vid visible so stamping/reply-matching don't lose it.
if (String(g[slug].vid).toUpperCase() !== vid) {
g[slug].aliasVids = g[slug].aliasVids || [];
@@ -86,7 +91,7 @@ const vendors = Object.values(g).map(v => {
// own, so a rebuild cannot drop routing that a hand-edit used to supply.
const aliasStubs = Object.entries(SLUG_ALIASES)
.filter(([vid]) => !vendors.some((v) => String(v.vid).toUpperCase() === vid.toUpperCase()))
- .map(([vid, slug]) => ({ slug, vid, name: NAME[vid] || `(vid ${vid})`, items: [], count: 0, reReqCount: 0 }));
+ .map(([vid, slug]) => ({ slug, vid, name: NAME[vid] || (contacts[slug] && contacts[slug].name) || `(vid ${vid})`, items: [], count: 0, reReqCount: 0 }));
const allVendors = [...vendors, ...aliasStubs];
// Build-time guard: a slug may repeat ONLY through a declared alias. An undeclared
← 89f8650 refresh fleet.json from live FM sweep + declare 1838 WALLCOV
·
back to Sample Followup Sweep
·
auto-data-snapshot: 2026-09-22T12:15:47 (1 data files) — dat bf91abd →