vl-metadata-spec-3.0.md 9.0 KB

VL Metadata Spec 3.0

Status: canonical metadata schema for VLCode-Lite and DocCenter Path 4

Scope:

  • Defines the canonical ProjectMeta JSON consumed by metadata diff, workflow regeneration, project context, and DocCenter-backed tooling
  • Normalizes legacy extractor output into one stable shape
  • Aligns Theme metadata with VL 3.7 / THEME 6.6

1. Purpose

ProjectMeta is the machine-readable project model for a VL workspace.

It exists to support:

  • deterministic workflow regeneration
  • project-wide diff and impact analysis
  • DocCenter-backed prompt context
  • IDE visualization and debug tooling
  • stable references across Apps/, Sections/, ExtComponents/, Services/, Database/, and Theme/

This spec defines the canonical schema. Legacy field names may still be accepted by importers, but they are not canonical output.

2. Canonical Rules

2.1 Root schema

Canonical root object:

{
  "$schema": "VL-ProjectMeta/3.0",
  "projectName": "SmartCampus",
  "projectDescription": "optional",
  "vlVersion": "3.7",
  "config": {
    "deviceTarget": "web",
    "screenResolution": "1440x900"
  },
  "fileManifest": [],
  "valueDomains": {},
  "apps": [],
  "sections": [],
  "components": [],
  "services": [],
  "dataSchema": {
    "tables": [],
    "relations": []
  },
  "theme": null,
  "dependencyGraph": null
}

2.2 Identifier policy

  • apps[*].id is the canonical app identifier
  • sections[*].id is the canonical section identifier
  • components[*].id is the canonical component identifier
  • services[*].domainId is the canonical service-domain identifier
  • services[*].methods[*].id is the canonical method identifier
  • services[*].methods[*].serviceId is the canonical fully-qualified service identifier, normally domainId.methodId
  • dataSchema.tables[*].id is the canonical table identifier
  • theme.id is the canonical theme identifier

Legacy aliases such as appId, sectionId, componentId, tableName, serviceDomains, servicesUsed, and componentRefs are compatibility inputs only.

2.3 File path policy

Canonical default file locations:

  • app: Apps/<id>.vx
  • section: Sections/<id>.sc
  • component: ExtComponents/<id>.cp
  • service: Services/<domainId>.vs
  • database: Database/<projectName>.vdb or explicit per-table/file-level mapping when available
  • theme: Theme/Theme.vth

If filePath is omitted during normalization, tooling may synthesize the conventional path above.

3. Entity Schemas

3.1 App

{
  "id": "AdminApp",
  "filePath": "Apps/AdminApp.vx",
  "vlVersion": "3.7",
  "device": "web",
  "resolution": "1440x900",
  "description": "",
  "globalVars": [],
  "pages": [
    {
      "id": "Dashboard",
      "route": "/dashboard",
      "sections": ["DashboardMain"],
      "sectionRefs": [
        {
          "sectionId": "DashboardMain",
          "instanceId": "mainSection",
          "layoutProps": {}
        }
      ],
      "componentRefs": [],
      "layout": []
    }
  ],
  "routeMap": {
    "/dashboard": "DashboardMain"
  },
  "homeRoute": "/dashboard",
  "wiring": [],
  "navSectionInstanceId": null,
  "navEventName": null
}

Rules:

  • pages[*].id must be stable inside the app
  • pages[*].sections contains section IDs only
  • pages[*].sectionRefs[*].sectionId must resolve to an existing section
  • routeMap is a convenience index, not a second source of truth

3.2 Section

{
  "id": "DashboardMain",
  "filePath": "Sections/DashboardMain.sc",
  "vlVersion": "3.7",
  "previewSize": null,
  "publicProps": [],
  "publicEvents": [],
  "publicMethods": [],
  "globalVars": [],
  "derivedVars": [],
  "consumesServices": [
    "CampusService.getOverview",
    "CampusService.listAlerts"
  ],
  "usesComponents": [
    "StatCard",
    "AlertTable"
  ],
  "interactiveElements": [],
  "internalMethods": [],
  "pipeFuncs": [],
  "isNavSection": false,
  "navMenuItems": [],
  "navItemInstanceId": null,
  "keyStates": {},
  "description": ""
}

Rules:

  • consumesServices is an array of service ID strings, not nested service objects
  • usesComponents is an array of component ID strings, not component ref objects
  • consumesServices[*] must resolve to an existing services[*].methods[*].serviceId
  • usesComponents[*] must resolve to an existing components[*].id

3.3 Component

{
  "id": "StatCard",
  "filePath": "ExtComponents/StatCard.cp",
  "vlVersion": "3.7",
  "previewSize": null,
  "publicProps": [],
  "publicEvents": [],
  "derivedVars": [],
  "interactiveElements": [],
  "internalMethods": [],
  "pipeFuncs": [],
  "description": ""
}

3.4 Service domain

{
  "domainId": "CampusService",
  "filePath": "Services/CampusService.vs",
  "vlVersion": "3.7",
  "envVars": [],
  "methods": [
    {
      "id": "getOverview",
      "serviceId": "CampusService.getOverview",
      "type": null,
      "params": [],
      "returns": {},
      "expose": null,
      "sig": null
    }
  ],
  "virtualTables": [
    {
      "id": "OverviewView",
      "source": "campus_overview",
      "fields": ["id", "title"],
      "extraSpecs": {}
    }
  ],
  "transactions": [],
  "backendComponents": []
}

Rules:

  • domainId is canonical; id/name are compatibility inputs only
  • methods[*].id is canonical; methods[*].name is compatibility input only
  • methods[*].serviceId should be emitted even when it can be derived
  • virtualTables[*].source must reference an existing table ID when it points to a physical table

3.5 Database schema

{
  "dataSchema": {
    "tables": [
      {
        "id": "campus_overview",
        "name": "campus_overview",
        "filePath": "",
        "fields": [
          {
            "name": "id",
            "type": "STRING",
            "notNull": true,
            "default": null,
            "enumRef": null,
            "sourceField": null
          }
        ],
        "indexes": [],
        "seedData": null
      }
    ],
    "relations": [
      {
        "id": "overview_to_building",
        "from": "campus_overview",
        "to": "building",
        "cardinality": "N:1"
      }
    ]
  }
}

Rules:

  • canonical table key is id, not tableName
  • canonical column collection is fields; columns is compatibility input only
  • enumRef must resolve into valueDomains.enums[*].name when used

3.6 Theme

{
  "theme": {
    "id": "Theme",
    "name": "Theme",
    "filePath": "Theme/Theme.vth",
    "vlVersion": "3.7",
    "rootTag": "Theme-Enterprise-6.6",
    "meta": {
      "mode": "light",
      "version": "6.6.0",
      "styleSpaceVersion": "1.6",
      "base_theme": "Platform/Theme-Default-Light@1",
      "profile": "enterprise"
    },
    "slots": {
      "intent.primary.intentBg": "#2563EB",
      "size.md.sizeMinHeight": "40px",
      "state.focus.stateShadow": "@intent.intentFocusRing"
    },
    "designTokens": [],
    "componentVariants": [],
    "bindingRules": [],
    "overrides": []
  }
}

Rules:

  • for VL 3.7 / THEME 6.6, the canonical theme model is # Meta plus # Point Slot Values
  • theme.slots is the canonical compiled metadata view of .vth point-slot assignments
  • designTokens, componentVariants, bindingRules, and overrides are compatibility carry-through fields only; new tooling should not require them

4. Consistency Constraints

Validation must reject or flag at least the following:

  • section consumes a non-existent service ID
  • section uses a non-existent component ID
  • service virtual table points at a non-existent table
  • app wiring references an instance ID not present in layout refs
  • field enumRef points at a non-existent enum

5. Legacy Compatibility Mapping

Normalizers may accept the following legacy inputs:

Legacy input Canonical output
project.name / project.projectName projectName
database dataSchema
serviceDomains services
appId apps[*].id
sectionId sections[*].id
componentId components[*].id
servicesUsed / services / serviceDomains on section consumesServices
componentRefs / components on section usesComponents
tableName / entityId dataSchema.tables[*].id
columns fields
methods[*].name methods[*].id
theme.pointSlotValues / theme.pointSlots theme.slots

Compatibility input does not change canonical output names.

6. Producer Requirements

Any producer that claims compliance with Metadata Spec 3.0 must emit:

  • $schema: "VL-ProjectMeta/3.0"
  • canonical IDs and field names
  • sections[*].consumesServices as string IDs
  • sections[*].usesComponents as string IDs
  • services[*].methods[*].id
  • dataSchema.tables[*].id
  • theme.slots when theme slot data is available

7. Consumer Requirements

Consumers should:

  • read canonical fields first
  • optionally normalize known legacy aliases on import
  • never write new metadata using legacy key names
  • treat DocCenter path references and workflow prompts as external configuration, not as metadata schema fields

8. Canonical Schema String

Use exactly:

VL-ProjectMeta/3.0