Skip to content

Workspace Spec

The workspace spec (workspace.yaml) is the kernel-level configuration file that defines the runtime environment for a LumenFlow workspace. It declares which packs are loaded, which lanes exist, what security boundaries apply, and where events and memory are stored.

LumenFlow is designed to work across multiple consumer repo shapes, but the portability contract is explicit:

  • LumenFlow remains a Node-distributed CLI.
  • Consumer repos do not need to be Next.js apps or pnpm monorepos.
  • Framework-specific surfaces such as apps/web dashboards are optional and should only be referenced when present or configured.

Current baseline archetypes for generic lifecycle support:

ArchetypeExpected shapeGeneric lifecycle expectation
Single-package service reposrc/**, no apps/ or packages/init, wu:create, wu:brief, wu:prep, and wu:done work without monorepo-specific guidance
Monorepo without web appmultiple packages or services, no apps/webgate planning and onboarding do not instruct the user to start a dashboard
Backend/docs-oriented reposervice code plus docs/content pathswork classification does not infer UI-only guidance from framework-like filenames alone

Smoke verification for this baseline should confirm:

  1. onboarding does not advertise dashboard startup when no dashboard surface exists
  2. classifier defaults stay backend/docs/infra-oriented unless generic UI signals or workspace config justify UI guidance
  3. docs and generated workflow guidance describe these boundaries explicitly
# workspace.yaml
id: my-workspace
name: My Project

packs:
  - id: software-delivery
    version: '0.1.0'
    integrity: sha256:a1b2c3d4e5f6...
    source: local
    # url: optional — required for git/registry sources
    # registry_url: optional — override default registry

lanes:
  - id: framework-core
    title: 'Framework: Core'
    allowed_scopes:
      - type: path
        pattern: 'packages/@lumenflow/core/**'
        access: write
    wip_limit: 1
    # policy_overrides: optional

security:
  allowed_scopes:
    - type: path
      pattern: '**'
      access: write
    - type: network
      posture: 'off'
  network_default: 'off'
  deny_overlays:
    - '.lumenflow/**'

memory_namespace: my-workspace
event_namespace: my-workspace

All ten root keys recognized by the kernel’s WorkspaceSpecSchema:

FieldTypeRequiredManaged ByDescription
idstringYesworkspace-initUnique workspace identifier
namestringYesworkspace-initHuman-readable workspace name
packsPackPin[]Nopack:installArray of pack pins to load
lanesLaneSpec[]Nolane:editArray of lane definitions
policiesobjectNopolicy:setWorkspace-level policy overrides
securityobjectNosecurity:setWorkspace-level security config
software_deliveryobjectNoconfig:set (pack config)Software Delivery pack configuration (see below)
control_planeobjectNoconfig:set (writable root key)Control plane connection and sync settings
memory_namespacestringNoconfig:set (writable root key)Namespace for memory layer isolation
event_namespacestringNoconfig:set (writable root key)Namespace for kernel event stream isolation

Root keys fall into three categories based on how they are modified:

  1. Writable root keyscontrol_plane, memory_namespace, event_namespace. These can be written directly with config:set.
  2. Pack config keys — Keys like software_delivery that are declared by a pack’s config_key field in its manifest. Written with config:set and validated against the pack’s config schema.
  3. Managed root keysid, name, packs, lanes, policies, security. These require dedicated CLI commands (shown in the table above). Running config:set on a managed key produces an error with guidance on which command to use instead.

When a pack declares a config_key in its manifest, that key becomes a valid root-level field in workspace.yaml. For example, the Software Delivery pack declares config_key: software_delivery, which makes the software_delivery root key available.

The software_delivery field is optional. If the Software Delivery pack is not pinned in the packs array, the workspace boots without it. This allows workspaces that use other domain packs (or no packs at all) to operate with a minimal kernel-only configuration.

Each entry in the packs array is a pack pin — a versioned, integrity-checked reference to a domain pack that the kernel loads at startup.

FieldTypeRequiredDescription
idstringYesPack identifier (e.g., software-delivery)
versionstringYesSemantic version (e.g., 0.1.0)
integritystringYessha256:<64-hex> hash or dev for local development
sourcestringYesOne of local, git, or registry
urlstringNoSource URL (required for git and registry sources)
registry_urlstringNoOverride the default pack registry URL

The integrity field ensures packs cannot be tampered with. It uses the same sha256:<hex> format as Subresource Integrity (SRI):

  • sha256:<64-char-hex> — Production mode. The kernel verifies the pack manifest hash matches before loading.
  • dev — Development mode. Skips integrity verification for local pack development.
packs:
  # Production: integrity-verified
  - id: software-delivery
    version: '1.0.0'
    integrity: sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    source: registry

  # Development: skip verification
  - id: software-delivery
    version: '0.1.0'
    integrity: dev
    source: local

Each entry in lanes defines a lane at the kernel level (separate from delivery lane definitions under software_delivery.lanes.definitions).

FieldTypeRequiredDescription
idstringYesLane identifier (kebab-case, e.g., framework-core)
titlestringYesHuman-readable name (e.g., Framework: Core)
allowed_scopesToolScope[]NoScopes this lane grants (defaults to [])
wip_limitintegerNoMaximum concurrent active tasks
policy_overridesobjectNoLane-level policy configuration

The lane’s allowed_scopes are used as the second level of the scope intersection algorithm:

effective_scope = workspace ∩ lane ∩ task ∩ tool

The security object defines the workspace-level permission boundary — the outermost layer of the scope intersection.

FieldTypeRequiredDescription
allowed_scopesToolScope[]YesMaximum permissions any tool can receive
network_defaultstringYesDefault network posture: off or full
deny_overlaysstring[]YesGlob patterns for unconditionally denied paths

Scopes can be path or network types:

security:
  allowed_scopes:
    # Path scope: grant write access to all files
    - type: path
      pattern: '**'
      access: write

    # Network scope: deny all network access
    - type: network
      posture: 'off'

The network scope posture field accepts three values:

PostureDescription
offAll network access blocked
allowlistOnly traffic to listed hosts/CIDRs is permitted
fullUnrestricted network access

When posture is allowlist, the allowlist_entries field is required:

FieldTypeRequiredDescription
allowlist_entriesstring[]Yes (when posture=allowlist)Array of permitted host:port or CIDR entries
security:
  allowed_scopes:
    - type: network
      posture: allowlist
      allowlist_entries:
        - 'registry.npmjs.org:443' # host:port format
        - 'api.github.com:443' # host:port format
        - '10.0.0.0/24' # CIDR format

The kernel validates that allowlist_entries is present and non-empty when posture is allowlist. Omitting it or passing an empty array produces a Zod validation error at startup.

Network scopes participate in scope intersection across all four layers (workspace, lane, task, tool). See the scope intersection page for the deny-wins semantics and entry-level set intersection behavior.

Paths in deny_overlays are unconditionally denied regardless of scope intersection. The kernel checks these before any other authorization step:

security:
  deny_overlays:
    - '.lumenflow/**' # Kernel state is tamper-proof
    - '.git/**' # Git internals are protected

The kernel validates workspace.yaml against WorkspaceSpecSchema (defined in @lumenflow/kernel) at startup. Invalid specs cause initializeKernelRuntime() to throw with a Zod validation error.

# The kernel validates automatically during initialization.
# There is no separate public CLI validation command for kernel-only workspace specs.
# Validate by booting the kernel runtime with your workspace.yaml in place.

The software_delivery root key is a pack config block owned by the Software Delivery pack. It exists in workspace.yaml only when the pack is pinned and declares config_key: software_delivery in its manifest.

Concernworkspace.yaml top-level (kernel)workspace.yaml > software_delivery (pack)
AudienceKernel runtimeCLI and tooling layer
LanesLaneSpec (id, scopes, wip)Lane definitions (name, code_paths)
PacksPackPin (id, version, integrity)Not present
SecurityScope intersection boundariesGit hooks, safe-git wrapper
GatesPack policies (on_completion)Gate commands, conditional commands
ValidationZod WorkspaceSpecSchema at initPack config schema via config:set

The software_delivery.gates block configures quality gate commands and conditional commands.

Pattern-triggered commands that run only when matching files change:

software_delivery:
  gates:
    execution:
      format: 'pnpm format:check'
      lint: 'pnpm lint'
      test: 'pnpm test'

    conditional_commands:
      - trigger_patterns:
          - 'supabase/migrations/**'
          - 'supabase/schema.sql'
        command: 'pnpm db:verify'
        severity: error
        guidance: 'Apply pending migrations before verifying.'
        guidance_ref: 'docs/db-verification-guide.md'
FieldTypeRequiredDescription
trigger_patternsstring[]YesGlob patterns matched against changed files (min 1)
commandstringYesShell command to execute
severitystringNoerror (default), warn, or off
guidancestringNoActionable text shown on failure
guidance_refstringNoFile path whose content is appended to guidance on failure

See Gates for usage details.

  • Kernel Runtime — How the workspace spec is loaded and used
  • Packs — Domain pack architecture and the Software Delivery Pack
  • Scope Intersection — How workspace security becomes effective permissions
  • Configurationsoftware_delivery configuration reference