@enrichlayer/el-linear 1.23.0 → 1.24.0
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.
- package/README.md +44 -0
- package/dist/output.d.ts +1 -1
- package/dist/utils/output.d.ts +68 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -533,6 +533,50 @@ global `summary` value works on every read/list command.
|
|
|
533
533
|
`--raw` together with `--format summary` to render a list envelope as a
|
|
534
534
|
bare item-list rather than an envelope.
|
|
535
535
|
|
|
536
|
+
### Windowed metadata (`WindowedMeta`)
|
|
537
|
+
|
|
538
|
+
When a command returns less than its complete result set — because it
|
|
539
|
+
windowed by time, paginated, filtered, or hit a `--limit` — it should make
|
|
540
|
+
that visible in the envelope's `meta` rather than leaving the consumer to
|
|
541
|
+
guess. The shared output package (`@enrichlayer/el-linear/output`) exports a
|
|
542
|
+
canonical `WindowedMeta` type for exactly these fields, so every CLI built on
|
|
543
|
+
it uses one set of names instead of ad-hoc `_window` / `_total` / `truncated`
|
|
544
|
+
keys:
|
|
545
|
+
|
|
546
|
+
| Field | Populate when… |
|
|
547
|
+
| ---------------- | --------------------------------------------------------------------- |
|
|
548
|
+
| `_window` | a time/scope window was applied — `"30d"`, `"since 2026-06-01"`. |
|
|
549
|
+
| `_limit_applied` | a cap is in effect — the caller's value, or the default when omitted. |
|
|
550
|
+
| `_query` | a search / filter expression produced `data`. |
|
|
551
|
+
| `_total` | the total matching rows *before* windowing / limiting / filtering. |
|
|
552
|
+
| `_fetched` | rows in *this* response (equals `meta.count` for list envelopes). |
|
|
553
|
+
| `truncated` | `_fetched` hit `_limit_applied` and more rows exist beyond this page. |
|
|
554
|
+
| `availability` | `{status: "complete" \| "partial" \| "degraded", detail?}` — emit `degraded` when a sub-source failed, never an empty result that reads as "no hits". |
|
|
555
|
+
|
|
556
|
+
All fields are optional; a command populates only the ones that apply. The
|
|
557
|
+
`meta` object still admits CLI-specific counters (`_total_hits`,
|
|
558
|
+
`_source_users_total`, …) alongside these, but prefer the generic field where
|
|
559
|
+
one fits so cross-CLI tooling and skills can read a single shape. Skill output
|
|
560
|
+
templates that show counts MUST consume `_total` / `truncated` from `meta`
|
|
561
|
+
rather than counting returned rows.
|
|
562
|
+
|
|
563
|
+
This convention comes from the output-transparency audit's **"Standard
|
|
564
|
+
Convention"** section (`docs/output-transparency-audit-report.md` in the
|
|
565
|
+
`vertical-int/tools` repo, DEV-3810); `WindowedMeta` is the shared type that
|
|
566
|
+
audit recommends promoting into the envelope (DEV-4668).
|
|
567
|
+
|
|
568
|
+
```ts
|
|
569
|
+
import type { WindowedMeta } from "@enrichlayer/el-linear/output";
|
|
570
|
+
|
|
571
|
+
// A list command echoing what it windowed and whether it clipped:
|
|
572
|
+
outputList(rows, {
|
|
573
|
+
_window: "30d",
|
|
574
|
+
_limit_applied: 100,
|
|
575
|
+
_total: 247,
|
|
576
|
+
truncated: rows.length === 100,
|
|
577
|
+
} satisfies WindowedMeta);
|
|
578
|
+
```
|
|
579
|
+
|
|
536
580
|
### Extract a single description section: `--field`
|
|
537
581
|
|
|
538
582
|
`issues read --field <name>` extracts one named section from an issue's
|
package/dist/output.d.ts
CHANGED
|
@@ -79,4 +79,4 @@
|
|
|
79
79
|
* redactor of its own; coupling token redaction to the output layer
|
|
80
80
|
* would make this API surface stickier than it needs to be.
|
|
81
81
|
*/
|
|
82
|
-
export { type CliListEnvelope, getOutputFormat, handleAsyncCommand, type ListExtraMeta, type ListMeta, outputList, outputSingle, outputSuccess, outputWarning, resetWarnings, setFieldsFilter, setJqFilter, setOutputFormat, setRawMode, warnIfTruncated, } from "./utils/output.js";
|
|
82
|
+
export { type CliListEnvelope, getOutputFormat, handleAsyncCommand, type ListExtraMeta, type ListMeta, outputList, outputSingle, outputSuccess, outputWarning, resetWarnings, setFieldsFilter, setJqFilter, setOutputFormat, setRawMode, type WindowedMeta, warnIfTruncated, } from "./utils/output.js";
|
package/dist/utils/output.d.ts
CHANGED
|
@@ -11,6 +11,65 @@ export declare function setFieldsFilter(fields: string[] | null): void;
|
|
|
11
11
|
export declare function setOutputFormat(format: OutputFormat): void;
|
|
12
12
|
/** @internal Test seam — consumers should not depend on the format state. */
|
|
13
13
|
export declare function getOutputFormat(): OutputFormat;
|
|
14
|
+
/**
|
|
15
|
+
* Standard windowing / pagination / truncation metadata for any command
|
|
16
|
+
* that does not return its complete result set in one response.
|
|
17
|
+
*
|
|
18
|
+
* This is the canonical `WindowedMeta` type referenced by the
|
|
19
|
+
* output-transparency audit (DEV-3810 → DEV-4668). It promotes the
|
|
20
|
+
* `el-user usage` reference convention into the shared envelope so every
|
|
21
|
+
* consuming CLI uses the same field names instead of inventing ad-hoc
|
|
22
|
+
* `_window` / `_total` / `truncated` keys. The motivating principle:
|
|
23
|
+
* **every piece of data between a database and a decision-maker (human or
|
|
24
|
+
* LLM) should make its scope, limits, and assumptions visible in the
|
|
25
|
+
* output** — a consumer should never have to read source to interpret
|
|
26
|
+
* data correctly.
|
|
27
|
+
*
|
|
28
|
+
* All fields are optional: a command populates only the ones that apply.
|
|
29
|
+
* Because `ListMeta` / `ListExtraMeta` still carry an open
|
|
30
|
+
* `Record<string, unknown>` index, a CLI may also add its own
|
|
31
|
+
* domain-specific counters (`_total_hits`, `_indices_queried`,
|
|
32
|
+
* `_source_users_total`, …) alongside these — but where a generic field
|
|
33
|
+
* fits, prefer it so cross-CLI tooling and skills can read one shape.
|
|
34
|
+
*
|
|
35
|
+
* When to populate each field:
|
|
36
|
+
* - `_window` — the time/scope window applied, e.g. `"30d"`, `"12 months"`,
|
|
37
|
+
* `"since 2026-06-01"`.
|
|
38
|
+
* - `_limit_applied` — the cap actually in effect (the value the caller
|
|
39
|
+
* passed, or the command's default when they passed nothing).
|
|
40
|
+
* - `_query` — the search / filter expression applied to produce `data`.
|
|
41
|
+
* - `_total` — total matching rows *before* windowing / limiting /
|
|
42
|
+
* filtering. Lets a consumer report "showing N of `_total`".
|
|
43
|
+
* - `_fetched` — how many rows are in *this* response (distinct from
|
|
44
|
+
* `_total`). For list envelopes this equals `meta.count`.
|
|
45
|
+
* - `truncated` — `true` when `_fetched` hit `_limit_applied` and more
|
|
46
|
+
* rows exist beyond this page. Skills MUST consume this rather than
|
|
47
|
+
* counting returned rows to decide whether output is complete.
|
|
48
|
+
* - `availability` — per-response (or per-source) completeness signal.
|
|
49
|
+
* Emit `{status: "degraded", detail}` when a sub-source failed (e.g. a
|
|
50
|
+
* Slack timeout in an aggregator) rather than collapsing to an empty
|
|
51
|
+
* result indistinguishable from "no hits".
|
|
52
|
+
*/
|
|
53
|
+
export interface WindowedMeta {
|
|
54
|
+
/** Time/scope window applied, e.g. `"30d"`, `"since 2026-06-01"`. */
|
|
55
|
+
_window?: string;
|
|
56
|
+
/** The cap actually in effect (caller's value, or the default). */
|
|
57
|
+
_limit_applied?: number;
|
|
58
|
+
/** The search / filter expression applied to produce `data`. */
|
|
59
|
+
_query?: string;
|
|
60
|
+
/** Total matching rows before windowing / limiting / filtering. */
|
|
61
|
+
_total?: number;
|
|
62
|
+
/** Rows in this response (equals `meta.count` for list envelopes). */
|
|
63
|
+
_fetched?: number;
|
|
64
|
+
/** `true` when `_fetched` hit `_limit_applied` — more rows exist. */
|
|
65
|
+
truncated?: boolean;
|
|
66
|
+
/** Per-response completeness signal; mirrors the `el-user` convention. */
|
|
67
|
+
availability?: {
|
|
68
|
+
status: "complete" | "partial" | "degraded";
|
|
69
|
+
/** Human-readable reason, e.g. `"result reached row cap 100"`. */
|
|
70
|
+
detail?: string;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
14
73
|
/**
|
|
15
74
|
* Resource-specific extra metadata that may be added to a list response
|
|
16
75
|
* alongside the canonical `count` (e.g. `query` on search, `team` on
|
|
@@ -18,12 +77,16 @@ export declare function getOutputFormat(): OutputFormat;
|
|
|
18
77
|
* accidentally pass a string `count` and have it silently overridden;
|
|
19
78
|
* the only way to set `count` is via `data.length` inside `outputList`.
|
|
20
79
|
*
|
|
80
|
+
* Intersected with {@link WindowedMeta} so the standard windowing fields
|
|
81
|
+
* (`_total`, `truncated`, `_window`, …) are typed when present, while the
|
|
82
|
+
* open `Record<string, unknown>` index still admits CLI-specific keys.
|
|
83
|
+
*
|
|
21
84
|
* Implementation note: `count?: never` together with `Record<string, unknown>`
|
|
22
85
|
* lets TypeScript accept any other key while disallowing the literal
|
|
23
86
|
* `count` key. The `never`-typed property is impossible to assign, which
|
|
24
87
|
* is what we want for the "no count here" contract.
|
|
25
88
|
*/
|
|
26
|
-
export type ListExtraMeta = Record<string, unknown> & {
|
|
89
|
+
export type ListExtraMeta = Record<string, unknown> & WindowedMeta & {
|
|
27
90
|
count?: never;
|
|
28
91
|
};
|
|
29
92
|
/**
|
|
@@ -34,6 +97,10 @@ export type ListExtraMeta = Record<string, unknown> & {
|
|
|
34
97
|
* read it both for emptiness checks (`.meta.count == 0`) and for the
|
|
35
98
|
* actual magnitude (e.g. logging "found N issues"). A boolean isEmpty
|
|
36
99
|
* would lose the magnitude signal, so `count: number` stays.
|
|
100
|
+
*
|
|
101
|
+
* The open `Record<string, unknown>` index admits the {@link WindowedMeta}
|
|
102
|
+
* fields a windowed list echoes (`_total`, `truncated`, `_window`, …);
|
|
103
|
+
* those are typed at the write site via {@link ListExtraMeta}.
|
|
37
104
|
*/
|
|
38
105
|
export interface ListMeta extends Record<string, unknown> {
|
|
39
106
|
count: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enrichlayer/el-linear",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.0",
|
|
4
4
|
"description": "A pragmatic CLI for Linear.app — deterministic team/label/member resolution, structured issue validation, configurable term enforcement, and a GraphQL escape hatch.",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"types": "dist/main.d.ts",
|