@lmctl-ai/lmctl 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,8 +36,10 @@ export declare function modelSelectionWarnings(members: MemberConfig[], opts?: {
36
36
  * - unresolved -> silent (deliberate non-binding in lmprice's alias
37
37
  * table, not lint's claim to second-guess)
38
38
  * - no-catalog / catalog unavailable -> skip silently
39
- * The returned warnings wire into lint/seed's standard warnings array, so
40
- * `lint --strict` promotes them exactly like every other warning.
39
+ * The returned warnings wire into lint/seed's standard warnings array
40
+ * (operator ruling, 2026-09-29: lint has exactly two outcomes, ok/warning --
41
+ * never an error, and the `--strict` flag that used to promote warnings to
42
+ * a failing exit code has been removed entirely).
41
43
  */
42
44
  export declare function catalogModelWarnings(members: MemberConfig[], opts?: {
43
45
  snapshot?: CatalogSnapshot;
@@ -6,13 +6,19 @@
6
6
  * 2. Scan all and check before execution: In-memory AST validation upfront. Zero intermediate files generated.
7
7
  * 3. Language features: Top-level functions, flow control (if/else, while, for, break, continue, return), tuple & destructuring assignment: (a, b) = [1, 2], dot notation (data.key), object literals { key: val }, and negative indexing arr[-1].
8
8
  * 4. Predefined functions implemented in TypeScript:
9
- * - File I/O: read_file, write_file, append_file, read_lines, read_json, write_json, read_csv, write_csv, file_exists, delete_file.
9
+ * - File I/O: read_file, write_file, append_file, read_lines, read_json, write_json, read_csv, write_csv, file_exists, delete_file, mkdir, rmdir, copy_file, move_file, basename, dirname, path_join, abs_path.
10
10
  * - Data structures:
11
11
  * * List/Array: list, len, push, pop, shift, unshift, insert, remove_at, slice, concat, reverse, sort, contains, index_of, join, unique, flatten, first, last, is_empty, sum, avg.
12
- * * Hash/Map: map, keys, values, entries, from_entries, has_key, get, set, delete_key, merge, clone, clear, size.
12
+ * * Hash/Map: hash, keys, values, entries, from_entries, has_key, get, set, delete_key, merge, clone, clear, size. ("map" is deliberately unimplemented, not an empty-hash constructor -- reserved for a future higher-order array-transform function.)
13
13
  * - JSON processing: data = json(out), json_parse, json_parse_safe, json_stringify, pluck, filter_by, find_by.
14
+ * - Regex: regex_test/test, regex_match/match/search, regex_find_all/findall, regex_replace, split_regex -- patterns are plain strings compiled via the host RegExp engine.
15
+ * - Environment & time: env, getenv, set_env, now, timestamp, date, strftime, date_format.
16
+ * - Null handling: coalesce, if_null, default_to, if_else (expression-level ternary).
14
17
  * - System & Process: system() returning SystemResult, prompt_human() for attended terminal pause/handoff.
15
18
  * - Comprehensive string operations (split, lines, words, join, trim, upper, lower, contains, replace, slice, etc.).
19
+ * - First-class function values: a bare reference to an already-declared function name (user or host) is a
20
+ * callable FunctionRef, assignable to a variable (`g = dbl; g(4);`) -- a NAMED reference, not a lexical
21
+ * closure; calling through a non-identifier expression (e.g. `arr[0](x)`) is not supported.
16
22
  * 5. Register new functions: API allowing host TypeScript functions to be registered and checked statically.
17
23
  *
18
24
  * Security & Authority Model:
@@ -315,7 +321,7 @@ export declare class Parser {
315
321
  private consume;
316
322
  private consumeOptionalSemicolon;
317
323
  }
318
- export declare const STDLIB_SOURCE = "# LMScript Standard Library (std.lms)\n\n# String Utilities\nfn is_blank(s) {\n if (s == null) {\n return true;\n }\n return len(trim(s)) == 0;\n}\n\n# Array Utilities\nfn chunk(arr, size) {\n if (size <= 0) {\n return [];\n }\n res = [];\n current = [];\n for (i = 0; i < len(arr); i = i + 1) {\n push(current, arr[i]);\n if (len(current) == size) {\n push(res, current);\n current = [];\n }\n }\n if (len(current) > 0) {\n push(res, current);\n }\n return res;\n}\n\nfn compact(arr) {\n res = [];\n for (i = 0; i < len(arr); i = i + 1) {\n item = arr[i];\n if (item != null) {\n push(res, item);\n }\n }\n return res;\n}\n\nfn zip(arr1, arr2) {\n res = [];\n limit = len(arr1);\n if (len(arr2) < limit) {\n limit = len(arr2);\n }\n for (i = 0; i < limit; i = i + 1) {\n push(res, [arr1[i], arr2[i]]);\n }\n return res;\n}\n\nfn take(arr, n) {\n res = [];\n limit = n;\n if (limit > len(arr)) {\n limit = len(arr);\n }\n for (i = 0; i < limit; i = i + 1) {\n push(res, arr[i]);\n }\n return res;\n}\n\nfn drop(arr, n) {\n res = [];\n start = n;\n if (start < 0) {\n start = 0;\n }\n for (i = start; i < len(arr); i = i + 1) {\n push(res, arr[i]);\n }\n return res;\n}\n\n# Math Utilities\nfn clamp(val, low, high) {\n if (val < low) {\n return low;\n }\n if (val > high) {\n return high;\n }\n return val;\n}\n";
324
+ export declare const STDLIB_SOURCE = "# LMScript Standard Library (std.lms)\n\n# String Utilities\nfn is_blank(s) {\n if (s == null) {\n return true;\n }\n return len(trim(s)) == 0;\n}\n\n# Array Utilities\nfn chunk(arr, size) {\n if (size <= 0) {\n return [];\n }\n res = [];\n current = [];\n for (i = 0; i < len(arr); i = i + 1) {\n push(current, arr[i]);\n if (len(current) == size) {\n push(res, current);\n current = [];\n }\n }\n if (len(current) > 0) {\n push(res, current);\n }\n return res;\n}\n\nfn compact(arr) {\n res = [];\n for (i = 0; i < len(arr); i = i + 1) {\n item = arr[i];\n if (item != null) {\n push(res, item);\n }\n }\n return res;\n}\n\nfn zip(arr1, arr2) {\n res = [];\n limit = len(arr1);\n if (len(arr2) < limit) {\n limit = len(arr2);\n }\n for (i = 0; i < limit; i = i + 1) {\n push(res, [arr1[i], arr2[i]]);\n }\n return res;\n}\n\nfn enumerate(arr) {\n res = [];\n for (i = 0; i < len(arr); i = i + 1) {\n push(res, [i, arr[i]]);\n }\n return res;\n}\n\nfn take(arr, n) {\n res = [];\n limit = n;\n if (limit > len(arr)) {\n limit = len(arr);\n }\n for (i = 0; i < limit; i = i + 1) {\n push(res, arr[i]);\n }\n return res;\n}\n\nfn drop(arr, n) {\n res = [];\n start = n;\n if (start < 0) {\n start = 0;\n }\n for (i = start; i < len(arr); i = i + 1) {\n push(res, arr[i]);\n }\n return res;\n}\n\n# Math Utilities\nfn clamp(val, low, high) {\n if (val < low) {\n return low;\n }\n if (val > high) {\n return high;\n }\n return val;\n}\n";
319
325
  export declare function getStdlibProgram(): Program;
320
326
  export interface CheckOptions {
321
327
  /** Inspect literal built-in read paths against the current filesystem. No script evaluation. */
@@ -385,6 +391,23 @@ export declare class BreakSignal {
385
391
  }
386
392
  export declare class ContinueSignal {
387
393
  }
394
+ /**
395
+ * First-class function value (operator ruling, 2026-09-29, Rule 2 -- "if it
396
+ * is just how it came out, it is worth fixing": no stated design rationale
397
+ * anywhere separated function names from the variable namespace; it was an
398
+ * omission of scope, not a deliberate tradeoff). A bare reference to an
399
+ * already-declared function name (user `fn` or host) evaluates to one of
400
+ * these, which can be assigned, stored, and called through a variable --
401
+ * `g = dbl; g(4);` now works. Deliberately a NAMED reference, not a true
402
+ * lexical closure over an enclosing scope: nothing in the reported gaps
403
+ * (map/filter/reduce/etc. over top-level named functions) needs closures,
404
+ * and adding them is a materially bigger, separate change.
405
+ */
406
+ export declare class FunctionRef {
407
+ readonly name: string;
408
+ constructor(name: string);
409
+ toString(): string;
410
+ }
388
411
  export declare class Environment {
389
412
  private static nextId;
390
413
  readonly id: number;
@@ -464,6 +487,13 @@ export declare class Interpreter {
464
487
  evaluateProgram(program: Program): any;
465
488
  private execStmt;
466
489
  private evalExpr;
490
+ /** A call's callee name is normally used directly -- but if it names
491
+ * neither a declared user function nor a host function, it may be a
492
+ * variable holding a first-class FunctionRef (`g = dbl; g(4);`), in which
493
+ * case the actual function to invoke is the ref's name instead. */
494
+ private resolveCallTarget;
495
+ private invokeNamed;
496
+ private resolveIdentifier;
467
497
  private isTruthy;
468
498
  evaluateProgramAsync(program: Program): Promise<any>;
469
499
  private execStmtAsync;
@@ -10,15 +10,20 @@ For `.lmctl` teamfile compatibility mode:
10
10
  This REPLACED the static tested-model lists that used to live in this
11
11
  document (2026-09-24) — hand-copied lists contradicted the catalog.
12
12
 
13
- **Best-effort contract (operator, 2026-09-25): lint is advisory and is NOT
14
- claimed to be 100% up to date.** Checks can lag provider reality in BOTH
15
- directions — a model lint warns about may have just been added upstream, and
16
- a model lint accepts may have just been retired. Every model check is a
17
- warning, never an error (`lint --strict` is the operator's explicit
18
- promotion, not the default). The runtime stance for anything unrecognized
19
- or out of date is always: "not recognized — could still be valid; no cost
20
- information," never a failure. Cost is equally best-effort (n/a with a
21
- reason, never a guessed price).
13
+ **Best-effort contract (operator, 2026-09-25, hardened 2026-09-29): lint is
14
+ advisory and is NOT claimed to be 100% up to date.** Checks can lag provider
15
+ reality in BOTH directions — a model lint warns about may have just been
16
+ added upstream, and a model lint accepts may have just been retired. Every
17
+ model check is a warning, never an error, full stop: lint has exactly two
18
+ outcomes (ok / warning) and always exits 0 on warnings-only. There used to be
19
+ a `--strict` flag that could promote warnings to a failing exit code; the
20
+ operator removed it entirely (2026-09-29: "no need to give users the choice
21
+ with no obvious value") — lmctl decides the scoping, not the caller. Exit 1
22
+ is reserved for genuine validation errors (a malformed teamfile, an
23
+ unparseable member line), never for a warning. The runtime stance for
24
+ anything unrecognized or out of date is always: "not recognized — could
25
+ still be valid; no cost information," never a failure. Cost is equally
26
+ best-effort (n/a with a reason, never a guessed price).
22
27
  - `codex` and `agy` model validation queries each provider's own live
23
28
  catalog command (`codex debug models`, `agy models`) instead of a
24
29
  hand-copied list — see their `## Codex` / `## Antigravity` sections
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmctl-ai/lmctl",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "A provider-agnostic control plane for teams of AI coding agents — across providers, with independent review and durable memory.",
5
5
  "type": "module",
6
6
  "homepage": "https://lmctl.com",