@bookedsolid/rea 0.45.0 → 0.47.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.
@@ -0,0 +1,180 @@
1
+ /**
2
+ * `rea audit timeline [--bucket=HOUR|DAY|<DUR>] [--since=DUR] [--json]`
3
+ * — 0.46.0 charter item 2.
4
+ *
5
+ * Time-bucketed event counts over the audit log. Useful for spotting
6
+ * activity spikes ("what happened during the 3pm CI build?") and
7
+ * day/week cadence patterns.
8
+ *
9
+ * # Bucket sizes
10
+ *
11
+ * - `HOUR` (default) — bucket boundaries align to the UTC hour
12
+ * (`HH:00:00.000Z`)
13
+ * - `DAY` — bucket boundaries align to the UTC day
14
+ * (`YYYY-MM-DDT00:00:00.000Z`)
15
+ * - `<DUR>` (`15m`, `30m`, `1h`, `2h`, `1d`, etc) — arbitrary
16
+ * duration. Boundaries align to the UTC epoch (multiples of the
17
+ * bucket size from `1970-01-01T00:00:00Z`). The `<DUR>` form is
18
+ * useful for sub-hour cadence (`--bucket=15m`) or unusual cuts
19
+ * (`--bucket=6h` for "morning / afternoon / evening / night").
20
+ *
21
+ * Bucket boundaries are half-open `[start, end)` so a record at
22
+ * `15:00:00.000Z` lands in the `15:00 → 16:00` bucket, not the
23
+ * `14:00 → 15:00` one.
24
+ *
25
+ * # Window
26
+ *
27
+ * - `--since=DUR` with same shape as `audit summary` / `audit
28
+ * by-tool` (`24h`, `7d`, etc). When set, the timeline emits a
29
+ * bucket for every interval intersecting `[now - DUR, now]`, even
30
+ * zero-count ones — silence is signal too. Without `--since`,
31
+ * buckets are emitted only for intervals that actually contain a
32
+ * record (no implicit filler — we don't know the operator's
33
+ * intended window).
34
+ *
35
+ * # Output (default `--bucket=HOUR`, last 24h)
36
+ *
37
+ * rea audit timeline (last 24h, hourly)
38
+ * ──────────────────────────────────────
39
+ * 2026-05-16 14:00 ▁▁▁▁▁ 23 events
40
+ * 2026-05-16 15:00 ▁▁▁▁▁▁▁▁ 47 events
41
+ * 2026-05-16 16:00 ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ 127 events ← peak
42
+ * 2026-05-16 17:00 ▁▁▁▁▁▁▁▁▁▁▁▁ 89 events
43
+ * …
44
+ *
45
+ * The histogram bar uses a single Unicode block char (▁) repeated
46
+ * proportionally to peak — chosen for terminal friendliness over the
47
+ * staircase forms (▁▂▃▄▅▆▇█) because the staircase forms render
48
+ * unevenly in many terminals and the proportional bar carries the
49
+ * same information at-a-glance. Bar width is capped at 32 chars so
50
+ * the line still fits in a typical 100-col terminal alongside the
51
+ * timestamp and count.
52
+ *
53
+ * Peak marker (`← peak`) sits next to the bucket with the highest
54
+ * count. Ties go to the first occurrence.
55
+ *
56
+ * # JSON output
57
+ *
58
+ * {
59
+ * "schema_version": 1,
60
+ * "bucket": { "raw": "HOUR", "seconds": 3600 },
61
+ * "window": {
62
+ * "seconds": 86400,
63
+ * "start": "2026-05-16T14:00:00.000Z",
64
+ * "end": "2026-05-17T14:00:00.000Z"
65
+ * },
66
+ * "buckets": [
67
+ * { "start": "2026-05-16T14:00:00.000Z",
68
+ * "end": "2026-05-16T15:00:00.000Z",
69
+ * "count": 23 },
70
+ * …
71
+ * ],
72
+ * "total_events": 287,
73
+ * "peak_index": 2,
74
+ * "files_scanned": ["/abs/path/.rea/audit.jsonl"]
75
+ * }
76
+ */
77
+ import type { Command } from 'commander';
78
+ export declare const AUDIT_TIMELINE_SCHEMA_VERSION = 1;
79
+ /**
80
+ * Hard ceiling on the number of buckets the command will produce. A
81
+ * `--since=7d` with `--bucket=1m` would emit 10,080 buckets — well
82
+ * past what a terminal renderer handles gracefully. Capping at 2000
83
+ * still allows `--bucket=15m --since=21d` (`~2016 buckets`) which
84
+ * covers the realistic ops use cases.
85
+ */
86
+ export declare const MAX_BUCKETS = 2000;
87
+ export declare class AuditTimelineOptionError extends Error {
88
+ constructor(message: string);
89
+ }
90
+ export interface AuditTimelineBucket {
91
+ /** Inclusive start (ISO-8601 UTC). */
92
+ start: string;
93
+ /** Exclusive end (ISO-8601 UTC). `end - start === bucket.seconds`. */
94
+ end: string;
95
+ count: number;
96
+ }
97
+ export interface AuditTimelineResult {
98
+ schema_version: typeof AUDIT_TIMELINE_SCHEMA_VERSION;
99
+ bucket: {
100
+ /** The raw `--bucket` value (e.g. `HOUR`, `15m`). */
101
+ raw: string;
102
+ /** Resolved bucket size in seconds. */
103
+ seconds: number;
104
+ };
105
+ window: {
106
+ seconds: number | null;
107
+ start: string | null;
108
+ end: string | null;
109
+ };
110
+ buckets: AuditTimelineBucket[];
111
+ total_events: number;
112
+ /** Index of the bucket with the highest count. `-1` when no events. */
113
+ peak_index: number;
114
+ files_scanned: string[];
115
+ /**
116
+ * 0.47.0 charter item 2: when `--since` was NOT specified and the
117
+ * audit log spans more than `MAX_BUCKETS` buckets at the requested
118
+ * cadence, the timeline auto-clamps the window to the widest duration
119
+ * that fits. This field carries the duration string that was actually
120
+ * applied (e.g. `"7d"`) — `null` when no clamping fired (the common
121
+ * case). Dashboard consumers use this to flag "the window you saw is
122
+ * not the whole log" in their UI.
123
+ */
124
+ clamped_since: string | null;
125
+ }
126
+ export interface ComputeAuditTimelineOptions {
127
+ /** Override CWD. Tests set this; production uses `process.cwd()`. */
128
+ baseDir?: string;
129
+ /** `--since` (e.g. `24h`, `7d`). Parsed via parseDuration. */
130
+ since?: string;
131
+ /** `--bucket` value (`HOUR`, `DAY`, or duration). Default `HOUR`. */
132
+ bucket?: string;
133
+ /** Test seam — pin "now". */
134
+ now?: Date;
135
+ }
136
+ /**
137
+ * Resolve `--bucket` to a number of seconds. Accepts:
138
+ * - `HOUR` / `H` / `1H` (case-insensitive) → 3600
139
+ * - `DAY` / `D` / `1D` (case-insensitive) → 86400
140
+ * - duration form (`15m`, `30s`, `2h`, `1d`, `1w`) → parsed via
141
+ * `parseDurationSeconds` for shape compatibility with `--since`
142
+ *
143
+ * Bucket size must be >= 1 second; on the upper end we accept any
144
+ * value but `MAX_BUCKETS` will bound the rendered output.
145
+ */
146
+ export declare function resolveBucketSeconds(raw: string): number;
147
+ /**
148
+ * Format a duration in seconds as the coarsest single-unit compact
149
+ * string that round-trips through `parseDurationSeconds`. Mirrors the
150
+ * shape `--since` accepts (`s`/`m`/`h`/`d`/`w`).
151
+ *
152
+ * 0.47.0 charter item 1: powers the helpful-error suggestion + the
153
+ * auto-clamp `clamped_since` field. The largest-unit pass keeps the
154
+ * suggestion readable — `"21d"` not `"1814400s"`.
155
+ */
156
+ export declare function formatDurationCompact(seconds: number): string;
157
+ /**
158
+ * Compute the bucketed timeline. Pure (read-only). Throws
159
+ * `AuditTimelineOptionError` on bad `--since` / `--bucket`; throws on
160
+ * unreadable rotated segments (mirror of audit-summary's stance).
161
+ */
162
+ export declare function computeAuditTimeline(options?: ComputeAuditTimelineOptions): Promise<AuditTimelineResult>;
163
+ /**
164
+ * Render the result as a human-readable terminal block with inline
165
+ * histogram bars. See module docstring for the rendering choices.
166
+ */
167
+ export declare function renderAuditTimeline(result: AuditTimelineResult): string;
168
+ export interface RunAuditTimelineOptions {
169
+ since?: string;
170
+ bucket?: string;
171
+ json?: boolean;
172
+ /** Test seam — pin "now". */
173
+ now?: Date;
174
+ }
175
+ /** Commander entrypoint. */
176
+ export declare function runAuditTimeline(options: RunAuditTimelineOptions): Promise<void>;
177
+ /**
178
+ * Register `rea audit timeline` under the `audit` command group.
179
+ */
180
+ export declare function registerAuditTimelineCommand(auditCommand: Command): void;