Project Data Persistence Architecture

Created: April 9, 2026 Status: Implementation in progress Bugs: 103 (export naming mismatch), 104 (persistence gap) DFMEA: 039 (RPN 210), 040 (RPN 400)

Problem Statement

The Project Details dialog (projdet_edit in projdet.lsp) captures 21 user-entered values into AutoLISP runtime globals but never writes them to persistent storage. All values except 5 partial title-block-backed fields are lost when AutoCAD closes. The PB11 VLX has compiled persistence code that does not exist in the TB11 source tree — same class of VLX/source mismatch as the progcont routing gap (DFMEA-013).

A secondary problem compounds this: the cvxpproj.lsp validation export script probes the wrong global names for 19 of 21 fields, silently exporting null even when the data is in memory.


Variable Lifecycle — Parity Matrix

This table maps every project detail variable across all 5 touch points in the system. The naming mismatch between projdet_edit globals (columns 3-4) and cvxpproj.lsp probes (column 5) is the Bug 103 root cause. The empty “XRecord Key” column (column 7) is the Bug 104 root cause — no XRecord storage exists.

#

DCL Key

projdet_edit WRITES global

projdet_edit READS global

cvxpproj.lsp PROBES (pre-fix)

Title Block Tag

XRecord Key (new project_list)

1

concpsi

concpsi (bare)

concpsi (bare, default “4000”)

concpsi

concpsi

2

concpcf

concpcf (bare)

concpcf (bare, default “150”)

concpcf

concpcf

3

bldgname

csv_bldgname

csv_bldgname

bldgname

bldgname

4

projloc

csv_projloc

csv_projloc (bridged ← mplo)

projloc

LOmplocsv_projloc

projloc

5

contractor

csv_contractor

csv_contractor (bridged ← mpco)

contractor

CONmpcocsv_contractor

contractor

6

super

csv_super

csv_super

super

super

7

city

csv_city

csv_city

— (only csz composite)

Parsed from ADD2

city

8

state

csv_state

csv_state

— (only csz composite)

Parsed from ADD2

state

9

zip

csv_zip

csv_zip

— (only csz composite)

Parsed from ADD2

zip

10

(computed)

csv_csz

csz

ADD2 raw value

csz

11

phsite

csv_phsite

csv_phsite

phsite

phsite

12

phoffice

csv_phoffice

csv_phoffice

phoffice

phoffice

13

fxsite

csv_fxsite

csv_fxsite

fxsite

fxsite

14

fxoffice

csv_fxoffice

csv_fxoffice

fxoffice

fxoffice

15

email

csv_email

csv_email

email

email

16

addr1

csv_addr1

csv_addr1

addr1

ADD1csv_addr1

addr1

17

addr2

csv_addr2

csv_addr2

addr2

addr2

18

metric/imperial

csv_msys

csv_msys

msys

msys

19

p8/p16

csv_dprec

csv_dprec

dprec

dprec

20

english/espanol

csv_lang

csv_lang

lang

lang

21

s8x11/etc.

csv_ppsize

csv_ppsize

ppsize

ppsize

Naming Convention

  • Bare names (concpsi, concpcf): Used by projdet_edit for the two concrete strength fields. Also used as XRecord keys and export keys.

  • csv_-prefixed names (csv_super, csv_dprec, etc.): Used by projdet_edit for the remaining 19 fields. The csv_ prefix is a runtime global naming convention — it does NOT appear in XRecord keys or export keys.

  • mp-prefixed names (mpco, mplo): Panel-domain globals that bridge to project globals via csvcompat.lsp’s title block reader. mpcocsv_contractor, mplocsv_projloc.

  • Short export names (cn, nm, sa, ct, st, zp, ph, fx, em): Used by dreng.lsp for engineering .pdx export. Initialization code is in compiled VLX only — out of scope for this implementation.


Data Source Priority Hierarchy

When projdet_edit() opens, it populates dialog fields from multiple sources in this priority order. Each source only fills values that are still at default (empty/space/nil) — it never clobbers data set by a higher-priority source.

1. NOD XRecord "project_list"     ← NEW (this implementation)
   │  Highest priority. Reads DXF 1/2/3 triplets from Named Object Dictionary.
   │  Sets all 21 globals directly. Only fires if project_list exists.
   │
2. Title Block ATTRIBs            ← EXISTING (titleblk.lsp / csv_read-title-block)
   │  Reads INSERT "title" entity attributes:
   │    CON tag → mpco → csv_contractor
   │    LO  tag → mplo → csv_projloc
   │    ADD1 tag → csv_addr1
   │    ADD2 tag → csv_city, csv_state, csv_zip, csv_csz
   │  Only covers 5 of 21 fields.
   │
3. Runtime globals                ← EXISTING (in-memory from prior dialog interaction)
   │  Values set by previous projdet_edit accept callback in current session.
   │  Volatile — lost when AutoCAD closes.
   │
4. Hardcoded defaults             ← EXISTING (convert.lsp / projdet.lsp)
      concpsi = "4000", concpcf = "150"
      All others = " " (space) or empty

Design: project_list NOD Dictionary

Why a Separate Dictionary Key

Project details are per-drawing/per-project metadata, not per-panel geometry. The existing panel_list and site_list dictionaries store panel and site geometry variables (21 panelvar sections × ~400 variables, 5 sitevar sections × ~50 variables). Mixing project metadata into panel_list would:

  1. Break the conceptual model — project details (contractor, phones, email) are not panel features

  2. Cause redundant writespanel.lsp’s save loop iterates all panelvar sections; adding pdvar means every panel save writes project data

  3. Mismatch VLX behavior — the VLX uses a separate persistence mechanism for project data (not identified in source, but demonstrably separate from panel/site XRecord)

XRecord Format

The project_list XRecord uses the same DXF code convention as panel_list / site_list:

Header codes (one occurrence each):
  DXF 3 = CV version string (e.g., "11.01")
  DXF 4 = project name (from pjname global)
  DXF 6 = panel prefix (from pnlname global)
  DXF 7 = date code (Julian date string)

Body codes (repeated for each variable, 21 triplets):
  DXF 1 = section name ("pdvar" for all entries)
  DXF 2 = variable key (bare name, e.g., "concpsi", "super", "dprec")
  DXF 3 = variable value (string, e.g., "4000", "John Smith", "p16")

Variable Defaults

;; pdvar section definition (added to convert.lsp)
;; 21 variables with factory defaults
(list "pdvar"
  (cons "concpsi"    "4000")      ; Concrete strength (psi)
  (cons "concpcf"    "150")       ; Concrete unit weight (pcf)
  (cons "bldgname"   " ")         ; Building name
  (cons "projloc"    " ")         ; Project location
  (cons "contractor" " ")         ; Contractor name
  (cons "super"      " ")         ; Superintendent name
  (cons "city"       " ")         ; City
  (cons "state"      " ")         ; State
  (cons "zip"        " ")         ; Zip code
  (cons "csz"        " ")         ; City/State/Zip composite
  (cons "phsite"     " ")         ; Phone (site)
  (cons "phoffice"   " ")         ; Phone (office)
  (cons "fxsite"     " ")         ; Fax (site)
  (cons "fxoffice"   " ")         ; Fax (office)
  (cons "email"      " ")         ; Email
  (cons "addr1"      " ")         ; Address line 1
  (cons "addr2"      " ")         ; Address line 2
  (cons "msys"       "imperial")  ; Measurement system
  (cons "dprec"      "p8")        ; Decimal precision (1/8")
  (cons "lang"       "english")   ; Language
  (cons "ppsize"     "s8x11")    ; Page/print size
)

Global-to-XRecord Mapping

The write function maps csv_-prefixed runtime globals to bare XRecord keys:

Runtime Global

XRecord Key

Direction

concpsi

concpsi

bare → bare

concpcf

concpcf

bare → bare

csv_bldgname

bldgname

csv_ → bare

csv_projloc

projloc

csv_ → bare

csv_contractor

contractor

csv_ → bare

csv_super

super

csv_ → bare

csv_city

city

csv_ → bare

csv_state

state

csv_ → bare

csv_zip

zip

csv_ → bare

csv_csz

csz

csv_ → bare

csv_phsite

phsite

csv_ → bare

csv_phoffice

phoffice

csv_ → bare

csv_fxsite

fxsite

csv_ → bare

csv_fxoffice

fxoffice

csv_ → bare

csv_email

email

csv_ → bare

csv_addr1

addr1

csv_ → bare

csv_addr2

addr2

csv_ → bare

csv_msys

msys

csv_ → bare

csv_dprec

dprec

csv_ → bare

csv_lang

lang

csv_ → bare

csv_ppsize

ppsize

csv_ → bare


Implementation Files

File

Change

Phase

scripts/validation-lsp/cvxpproj.lsp

Fix cvxp-snapshot-globals naming mismatch (Bug 103)

2

src/x32/TB11-01x32/convert.lsp

Add pdvar section definition (21 vars + defaults)

3a

src/x32/TB11-01x32/projdet.lsp

Add csv_write-project-xrecord + csv_read-project-xrecord

3b, 3c

src/x32/TB11-01x32/csvmenu.lsp

Wire csv_read-project-xrecord into startup chain

3d

src/x32/TB11-01x32/csv_diag.lsp

Add project_list/project dictionary probe

4c

scripts/validation-lsp/cvxpproj.lsp

Add project XRecord probe + body parse

4a

scripts/validation-lsp/cvxpproj.schema.json

Add project XRecord header/body schema definition

4b


Backward Compatibility

  • PB11 drawings (VLX-era): Have title block ATTRIBs but no project_list in NOD. The csv_read-project-xrecord function returns nil → existing title block fallback fires → contractor, location, and city/state/zip are recovered. The remaining 16 fields start at defaults (same as current behavior).

  • TB11 drawings (before this fix): Same as PB11 — no project_list exists. First time the user opens Project Details and clicks OK, the write function creates project_list. Subsequent reopens will find it.

  • First-time creation: When project_list does not exist in NOD, the write function creates both the XRecord entity and the dictionary entry. No pre-existing dictionary is assumed.


Export/Import Alignment

Export Script (cvxpproj.lsp)

After Bug 103 fix and Phase 4a:

Source A: Panel XRecord header (existing — DXF 3,4,6,7 from "panel"/"panel_list")
Source B: Site XRecord header (existing — DXF 3,4,6,7 from "site"/"site_list")
Source C: Project XRecord header (NEW — DXF 3,4,6,7 from "project"/"project_list")
Source D: Project XRecord body (NEW — DXF 1/2/3 triplets = 21 pdvar key/value pairs)
Source E: Title block ATTRIBs (existing)
Source F: Runtime globals (existing, with corrected names)

The JSON schema (cvxpproj.schema.json) will add:

  • xrecordHeaders.project — same structure as panel/site headers

  • projectXrecordBody — flat object with 21 key/value pairs from DXF triplets

Diagnostic Script (csv_diag.lsp)

After Phase 4c, csv_diag will probe these NOD dictionary keys:

  • panel (VLX mode), panel1 (VLX backup), panel_list (source mode)

  • site (VLX mode), site1 (VLX backup), site_list (source mode)

  • project (VLX mode — may not exist), project_list (source mode — new)

Import Script (imprt.lsp)

No changes. imprt.lsp handles panel data only (.cvpanel JSON → panelvarpanel_list XRecord). A project import script is out of scope for this implementation.


Cross-References