vl-metadata-spec-3.1.md 9.6 KB

VL Metadata Spec 3.1

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
  • Clarifies that DocCenter / workflow document bindings live in project config as Doc ID, not inside ProjectMeta

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.

2.4 Doc binding exclusion

ProjectMeta must not inline DocCenter binding configuration for core specs or workflow prompts.

The following values belong to IDE / project profile configuration, not metadata schema:

  • coreDocIds
  • docIdOverrides
  • any UI-level Doc Ref or viewer URL such as vl://doc/16 or /doc-center.html?docId=16

Reason:

  • ProjectMeta models the project itself
  • doc bindings model external tooling configuration
  • keeping them separate prevents schema drift when official docs are republished or remapped

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.1 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