Skip to content

Packs

A pack is a self-contained domain extension that teaches the kernel how to work in a specific domain. The kernel itself is domain-agnostic — it provides scope enforcement, policy evaluation, evidence recording, and tool dispatch. Packs provide the actual tools, policies, and evidence types for a particular workflow.

LumenFlow currently ships six bundled first-party packs:

PackDomainCurrent role
software-deliverySoftware development workflowWork Units, lanes, gates, memory, CLI-driven delivery lifecycle
sidekickWorkspace-local productivityManaged tasks, memory, channels, routines, and status under .sidekick/
agent-runtimeGoverned model turnsagent-session turns, policy-aware tool gating, orchestration state
campusCampus compute telemetryRead-only facility/PUE/power-signal observability, approval-gated tenant evidence export
knowledgeDocumentation and referenceDeclarative-tier pack — no tools, no factories, no executable authority
protocol-adaptersCross-protocol tool bridgingcapability_factory-driven protocol adapter surface (trusted-host-adapter tier)

The Software Delivery Pack provides 90+ tools for software development workflows:

NamespaceToolsPurpose
wu:*23Work Unit lifecycle (create, claim, prep, done, block, recover…)
mem:*14Memory layer (checkpoint, inbox, signal, recover…)
initiative:*8Initiative management (create, plan, status…)
file:*4File operations with audit trail
git:*4Git operations with audit trail
agent:*4Agent session management
orchestrate:*3Multi-agent orchestration
plan:*4Plan management
state:*3State management
Others23+Gates, validation, config, docs, metrics, flow analysis…

Every one of these tools routes through the kernel’s execution pipeline — scope intersection, policy evaluation, and evidence recording happen on every call.

The Sidekick Pack adds a compact 23-tool workspace productivity surface:

NamespaceToolsPurpose
task:*6Personal and team-local task tracking, updates, completion, cancel
memory:*4Workspace-local memory, snippets, and destructive forgetting
channel:*5Named message channels, local discovery, and local deletion
routine:*5Plan-only routine definitions, updates, stop flow, and deletion
sidekick:*3Initialization, status, and export

Destructive Sidekick lifecycle tools such as task:cancel, memory:forget, channel:delete, and routine:delete are approval-gated through the pack policy factory when invoked through the kernel runtime.

The Agent Runtime Pack provides the governed agent-runtime:execute-turn contract, policy-aware tool gating, provider normalization, and pack-owned agent-session orchestration.

The Campus Pack exposes campus-scale compute as governed tool surfaces: read-only facility telemetry (campus:*), read-only proof-record tools plus one approval-gated tenant proof-export tool (proof:*), and load-curtailment tooling (flexload:*). It is the pack-side of the campus governance boundary — it proposes observations and serializes proof bundles; it never actuates facility infrastructure. See the Campus Pack docs for the full tool and event surface.

A pack is a directory with a manifest.yaml at its root:

  • Directorymy-pack/ - manifest.yaml (declares tools, policies, evidence types) - constants.ts (pack id, version, shared strings) - config.schema.json (validates workspace config for the pack) - capability-factory.ts (derives runtime scopes/env from resolved pack config) - policy-factory.ts (returns conditional PolicyRule objects) - tools/ - types.ts (shared type definitions) - tool-impl/ - my-tool.ts (runtime implementation)

The manifest is the contract between a pack and the kernel. It declares:

  • Tools — what the pack can do (name, entry point, permissions, required scopes)
  • Policies — static rules the kernel evaluates at specific lifecycle triggers
  • Evidence types — kinds of audit records the pack produces
  • Task types — what domain objects the pack manages (e.g., work-unit)
  • State aliases — friendly names for kernel state machine states
  • Lane templates — pre-defined lane configurations
  • Config namespaceconfig_key and config_schema for pack-specific workspace settings
  • Capability factory — runtime augmentation of required_scopes and required_env
  • Policy factory — runtime-authored rules that can inspect PolicyEvaluationContext
  • Extension ownership — command and state namespaces plus opaque telemetry sources compiled with the tools, policies, configuration root, events, and required surfaces
  • Contract version, publisher, and compatibility — Pack Contract v2 fields (contract_version, publisher, compatibility, depends_on, migrations) declaring who published the pack and what kernel/host versions and dependencies it needs
  • Executable trust tier — Pack Contract v2’s closed classification (declarative, trusted-host-adapter, or isolated) for what the pack’s code is allowed to do — see Pack Contract v2 below
id: my-pack
version: 0.1.0
task_types:
  - my-task-type
tools:
  - name: my-pack:do-something
    entry: tool-impl/my-tool.ts#doSomethingTool
    permission: write
    required_env:
      - MY_PACK_TOKEN
    required_scopes:
      - type: path
        pattern: '**'
        access: write
config_key: my_pack
config_schema: config.schema.json
capability_factory: capability-factory.ts#createMyPackCapabilityFactory
policy_factory: policy-factory.ts#createMyPackPolicyFactory
policies: []
evidence_types: []
state_aliases: {}
lane_templates: []
emitted_event_kinds:
  - my-pack:operation_completed
surfaces_required:
  - cli
  - http
extensions:
  command_namespaces:
    - my-pack
  state_namespaces:
    - my-pack:runtime
  telemetry_sources: []

This example omits contract_version, so it is a Contract v1 manifest — still schema-valid, but not installable by the live registration gate (below). A v2 declaration of the same manifest would also need trust_tier: trusted-host-adapter and a matching adapter_id, since it declares tools and factories.

Every bundled pack declares Pack Contract v2: contract_version: 2 plus a publisher identity, compatibility ranges for the running kernel/host versions, and a closed executable trust tierdeclarative, trusted-host-adapter, or isolated — that decides whether the pack’s tools, capability_factory, and policy_factory are allowed to run at all. An omitted or malformed trust declaration always resolves to declarative, the least-privileged tier, never the most.

trusted-host-adapter and isolated packs also declare an adapter_id. That name only means anything once a host operator — never the pack itself — explicitly registers an adapter for it through HostAdapterRegistrationPort, bound to the specific pack_id it vouches for. A pack can never self-register as trusted, and an adapter registered for one pack can never sanction a different pack that happens to declare the same adapter_id string.

Before any pack’s capability_factory or policy_factory is resolved, the kernel runs validatePackContractV2Registration() against every installed pack in one fail-closed batch: Contract v1 manifests, incompatible kernel/host ranges, unmet dependencies, dependency cycles, and unregistered or mismatched trust adapters are all collected into one diagnostic set and refused together — there is no partial registration. Every subsequent tool dispatch for a trusted-host-adapter pack is checked again, per call, against that pack’s trust decision and the runtime-sealed ExecutionAuthority for the call (see Tool Execution).

See Pack Contract v2 for the full field reference, trust-tier closure rules, host-adapter registration walkthrough, declarative migrations, and how pack:author/pack:scaffold/pack:validate consume this same engine.

At startup, the kernel compiles every installed manifest into one immutable registry. The registry owns command names, configuration roots, emitted event kinds, state namespaces, tools, static policies, required surfaces, and telemetry-source declarations. Runtime registration and CLI/HTTP/MCP discovery read that compiled catalog. Generic tool execution does not need a pack-specific switch; dedicated CLI convenience adapters remain explicit.

Compilation is all-or-nothing. An unknown manifest field, duplicate pack ID, reserved namespace, undeclared tool namespace, cross-pack collision, or unsafe telemetry path prevents the catalog from becoming visible. Mapper modules resolve in a second atomic, pack-relative activation stage; a missing mapper activates none of that workspace’s new telemetry definitions. Removing a pack and compiling again removes all of its entries, including telemetry sources and state ownership.

For pre-v6 manifests without extensions, the compiler infers command namespaces from tool names and assumes no state or telemetry ownership. Reserved-name and collision checks still apply. Authors should add the explicit block during v6 migration, and must add it before declaring state namespaces or telemetry sources.

Pack-owned names follow these rules:

  • tools use one of the manifest’s extensions.command_namespaces;
  • emitted events, state namespaces, and telemetry source IDs start with <pack-id>:;
  • approval, fs, proc, task, and tool command namespaces and the kernel: state namespace are reserved;
  • config_key cannot claim a kernel-owned workspace root;
  • telemetry declares exactly one confined path or dir_glob, an opaque confined mapper module reference, and a metadata-only or full wire-payload policy.

See Authoring manifest-owned extensions for the complete manifest example and collision model.

When the kernel starts, it reads the workspace spec (workspace.yaml) which lists pinned packs:

packs:
  - id: software-delivery
    version: 0.1.0
    integrity: sha256:a1b2c3...
    source: local

For each pack pin, the kernel:

  1. Resolves the pack root — in order:
    • workspaceRoot/packs/
    • workspaceRoot/packages/@lumenflow/packs/ (monorepo development)
    • bundled CLI packs (@hellmai/lumenflow-cli/packs/) for end-user installs
    • a git repository (source: git), or the local pack cache a signed OCI registry install already materialized (source: registry — see Signed OCI pack distribution; this resolution step performs no network I/O itself)
  2. Parses the manifest — validates against the schema, checks that id and version match the pin.
  3. Validates pack config — if the manifest declares config_key and config_schema, the kernel validates the matching workspace config and makes the resolved payload available at runtime.
  4. Validates import boundaries — scans all runtime source files and permits only relative imports within the pack, Node built-ins, the kernel API, explicitly reviewed host/core adapters, exact shared control-plane contracts, exact declared pack dependencies, and a small audited library allowlist. Other LumenFlow packages, dependency subpaths, SDK subpaths, and arbitrary npm packages fail closed.
  5. Verifies integrity — computes a deterministic SHA-256 hash of the pack’s source and contract files and compares it to the pinned hash. Checkout-local dependencies, build caches, pack-local .lumenflow/ runtime state, and root-level .tgz files produced by package tooling are excluded. A mismatch in a tracked source, manifest, configuration, or distributable contract file means the pack was modified and the kernel refuses to load it.
  6. Compiles installed extensions — all manifests become one atomic immutable ownership catalog; any collision or invalid declaration stops startup before partial visibility.
  7. Runs the Pack Contract v2 registration gate — before any capability or policy factory is resolved, validatePackContractV2Registration() checks every installed pack’s contract_version, kernel/host compatibility ranges, depends_on dependencies, and executable trust decision (evaluatePackTrust() against the host’s registered adapters) in one fail-closed batch. Any diagnostic — a Contract v1 pack, an incompatible range, a missing dependency, a dependency cycle, or a denied trust tier — refuses the whole batch; see Pack Contract v2.
  8. Registers tools — each tool declared in the manifest becomes available in the kernel’s tool registry, then optional capability factories can augment required_scopes and required_env using the resolved pack config.
  9. Injects policies — pack-declared policies are added to the pack layer of the policy engine, and optional policy factories can add conditional rules such as intent-aware gating.

LumenFlow is pack-first. First-party packs share the same manifest contract and are loaded from local paths, monorepo packages, bundled installs, or external sources such as git and registries.

See:

Pack tools follow a standard pattern. Each tool returns a ToolOutput:

interface ToolOutput {
  success: boolean;
  data?: Record<string, unknown>;
  error?: { code: string; message: string };
  metadata?: {
    artifacts_written?: string[]; // paths written (for evidence)
  };
}

Tools can be implemented as:

  • In-process handlers — TypeScript functions that run directly in the kernel process. Used for lightweight read operations.
  • Subprocess handlers — executed in a sandboxed subprocess via spawnSync. Used for write operations and anything that needs OS-level isolation.

The Software Delivery Pack uses two implementation strategies. Most tools (~80) use the runtime CLI adapter to reuse existing CLI command modules in-process. A smaller set (~10) use direct implementations with simple-git wrappers and Node builtins. See Tool Execution for the full execution architecture.