Skip to content

Proposal: Add Formula and Module modes to llar list #185

Description

@MeteorsLiu

Proposal: Add Formula and Module modes to llar list

Summary

Add a read-only llar list [module] command with two object modes. Formula mode is the default and returns ordered Formula ranges plus Matrix metadata. The -m flag switches to Module mode and returns known upstream versions plus the static dependency table from versions.json.

The command does not accept module@version. Concrete version, matrix, dynamically resolved dependencies, and result data remain owned by llar make --json and llar install --json.

Motivation

LLARHub needs catalog data without parsing Formula source or invoking builds:

  1. Formula data: ordered fromVer boundaries and Formula Matrix metadata.
  2. Module data: module path, all known upstream versions in module-defined order, and static version-keyed dependency pins.

Formula already owns a Matrix structure with Require, Options, and DefaultOptions. Reusing it avoids separate and overlapping JSON contracts for defaults, options, and filter-related capability data.

Goals

  • List Formula ranges and Matrix metadata by default.
  • List Module metadata only with -m.
  • Order ranges and upstream versions with the module comparator, without assuming semantic versions.
  • Preserve the versions.json dependency-table shape and its static meaning.
  • Support the current local Formula checkout and explicit module arguments.
  • Remain read-only and suitable for automation.

Out of Scope

  • module@version queries.
  • Concrete version and matrix resolution.
  • Running Formula filter, onRequire, or MVS for dependency output.
  • Defining how complete future Matrix requirement and option domains are derived.
  • Artifact, cache, local/cloud availability, output-directory, or build-metadata listing.
  • Module patterns, recursive ..., or all.
  • A separate llar inspect command.
  • The LLARHub Action or final website data.json schema.

Formula Mode

Formula mode is the default:

llar list --json
llar list google/highway --json
llar list ./google/highway --json

It emits one module-level object:

{
  "path": "google/highway",
  "ranges": [
    "1.4.0"
  ],
  "formulas": [
    {
      "fromVer": "1.4.0",
      "matrix": {
        "require": {},
        "options": {
          "fPIC": ["ON"],
          "shared": ["OFF"],
          "with_test": ["OFF"]
        },
        "defaultOptions": {
          "fPIC": ["ON"],
          "shared": ["OFF"],
          "with_test": ["OFF"]
        }
      }
    }
  ]
}

A module with multiple ranges has the same shape:

{
  "path": "example/library",
  "ranges": [
    "v1.4",
    "v1.2"
  ],
  "formulas": [
    {
      "fromVer": "v1.4",
      "matrix": {
        "require": {},
        "options": {
          "shared": ["OFF"]
        },
        "defaultOptions": {
          "shared": ["OFF"]
        }
      }
    },
    {
      "fromVer": "v1.2",
      "matrix": {
        "require": {},
        "options": {
          "shared": ["ON"]
        },
        "defaultOptions": {
          "shared": ["ON"]
        }
      }
    }
  ]
}

Rules:

  • ranges contains every Formula fromVer, ordered highest to lowest by the module comparator.
  • formulas uses the same order and formulas[i].fromVer == ranges[i].
  • matrix reuses the Formula Matrix shape.
  • matrix.require, matrix.options, and matrix.defaultOptions are map[string][]string.
  • Existing Formula defaults are represented in both matrix.options and matrix.defaultOptions, matching the current Defaults behavior that initializes the active option selections and their defaults.
  • Version 1 emits an empty require object when the Formula declares no target requirements.
  • Formula filter is not a separate JSON field. Future capability data uses the Matrix structure.
  • ranges is a boundary list, not synthesized {min,max} objects.

Module Mode

The -m flag switches to Module mode:

llar list -m --json
llar list -m google/highway --json
llar list -m ./google/highway --json
{
  "path": "google/highway",
  "versions": [
    "v0.7.0",
    "0.11.0",
    "0.11.1",
    "1.4.0"
  ],
  "deps": {}
}

Rules:

  • versions contains every known upstream tag, preserving original strings and ordered lowest to highest by the module comparator.
  • deps exactly preserves the version-keyed versions.json shape.
  • deps means static declarations and pins only.
  • Module mode does not execute Formula hooks, inject a matrix, or run MVS.
  • deps must not be interpreted as the effective dependency graph for a concrete version and matrix.

Module Selection

With no module argument, the command walks from the working directory to the nearest versions.json and uses that local module.

An explicit local path selects that Formula checkout. An explicit module path selects that named module. A module@version argument is invalid in both modes.

Output And Errors

--json writes one JSON object per selected module to standard output. Diagnostics go to standard error. A failed query exits non-zero and must not emit a partial object.

Without --json, the command may render the same selected mode for humans. Human-readable output is not the automation contract.

Missing maps and arrays in the contract are encoded as {} and [], never null.

The command returns an error for an invalid module path, module@version, missing or invalid versions.json, Formula loading failure, comparator failure, or upstream version-query failure.

The command must not build, install, test, download artifacts, resolve dynamic dependencies, or mutate artifact-cache state.

Static And Resolved Dependencies

The two deps contracts remain distinct:

llar list -m deps  = versions.json static declarations and pins
make/install deps  = concrete version + matrix resolution result

For a concrete resolution, LLAR selects the Formula for the requested source version, injects the matrix, runs filter and onRequire, uses versions.json for pins or fallback, and then runs MVS. llar list performs none of those steps for deps.

Architecture Boundary

The module loader owns module paths, Formula discovery, custom version comparison, Matrix metadata, and dependency resolution. Formula mode exposes Formula boundaries and Matrix data. Module mode exposes upstream versions and the static versions.json table. The CLI owns mode selection, argument parsing, and rendering. LLARHub owns combining these facts with GitHub metadata and CI results.

Implementation must expose only the minimum internal data required by the CLI. It must not expose interpreted Formula callbacks, build contexts, cache internals, or resolver policy as a public API.

Compatibility

This proposal is additive. It changes no existing make, install, test, Formula DSL, versions.json, cache, artifact, or comparator behavior.

Alternatives Considered

Separate defaults, options, and filter fields

Rejected because Formula already owns Matrix{Require, Options, DefaultOptions}. Reusing Matrix provides one consistent contract.

One Formula JSON object per Formula

Rejected because callers need one module-level catalog containing the ordered ranges and corresponding Formula records.

Synthesized {min,max} ranges

Rejected because Formula selection is defined by ordered fromVer boundaries and the last Formula has no finite upper bound.

Treat static dependencies as effective dependencies

Rejected because onRequire may change dependencies for a concrete source version and matrix.

Separate llar inspect

Rejected because default Formula mode and explicit -m Module mode already provide the required boundary.

Include artifact availability

Rejected because make --json and install --json own result data. Read-only artifact inventory requires a separate storage-enumeration design.

Acceptance Criteria

  • llar list <module> --json emits one Formula catalog object with only path, ordered ranges, and same-order formulas containing fromVer and matrix.
  • Every Formula Matrix contains require, options, and defaultOptions maps shaped as map[string][]string.
  • Existing Formula defaults appear in both matrix.options and matrix.defaultOptions.
  • llar list -m <module> --json emits only path, comparator-ordered versions, and the unchanged static deps table.
  • No-argument queries resolve the current module through the nearest versions.json.
  • module@version is rejected in both modes.
  • Empty maps and arrays are {} and [], not null.
  • Neither mode executes a build, install, test, artifact download, dynamic dependency resolution, or cache mutation.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions