@drakulavich/zapara 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [0.1.0] - 2026-09-18
9
+
10
+ ### Added
11
+ - Project scaffold: Bun runs `src/index.ts` directly, `bun run check` typechecks and tests.
12
+ - `analyze()`: hourly buckets with sessions, prompts, decisions, context switches, active minutes, streak and late-night flag, scored 0–100, from real-format transcripts.
13
+ - CLI: `zapara week` and `zapara day` with `--json`, `--to`, `--days`, `--projects`; scans `~/.claude/projects`, skipping subagent transcripts and files older than the window.
14
+ - Week heatmap and day table with `--explain`; colors in a TTY, JSON in a pipe.
15
+ - Inbound messages from subagents, other sessions and background tasks are counted as `reports`, separate from human `prompts`; assistant output tokens are summed once per request as `outputTokens`. Both are measured and shown in the day table, week totals and JSON.
16
+ - `bun run stats`: per-hour signal distributions (n, p50, p75, p90, max, zero) over the active hours of a window, top 8 hours by reports and by human prompts, and a transcript-format drift line (records vs. events recognised by the parser), for comparing the same window across two machines before calibrating `src/score.ts`. Numbers only; never a file path or message text.
17
+ - `zapara card`: the last 14 days as one 2400×1260 picture (PNG, WebP, or the HTML page itself): one of four characters by dominant load, a sentence, the peak hour, the share of hours at each level, three highlights. Rendered locally by `Bun.WebView`; the page embeds its fonts and character sheet and references nothing. `--json` prints the card's data. The only command that writes a file.
18
+ - Published on npm as `@drakulavich/zapara`: `bunx @drakulavich/zapara@latest` runs it without a clone; releases publish from GitHub Actions with OIDC trusted publishing and provenance, no npm token.
19
+
20
+ ### Changed
21
+ - Score weights are integer points of 100 so half-point sums round exactly; the index is the rounded sum of the unrounded weighted parts.
22
+ - Index calibrated on two machines × 14 days: parallel 25 (norm 4 sessions), pace 15 (norm 20 prompts/h), supervision 30 (3·decisions + reports + context switches, norm 45), reading 10 (norm 80k output tokens), streak 10, late night 10. `parts` in JSON and `--explain` are now six: `par pace sup read strk late`.
23
+ - Week footer: the legend drops the ranges and the "none" entry, the totals line drops its prefix and commas, and both are dimmed in a TTY; the level ranges are in `--help`; counts past 9 999 print compact (12k, 1.2M).
24
+ - Day table: an event column that is 0 in every row is left out, and one dimmed line names what the day had none of; the skeleton columns always show.
25
+
26
+ ### Fixed
27
+ - A symlink loop or an unreadable directory anywhere under the projects root no longer aborts the scan as `projects directory not found`; that directory is skipped and every other transcript still counts. Symlinks are not followed.
28
+ - "1 session at once", "1 agent report", "1 prompt": the card sentence and the week footer use the singular for exactly one.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anton Yakutovich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,217 @@
1
+ <h1 align="center">zapara</h1>
2
+
3
+ <p align="center">
4
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
5
+ <a href="https://bun.sh"><img src="https://img.shields.io/badge/runtime-Bun-f9f1e1?logo=bun" alt="Bun"></a>
6
+ </p>
7
+
8
+ <p align="center"><b>How hard was today?</b> zapara reads the transcripts Claude Code already writes on your machine and scores every hour 0–100 from parallel sessions, prompt pace, agent supervision, model output, streak length and late-night work. Nothing leaves the machine, no message text is kept.</p>
9
+
10
+ <p align="center">
11
+ <img src="assets/demo.webp" alt="zapara demo: week heatmap, day table, JSON" width="800">
12
+ </p>
13
+
14
+ Claude Code writes a JSONL transcript for every session under `~/.claude/projects`. zapara reads those files, puts each record in the local hour it happened in, and turns the hour into one number. A week is a heatmap of seven rows by 24 cells; a day is a table with one row per hour and, with `--explain`, the weighted contribution of each component. Nothing is installed into Claude Code, no hook is registered, and no network call is made.
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ # Install Bun if you do not have it (zapara needs 1.4 or newer)
20
+ curl -fsSL https://bun.sh/install | bash
21
+
22
+ # Your week, straight from the registry
23
+ bunx @drakulavich/zapara@latest
24
+
25
+ # A day, with the components behind each index
26
+ bunx @drakulavich/zapara@latest day --explain
27
+
28
+ # The card
29
+ bunx @drakulavich/zapara@latest card
30
+ ```
31
+
32
+ To keep it around, `bun add -g @drakulavich/zapara` puts `zapara` on your PATH. There is no build step and no runtime dependency: Bun runs `src/index.ts` from the package as it is.
33
+
34
+ ## What it looks like
35
+
36
+ Both pictures below come from the synthetic fixture in `tests/fixtures/busy-week`: a calm morning of one session, a five-session storm in the middle of the day, and a late tail that runs past midnight.
37
+
38
+ ```
39
+ 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 peak active
40
+ Mon 14/09 · · · · · · · · · ░ ░ ░ █ █ █ · · · · · ░ ░ · ░ 87 6h00
41
+ Tue 15/09 · · · · · · · · · · ░ ░ ░ ░ ▒ ▒ ▒ ░ · · · · · · 33 4h00
42
+ Wed 16/09 · · · · · · · · · · · · · · · · · · · · · · · · - 0h00
43
+ Thu 17/09 · · · · · · · · · · · ░ ░ · · · · · · · · · · · 14 1h00
44
+ Fri 18/09 · · · · · · · · · · · · · · · ▓ · · · · · · · · 82 1h00
45
+ Sat 19/09 ░ ░ · · · · · · · · · · · · · · · · · · · · · · 24 1h00
46
+ Sun 20/09 · · · · · · · · · · · · · · · · · · · · · · · · - 0h00
47
+
48
+ ░ calm ▒ warming ▓ heating █ fried
49
+ 13h00 active 346 prompts 0 reports 100 decisions 5 sessions at once
50
+ ```
51
+
52
+ ```
53
+ hour index level sess prompts intr rej quest plan mode ctx-sw streak out-tok par pace sup read strk late
54
+ 09:00 9 Calm 1 6 0 0 0 0 0 0 53m 600 0 4.5 0 0.1 4.4 0
55
+ 10:00 14 Calm 1 6 0 0 0 0 0 0 113m 600 0 4.5 0 0.1 9.4 0
56
+ 11:00 15 Calm 1 6 0 0 0 0 0 0 173m 600 0 4.5 0 0.1 10 0
57
+ 12:00 87 Fried 5 55 20 1 1 1 2 54 237m 55.0k 25 15 30 6.9 10 0
58
+ 13:00 87 Fried 5 55 20 1 1 1 2 54 297m 55.0k 25 15 30 6.9 10 0
59
+ 14:00 87 Fried 5 55 20 1 1 1 2 54 357m 55.0k 25 15 30 6.9 10 0
60
+ 20:00 9 Calm 1 6 0 0 0 0 0 0 53m 600 0 4.5 0 0.1 4.4 0
61
+ 21:00 14 Calm 1 6 0 0 0 0 0 0 113m 600 0 4.5 0 0.1 9.4 0
62
+ 23:00 19 Calm 1 6 0 0 0 0 0 0 53m 600 0 4.5 0 0.1 4.4 10
63
+ no reports today
64
+ ```
65
+
66
+ <details>
67
+ <summary><b>Reproduce these pictures from the repository</b></summary>
68
+
69
+ Two commands in a terminal reproduce them. The fixture's timestamps are UTC and zapara buckets by local time, so pin the zone to get these exact hours:
70
+
71
+ ```bash
72
+ TZ=UTC bun src/index.ts week --projects tests/fixtures/busy-week --to 2026-09-20 --no-color
73
+ TZ=UTC bun src/index.ts day 2026-09-14 --projects tests/fixtures/busy-week --explain --no-color
74
+ ```
75
+
76
+ The grid is a fixed 98 columns wide, 100 with its hour header, and does not reflow, so it needs a terminal at least that wide.
77
+
78
+ </details>
79
+
80
+ ## Share a card
81
+
82
+ `zapara card` turns your last two weeks into one picture: a character named after the kind of load that dominates your hours, the sentence behind it, the peak hour, the share of calm, warming, heating and fried hours, and three highlights. No dates, no hour totals, nothing that reads as a timesheet.
83
+
84
+ ```bash
85
+ zapara card # writes zapara-card.png in the current directory
86
+ zapara card --out card.webp # WebP instead; --out card.html writes the page itself
87
+ ```
88
+
89
+ ```
90
+ The Marathoner: Longest streak 7h53m without a break, 68% of your hours calm.
91
+ wrote zapara-card.png
92
+ ```
93
+
94
+ <p align="center"><img src="assets/card.webp" alt="zapara card: The Marathoner, longest streak 7h53m, 68% of hours calm" width="800"></p>
95
+
96
+ This one comes from the same `busy-week` fixture as the pictures above. The picture is taken by a headless browser that Bun drives: WebKit on macOS, an installed Google Chrome elsewhere, so on Linux or Windows install Chrome, or write `--out card.html` and open the page in any browser.
97
+
98
+ ## Usage
99
+
100
+ | Command | What it does |
101
+ |---|---|
102
+ | `zapara` | Same as `zapara week`. |
103
+ | `zapara week` | The last 7 days ending today, in local time. |
104
+ | `zapara week --days 14 --to 2026-09-17` | Any window. `--days` takes an integer from 1 to 90. |
105
+ | `zapara day` | Today, one row per hour that had activity. |
106
+ | `zapara day 2026-09-14 --explain` | One day, with the six weighted components behind each index. |
107
+ | `zapara card` | The last 14 days as one shareable picture, `zapara-card.png` in the current directory. |
108
+ | `zapara card --days 30 --out me.webp` | Any window from 1 to 90 days; `.png`, `.webp` or `.html` by extension. `--json` prints the card's data instead. |
109
+
110
+ | Flag | What it does |
111
+ |---|---|
112
+ | `--json` | Print the whole window as one JSON document instead of a table. |
113
+ | `--projects <dir>` | Read this directory instead of `~/.claude/projects`. |
114
+ | `--out <path>` | Where `card` writes; the extension picks the format. |
115
+ | `--no-color` | Plain glyphs with no ANSI codes. `NO_COLOR` in the environment does the same. |
116
+ | `--help` | Usage, exit 0. |
117
+ | `--version` | The version from `package.json`, exit 0. |
118
+
119
+ Levels: calm 0–29, warming 30–59, heating 60–84, fried 85–100.
120
+
121
+ `week` and `day` print a text table when stdout is a terminal and JSON otherwise, so `zapara week | cat` prints JSON; there is no flag to force text in a pipe yet. `card` always writes its file and prints its two lines, piped or not, and only `card --json` prints JSON.
122
+
123
+ Exit codes are 0 on success, 1 when the projects directory cannot be read, and 2 for a usage error such as a bad date or an unknown flag. A window with no data prints an empty grid and exits 0.
124
+
125
+ ## Privacy
126
+
127
+ zapara reads `~/.claude/projects/**/*.jsonl`, taking only files modified inside the window and skipping subagent transcripts under `subagents/`. Message text is compared against a few fixed markers, for interrupts, tool rejections and inbound agent messages, and then discarded. What survives into an event is a timestamp, a session id, an event kind and a token count.
128
+
129
+ No message text, prompt length, file path or session title is kept, written or printed. The CLI never prints a path it derived or read, not even the projects root when it cannot open it. Nothing is sent anywhere, no file is written except the card you ask for, and nothing is installed into Claude Code.
130
+
131
+ ## Limits
132
+
133
+ - Time is local and buckets are whole hours, so an hour that straddles midnight or a daylight-saving change is bucketed by the local clock. On a fall-back day two wall-clock hours share one label and merge.
134
+ - Only Claude Code transcripts are read. Work in other tools, and time away from the keyboard, is invisible.
135
+ - Files are chosen by modification time. A very old session touched today is read in full, but only its in-window events count.
136
+ - The transcript format is Claude Code's private format, built against version 2.1.274, and it may drift. `bun run stats` shows when it has.
137
+ - The norms come from two machines of one user working in auto mode. They are a starting point for a conversation about the metric, not a study.
138
+ - The 98-column grid does not adapt to a narrow terminal.
139
+ - For `week` and `day` a pipe always gets JSON, and there is no flag to ask for text instead.
140
+ - The card needs a browser engine: WebKit comes with macOS, elsewhere Google Chrome must be installed. `--out card.html` works everywhere.
141
+
142
+ ## Under the hood
143
+
144
+ The formula behind the number and the transcript record behind every column, for when the number surprises you.
145
+
146
+ <details>
147
+ <summary><b>How the index works</b></summary>
148
+
149
+ Every hour that had activity gets six components normalized into `[0, 1]` and summed with integer weights:
150
+
151
+ ```
152
+ parallel = clamp((sessions - 1) / 4) # 1 session → 0, 3 → 0.5, 5+ → 1
153
+ pace = clamp(prompts / 20) # 10 prompts/hour → 0.5, 20+ → 1
154
+ supervision = clamp((3 * decisions + reports + contextSwitches) / 45) # 15 decisions alone → 1; 45 reports alone → 1
155
+ reading = clamp(outputTokens / 80000) # 40k → 0.5, 80k+ → 1
156
+ streak = clamp(streakMin / 120) # 60 min → 0.5, 2h+ → 1
157
+ late = lateNight ? 1 : 0
158
+
159
+ index = round(25*parallel + 15*pace + 30*supervision + 10*reading + 10*streak + 10*late)
160
+ ```
161
+
162
+ `decisions` is the sum of interrupts, tool rejections, questions, plan reviews and permission-mode switches. Without the late-night flag the index tops out at 90. An hour with no activity has no index at all: it renders as `·` and is `null` in JSON.
163
+
164
+ | Level | Range |
165
+ |---|---|
166
+ | Calm | 0–29 |
167
+ | Warming | 30–59 |
168
+ | Heating | 60–84 |
169
+ | Fried | 85–100 |
170
+
171
+ The norms come from two machines, 14 days each, of real transcripts covering 116 and 114 active hours. The surprise in that data was how rare explicit decisions are: in auto mode the p90 is 3 decisions per hour, so a component built on decisions alone reads near zero on hours that felt heavy. What those hours actually cost is reading the reports agents send back, switching between sessions, and getting through the volume of model output, which is why supervision carries 30 points and reading 10. Human prompts reached a p90 of 13 per hour on one machine and 20 on the other, hence the pace norm of 20. The parallel-session threshold follows the research this project started from rather than the transcripts: BCG and HBR report that productivity drops past three simultaneous AI tools, and Osmani makes the same point as three focused teammates beating five scattered ones.
172
+
173
+ Weights and norms live in one exported constant in `src/score.ts`, so a recalibration is one diff there plus a line in `CHANGELOG.md`.
174
+
175
+ </details>
176
+
177
+ <details>
178
+ <summary><b>What each column of the day table counts</b></summary>
179
+
180
+ | Column | What it counts |
181
+ |---|---|
182
+ | `sess` | Distinct session ids with at least one user or assistant record in the hour. |
183
+ | `prompts` | Messages the human typed. A `user` record whose text is neither an interrupt marker nor an agent-message marker; `isMeta` and sidechain records are excluded. |
184
+ | `rep` | Inbound messages from subagents, other sessions and background tasks. A `user` record whose text starts with one of the agent-message markers, which is something to read and react to rather than something typed. |
185
+ | `intr` | Interrupts. A `user` record whose text block starts with `[Request interrupted by user`, covering both the plain and the tool-use form. |
186
+ | `rej` | Tool rejections. A `tool_result` block saying the user did not want to proceed with that tool use. |
187
+ | `quest` | `AskUserQuestion` tool calls in an assistant message, one per block. |
188
+ | `plan` | `ExitPlanMode` tool calls in an assistant message, one per block. |
189
+ | `mode` | Permission-mode switches. A `permission-mode` record whose mode differs from the previous one; the first record of a session sets the baseline and repeats of the same mode count nothing. |
190
+ | `ctx-sw` | Context switches. Over the hour's prompts in time order, the number of consecutive pairs that came from different sessions. |
191
+ | `streak` | Minutes since the current activity streak began, which may reach back before the hour. A gap longer than 10 minutes between records breaks the streak. |
192
+ | `out-tok` | Assistant output tokens, summed once per request and only for requests that produced a text block. Claude Code repeats the same usage on each content block of a response, and a request holding only tool calls is not text anyone reads. |
193
+
194
+ `bun run stats --days 14` is the tool the norms were set with. It prints the per-hour distribution of each signal over the active hours of a window (n, p50, p75, p90, max, and how many hours were zero), the top hours by reports and by human prompts, and a format-drift line comparing records seen against events the parser recognised. Run it on another machine, or after a Claude Code update, to see whether the norms and the parser still fit. It prints numbers and nothing else.
195
+
196
+ </details>
197
+
198
+ ## Development
199
+
200
+ ```bash
201
+ git clone git@github.com:drakulavich/zapara.git
202
+ cd zapara
203
+ bun install
204
+ bun link
205
+ ```
206
+
207
+ `bun link` registers the clone's `bin` entry, so `zapara` runs this checkout; without it, `bun src/index.ts week` does the same thing.
208
+
209
+ ```bash
210
+ bun run check # tsc --noEmit, then the test suite under TZ=UTC
211
+ ```
212
+
213
+ Tests are fixture-driven: they build or load transcripts in the real Claude Code format and assert the statistics that come out of the public seams, `analyze()`, `report()` and the CLI itself. No test imports the parser, the deriver or the scanner, so refactoring internals never touches a test. The rules every change follows are in [CLAUDE.md](CLAUDE.md), the design is in [docs/superpowers/specs/2026-09-17-zapara-design.md](docs/superpowers/specs/2026-09-17-zapara-design.md), and every change is recorded in [CHANGELOG.md](CHANGELOG.md).
214
+
215
+ ## License
216
+
217
+ MIT. See [LICENSE](LICENSE).
Binary file
@@ -0,0 +1,92 @@
1
+ Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+ -----------------------------------------------------------
8
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
9
+ -----------------------------------------------------------
10
+
11
+ PREAMBLE
12
+ The goals of the Open Font License (OFL) are to stimulate worldwide
13
+ development of collaborative font projects, to support the font creation
14
+ efforts of academic and linguistic communities, and to provide a free and
15
+ open framework in which fonts may be shared and improved in partnership
16
+ with others.
17
+
18
+ The OFL allows the licensed fonts to be used, studied, modified and
19
+ redistributed freely as long as they are not sold by themselves. The
20
+ fonts, including any derivative works, can be bundled, embedded,
21
+ redistributed and/or sold with any software provided that any reserved
22
+ names are not used by derivative works. The fonts and derivatives,
23
+ however, cannot be released under any other type of license. The
24
+ requirement for fonts to remain under this license does not apply
25
+ to any document created using the fonts or their derivatives.
26
+
27
+ DEFINITIONS
28
+ "Font Software" refers to the set of files released by the Copyright
29
+ Holder(s) under this license and clearly marked as such. This may
30
+ include source files, build scripts and documentation.
31
+
32
+ "Reserved Font Name" refers to any names specified as such after the
33
+ copyright statement(s).
34
+
35
+ "Original Version" refers to the collection of Font Software components as
36
+ distributed by the Copyright Holder(s).
37
+
38
+ "Modified Version" refers to any derivative made by adding to, deleting,
39
+ or substituting -- in part or in whole -- any of the components of the
40
+ Original Version, by changing formats or by porting the Font Software to a
41
+ new environment.
42
+
43
+ "Author" refers to any designer, engineer, programmer, technical
44
+ writer or other person who contributed to the Font Software.
45
+
46
+ PERMISSION AND CONDITIONS
47
+ Permission is hereby granted, free of charge, to any person obtaining
48
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
49
+ redistribute, and sell modified and unmodified copies of the Font
50
+ Software, subject to the following conditions:
51
+
52
+ 1) Neither the Font Software nor any of its individual components,
53
+ in Original or Modified Versions, may be sold by itself.
54
+
55
+ 2) Original or Modified Versions of the Font Software may be bundled,
56
+ redistributed and/or sold with any software, provided that each copy
57
+ contains the above copyright notice and this license. These can be
58
+ included either as stand-alone text files, human-readable headers or
59
+ in the appropriate machine-readable metadata fields within text or
60
+ binary files as long as those fields can be easily viewed by the user.
61
+
62
+ 3) No Modified Version of the Font Software may use the Reserved Font
63
+ Name(s) unless explicit written permission is granted by the corresponding
64
+ Copyright Holder. This restriction only applies to the primary font name as
65
+ presented to the users.
66
+
67
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
68
+ Software shall not be used to promote, endorse or advertise any
69
+ Modified Version, except to acknowledge the contribution(s) of the
70
+ Copyright Holder(s) and the Author(s) or with their explicit written
71
+ permission.
72
+
73
+ 5) The Font Software, modified or unmodified, in part or in whole,
74
+ must be distributed entirely under this license, and must not be
75
+ distributed under any other license. The requirement for fonts to
76
+ remain under this license does not apply to any document created
77
+ using the Font Software.
78
+
79
+ TERMINATION
80
+ This license becomes null and void if any of the above conditions are
81
+ not met.
82
+
83
+ DISCLAIMER
84
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
85
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
86
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
87
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
88
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
89
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
90
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
91
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
92
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
1
+ Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
Binary file
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@drakulavich/zapara",
3
+ "version": "0.1.0",
4
+ "description": "Cognitive load index for people driving Claude Code, computed locally from transcripts",
5
+ "license": "MIT",
6
+ "author": "Anton Yakutovich",
7
+ "repository": { "type": "git", "url": "git+https://github.com/drakulavich/zapara.git" },
8
+ "homepage": "https://github.com/drakulavich/zapara#readme",
9
+ "bugs": "https://github.com/drakulavich/zapara/issues",
10
+ "keywords": ["claude-code", "cognitive-load", "developer-experience", "cli", "bun"],
11
+ "type": "module",
12
+ "bin": { "zapara": "src/index.ts" },
13
+ "files": ["src/", "assets/fonts/", "assets/characters.webp", "CHANGELOG.md", "!src/**/*.test.ts"],
14
+ "publishConfig": { "access": "public" },
15
+ "engines": { "bun": ">=1.4.0" },
16
+ "scripts": {
17
+ "dev": "bun run src/index.ts",
18
+ "stats": "bun scripts/signal-stats.ts",
19
+ "test": "TZ=UTC bun test",
20
+ "typecheck": "tsc --noEmit",
21
+ "check": "bun run typecheck && bun run test"
22
+ },
23
+ "devDependencies": {
24
+ "@types/bun": "^1.4.0",
25
+ "typescript": "^7.0.2"
26
+ }
27
+ }
package/src/analyze.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { derive } from "./derive.ts";
2
+ import { parseTranscript } from "./parse.ts";
3
+ import type { Day, Transcript, Window } from "./types.ts";
4
+
5
+ // The core's entry point: transcripts already in memory, in the real JSONL format, in.
6
+ // Day[] out. Transcripts are sorted by path so file discovery order cannot change a result.
7
+ export function analyze(transcripts: Transcript[], w: Window): Day[] {
8
+ const events = [...transcripts]
9
+ .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0))
10
+ .flatMap((t) => parseTranscript(t.text));
11
+ return derive(events, w);
12
+ }