estela 0.1.39 → 0.2.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.
Files changed (90) hide show
  1. package/README.md +96 -0
  2. package/dist/billing/assign.d.ts +45 -0
  3. package/dist/billing/assign.d.ts.map +1 -0
  4. package/dist/billing/assign.js +159 -0
  5. package/dist/billing/assign.js.map +1 -0
  6. package/dist/billing/assign.test.d.ts +2 -0
  7. package/dist/billing/assign.test.d.ts.map +1 -0
  8. package/dist/billing/assign.test.js +153 -0
  9. package/dist/billing/assign.test.js.map +1 -0
  10. package/dist/bin.js +23 -1
  11. package/dist/bin.js.map +1 -1
  12. package/dist/cli-import-recover.test.d.ts +2 -0
  13. package/dist/cli-import-recover.test.d.ts.map +1 -0
  14. package/dist/cli-import-recover.test.js +191 -0
  15. package/dist/cli-import-recover.test.js.map +1 -0
  16. package/dist/cli-quota.test.d.ts +2 -0
  17. package/dist/cli-quota.test.d.ts.map +1 -0
  18. package/dist/cli-quota.test.js +281 -0
  19. package/dist/cli-quota.test.js.map +1 -0
  20. package/dist/cli-statusline.test.d.ts +2 -0
  21. package/dist/cli-statusline.test.d.ts.map +1 -0
  22. package/dist/cli-statusline.test.js +333 -0
  23. package/dist/cli-statusline.test.js.map +1 -0
  24. package/dist/cli.d.ts.map +1 -1
  25. package/dist/cli.js +350 -49
  26. package/dist/cli.js.map +1 -1
  27. package/dist/db/store.d.ts +12 -1
  28. package/dist/db/store.d.ts.map +1 -1
  29. package/dist/db/store.js +52 -0
  30. package/dist/db/store.js.map +1 -1
  31. package/dist/demo.d.ts.map +1 -1
  32. package/dist/demo.js +53 -0
  33. package/dist/demo.js.map +1 -1
  34. package/dist/i18n/en.d.ts.map +1 -1
  35. package/dist/i18n/en.js +68 -0
  36. package/dist/i18n/en.js.map +1 -1
  37. package/dist/metrics/quota.d.ts +226 -0
  38. package/dist/metrics/quota.d.ts.map +1 -0
  39. package/dist/metrics/quota.js +291 -0
  40. package/dist/metrics/quota.js.map +1 -0
  41. package/dist/metrics/quota.test.d.ts +2 -0
  42. package/dist/metrics/quota.test.d.ts.map +1 -0
  43. package/dist/metrics/quota.test.js +325 -0
  44. package/dist/metrics/quota.test.js.map +1 -0
  45. package/dist/project-of.d.ts +52 -0
  46. package/dist/project-of.d.ts.map +1 -0
  47. package/dist/project-of.js +124 -0
  48. package/dist/project-of.js.map +1 -0
  49. package/dist/project-of.test.d.ts +2 -0
  50. package/dist/project-of.test.d.ts.map +1 -0
  51. package/dist/project-of.test.js +203 -0
  52. package/dist/project-of.test.js.map +1 -0
  53. package/dist/quota.d.ts +27 -0
  54. package/dist/quota.d.ts.map +1 -0
  55. package/dist/quota.js +79 -0
  56. package/dist/quota.js.map +1 -0
  57. package/dist/server.d.ts.map +1 -1
  58. package/dist/server.js +17 -26
  59. package/dist/server.js.map +1 -1
  60. package/dist/server.test.js +37 -0
  61. package/dist/server.test.js.map +1 -1
  62. package/dist/statusline-cache.d.ts +35 -0
  63. package/dist/statusline-cache.d.ts.map +1 -0
  64. package/dist/statusline-cache.js +57 -0
  65. package/dist/statusline-cache.js.map +1 -0
  66. package/dist/statusline-install.d.ts +52 -0
  67. package/dist/statusline-install.d.ts.map +1 -0
  68. package/dist/statusline-install.js +115 -0
  69. package/dist/statusline-install.js.map +1 -0
  70. package/dist/statusline-run.d.ts +8 -0
  71. package/dist/statusline-run.d.ts.map +1 -0
  72. package/dist/statusline-run.js +256 -0
  73. package/dist/statusline-run.js.map +1 -0
  74. package/dist/statusline.d.ts +71 -0
  75. package/dist/statusline.d.ts.map +1 -0
  76. package/dist/statusline.js +139 -0
  77. package/dist/statusline.js.map +1 -0
  78. package/dist/statusline.test.d.ts +2 -0
  79. package/dist/statusline.test.d.ts.map +1 -0
  80. package/dist/statusline.test.js +197 -0
  81. package/dist/statusline.test.js.map +1 -0
  82. package/dist/watchers/claude.d.ts +11 -1
  83. package/dist/watchers/claude.d.ts.map +1 -1
  84. package/dist/watchers/claude.js +32 -15
  85. package/dist/watchers/claude.js.map +1 -1
  86. package/package.json +1 -1
  87. package/web/app.css +36 -0
  88. package/web/app.js +61 -1
  89. package/web/i18n.js +28 -0
  90. package/web/index.html +4 -1
package/README.md CHANGED
@@ -116,6 +116,11 @@ Two things trip people up before Estela even starts:
116
116
  the standalone Node, then `nvm install lts` and `nvm use lts` from an
117
117
  administrator terminal. `where.exe npm` should list a single path.
118
118
 
119
+ A session in a subfolder or a git worktree counts for its repository's
120
+ project. If an import would add hours to what you had already imported, Estela
121
+ shows you how many per project and asks first (`estela import --yes` skips the
122
+ question); it never moves hours between projects or touches an approved day.
123
+
119
124
  ## Reporting to a client
120
125
 
121
126
  Projects are created as internal and without a rate, because making one up
@@ -189,6 +194,35 @@ different machine, pass `--token` with the existing one, or your client ends up
189
194
  with a dead link. The Free plan allows one published dashboard at a time; Pro
190
195
  and Teams have no limit.
191
196
 
197
+ The dashboard's footer says "Hours filled in by Estela", linking to
198
+ getestela.dev. On Pro and Teams, `--no-credit` removes that line.
199
+
200
+ ## Showing what you built
201
+
202
+ A badge for your project's README, with its measured hours and what the AI
203
+ cost:
204
+
205
+ ```sh
206
+ estela badge # the project for the repo you're in
207
+ estela badge --project acme-web
208
+ ```
209
+
210
+ It prints a Markdown line with a static [shields.io](https://shields.io) image,
211
+ something like `Built in 42 h · $18 of AI`. Nothing is hosted and nothing is
212
+ looked up: the numbers are baked into the URL, so run it again to update them.
213
+ It only counts **measured** hours, never the ones estimated from commits.
214
+
215
+ And a receipt of your week (or of your whole history) as a PNG:
216
+
217
+ ```sh
218
+ estela receipt --week
219
+ ```
220
+
221
+ Measured versus estimated hours, the AI cost, what caching saved you, and the
222
+ most expensive project and branch. It's drawn on your machine and stays there.
223
+ Project and branch names are left out by default, because they're usually a
224
+ client's; add `--names` to include them.
225
+
192
226
  ## What the AI actually costs
193
227
 
194
228
  On a flat subscription, your real spend isn't the sum of the tokens: it's the
@@ -202,6 +236,68 @@ estela ai-cost
202
236
  Cache is counted separately because it's usually most of the bill — ignoring it
203
237
  underestimated spend fivefold.
204
238
 
239
+ ## Which project is eating your quota
240
+
241
+ On Claude Max/Pro or Codex with a subscription, the quota runs out before you
242
+ expect it and nothing tells you where it went. `estela quota` splits it by
243
+ project:
244
+
245
+ ```sh
246
+ estela quota # current 5-hour window and this week, per project
247
+ estela quota --weighted # the % by list price instead of by tokens
248
+ estela quota --json # the same, for scripts
249
+ ```
250
+
251
+ Tokens (input, output, cache read and cache write) per project, for the current
252
+ 5-hour window and for this week (Monday to today, in your time zone), plus this
253
+ week against the average of your previous 4 over the same stretch. Claude Code
254
+ and Codex are shown separately: they draw on different quotas. It's also a card
255
+ in the Summary tab of `estela web`, and it's free.
256
+
257
+ A session in a subfolder or in a git worktree counts for its repo's project;
258
+ a folder that isn't a project shows up under its git root's name. The % is
259
+ by tokens by default; `--weighted` splits it by each model's list price
260
+ instead, which is not how the provider counts your limit. With the status
261
+ line installed (below), the 5-hour window is the one Claude Code reports
262
+ rather than an estimate.
263
+
264
+ What it never does is tell you how much you have left: Anthropic and OpenAI
265
+ don't publish their plans' limits, so any "X tokens left" would be made up. The
266
+ 5-hour window is an estimate — how its start is rounded isn't public, and
267
+ anything you use on claude.ai or another machine counts too but isn't on this
268
+ one. Copilot is left out because it doesn't record reliable tokens. Everything
269
+ is calculated on your machine.
270
+
271
+ ## A line under every Claude Code session
272
+
273
+ ```sh
274
+ npm install -g estela # the status line needs estela on your PATH
275
+ estela statusline install
276
+ ```
277
+
278
+ In a repository that isn't a project yet it shows `estela · web (no project) ·
279
+ estela setup`, and outside git just `estela · no project`. Each Claude Code
280
+ session in a project shows a line like this:
281
+
282
+ ```
283
+ estela · Brightside Health › brightside-portal · today 2h14 · this project 21% · week 38% · 5h 62%
284
+ ```
285
+
286
+ Hours measured today on this project (the same number the report will
287
+ give), this project's share of your Claude Code usage this week, and — only
288
+ if Claude Code sends them — its own weekly and 5-hour limit percentages, as
289
+ they come. Estela never estimates a limit or counts down to a reset. The
290
+ 5-hour figure turns amber from 80%. On a narrow terminal the line drops the
291
+ 5-hour figure first, then the week, then shortens the name, then this
292
+ project, then today; `estela` always stays. It runs in about 50 ms and only
293
+ reads what's new in the current session's transcript.
294
+
295
+ `install` merges the block into `~/.claude/settings.json` without touching
296
+ anything else, after making a backup. If you already have a status line it
297
+ won't overwrite it: `--force` replaces it, `--append` shows yours after
298
+ Estela's. `estela statusline uninstall` removes it (and puts yours back if
299
+ you used `--append`).
300
+
205
301
  ## Hours no import will infer
206
302
 
207
303
  Meetings, travel, research, and development without an agent that didn't leave
@@ -0,0 +1,45 @@
1
+ import type { DatabaseSync } from "node:sqlite";
2
+ import type { TimeEntry } from "@estela/shared";
3
+ import { type WorkBlock } from "./sessionize.js";
4
+ /**
5
+ * De bloques de trabajo a imputaciones: a qué proyecto va cada uno y con qué
6
+ * id se guarda. Lo usan `estela import` y el import automático del panel, que
7
+ * antes lo tenían copiado cada uno por su lado.
8
+ *
9
+ * La raíz git (worktrees, subcarpetas de un repo sin la carpeta exacta
10
+ * registrada) recupera horas que antes se perdían, con tres reglas:
11
+ *
12
+ * 1. Solo se reasigna lo que hoy NO tiene proyecto. La carpeta tal cual se
13
+ * mira primero, así que nada de lo ya asignado cambia de proyecto.
14
+ * 2. Un día aprobado o facturado de ese proyecto no se toca: las horas que se
15
+ * recuperarían ahí se informan (`blocked`), no se aplican.
16
+ * 3. Recuperar es opcional (`recover`): la primera vez lo confirma la persona.
17
+ */
18
+ export interface PlannedEntry {
19
+ readonly entry: Omit<TimeEntry, "id"> & {
20
+ id: string;
21
+ };
22
+ /** Segundos que esta imputación gana por la raíz git (0 si no cambia). */
23
+ readonly recoveredSeconds: number;
24
+ }
25
+ export interface RecoveryBlocked {
26
+ readonly projectId: string;
27
+ readonly day: string;
28
+ readonly seconds: number;
29
+ }
30
+ export interface AssignmentPlan {
31
+ readonly entries: readonly PlannedEntry[];
32
+ /** Bloques tras agrupar por rama y día, con y sin proyecto. */
33
+ readonly grouped: number;
34
+ /** De esos, los que siguen sin proyecto. */
35
+ readonly unassigned: number;
36
+ /** Segundos recuperados que SÍ se aplican, por proyecto. */
37
+ readonly recovered: ReadonlyMap<string, number>;
38
+ /** Lo que se recuperaría en días aprobados o facturados: no se aplica. */
39
+ readonly blocked: readonly RecoveryBlocked[];
40
+ }
41
+ export declare function entryId(projectId: string, day: string, branch: string | null): string;
42
+ export declare function planEntries(db: DatabaseSync, raw: readonly WorkBlock[], options: {
43
+ readonly recover: boolean;
44
+ }): AssignmentPlan;
45
+ //# sourceMappingURL=assign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.d.ts","sourceRoot":"","sources":["../../src/billing/assign.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAKhD,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAErF;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,0EAA0E;IAC1E,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAC1C,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,4CAA4C;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;CAC9C;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAKrF;AAED,wBAAgB,WAAW,CACzB,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,SAAS,EAAE,EAAE,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAClF,cAAc,CAwEhB"}
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.entryId = entryId;
37
+ exports.planEntries = planEntries;
38
+ const shared_1 = require("@estela/shared");
39
+ const store = __importStar(require("../db/store.js"));
40
+ const project_of_js_1 = require("../project-of.js");
41
+ const sessionize_js_1 = require("./sessionize.js");
42
+ function entryId(projectId, day, branch) {
43
+ // Determinista (proyecto + día + rama) para que reimportar actualice en vez
44
+ // de duplicar. La fecha, la LOCAL: la misma que usa el servidor.
45
+ const slug = (branch ?? "sin-rama").replace(/[^a-zA-Z0-9]+/g, "-");
46
+ return `te_${projectId}_${day}_${slug}`;
47
+ }
48
+ function planEntries(db, raw, options) {
49
+ const ownerOf = (0, project_of_js_1.ownerResolver)(db);
50
+ const direct = (repo) => (repo ? store.projectForRepo(db, repo) : null);
51
+ const viaRoot = (repo) => {
52
+ if (!repo)
53
+ return null;
54
+ const o = ownerOf(repo);
55
+ return o.kind === "project" ? o.projectId : null;
56
+ };
57
+ // Lo de siempre: la carpeta tal cual. Se agrupa por PROYECTO, no por ruta:
58
+ // `repo/` y `repo/src/UI` son el mismo proyecto, y agrupar por ruta daba dos
59
+ // bloques que luego se pisaban al guardarse con el mismo id.
60
+ const keyDirect = (b) => direct(b.repoPath) ?? b.repoPath ?? "";
61
+ const groupedBase = (0, sessionize_js_1.groupByBranchAndDay)(raw, keyDirect);
62
+ const base = byId(groupedBase, direct);
63
+ if (!options.recover) {
64
+ return {
65
+ entries: [...base.values()].map((g) => ({ entry: toEntry(db, g.projectId, g.block), recoveredSeconds: 0 })),
66
+ grouped: groupedBase.length,
67
+ unassigned: groupedBase.filter((b) => !direct(b.repoPath)).length,
68
+ recovered: new Map(), blocked: [],
69
+ };
70
+ }
71
+ // Con la raíz git, pero solo para lo que no tenía proyecto (regla 1).
72
+ const assigned = (repo) => direct(repo) ?? viaRoot(repo);
73
+ const keyFull = (b) => assigned(b.repoPath) ?? b.repoPath ?? "";
74
+ const groupedFull = (0, sessionize_js_1.groupByBranchAndDay)(raw, keyFull);
75
+ const full = byId(groupedFull, assigned);
76
+ // Qué imputaciones cambian: las que reciben algún bloque recuperado.
77
+ const touched = new Set();
78
+ for (const b of raw) {
79
+ if (direct(b.repoPath))
80
+ continue;
81
+ const p = viaRoot(b.repoPath);
82
+ if (p)
83
+ touched.add(entryId(p, (0, shared_1.localDate)(b.startedAt), b.branch));
84
+ }
85
+ const lockedDays = new Map();
86
+ const locked = (projectId, day) => {
87
+ const k = `${projectId}\0${day}`;
88
+ if (!lockedDays.has(k)) {
89
+ lockedDays.set(k, !!db.prepare(`SELECT 1 FROM time_entries WHERE project_id = ? AND local_date = ?
90
+ AND (approved = 1 OR invoice_id IS NOT NULL) LIMIT 1`).get(projectId, day));
91
+ }
92
+ return lockedDays.get(k);
93
+ };
94
+ const entries = [];
95
+ const recovered = new Map();
96
+ const blocked = [];
97
+ for (const [id, g] of full) {
98
+ const before = base.get(id);
99
+ if (!touched.has(id)) {
100
+ entries.push({ entry: toEntry(db, g.projectId, g.block), recoveredSeconds: 0 });
101
+ continue;
102
+ }
103
+ const gain = Math.max(0, g.block.seconds - (before?.block.seconds ?? 0));
104
+ const day = (0, shared_1.localDate)(g.block.startedAt);
105
+ if (locked(g.projectId, day)) {
106
+ // Regla 2: el día se queda como estaba; si antes no había nada, nada.
107
+ if (before)
108
+ entries.push({ entry: toEntry(db, before.projectId, before.block), recoveredSeconds: 0 });
109
+ if (gain > 0)
110
+ blocked.push({ projectId: g.projectId, day, seconds: gain });
111
+ continue;
112
+ }
113
+ entries.push({ entry: toEntry(db, g.projectId, g.block), recoveredSeconds: gain });
114
+ if (gain > 0)
115
+ recovered.set(g.projectId, (recovered.get(g.projectId) ?? 0) + gain);
116
+ }
117
+ return {
118
+ entries, grouped: groupedFull.length,
119
+ unassigned: groupedFull.filter((b) => !assigned(b.repoPath)).length,
120
+ recovered, blocked,
121
+ };
122
+ }
123
+ /** Los bloques agrupados con proyecto, por el id con el que se guardarían. */
124
+ function byId(blocks, projectOf) {
125
+ const out = new Map();
126
+ for (const block of blocks) {
127
+ const projectId = projectOf(block.repoPath);
128
+ if (!projectId)
129
+ continue;
130
+ out.set(entryId(projectId, (0, shared_1.localDate)(block.startedAt), block.branch), { projectId, block });
131
+ }
132
+ return out;
133
+ }
134
+ function toEntry(db, projectId, block) {
135
+ const project = store.getProject(db, projectId);
136
+ return {
137
+ id: entryId(projectId, (0, shared_1.localDate)(block.startedAt), block.branch),
138
+ projectId,
139
+ startedAt: block.startedAt,
140
+ endedAt: block.endedAt,
141
+ seconds: block.seconds,
142
+ description: (0, sessionize_js_1.describeBlock)(block),
143
+ billable: project.billable,
144
+ invoiceId: null,
145
+ aiCost: block.aiCost,
146
+ // Un bloque deducido solo de commits no tuvo agente: ni segundos de
147
+ // agente ni agente al que atribuirlos.
148
+ agentSeconds: block.turnCount > 0 ? block.seconds : 0,
149
+ commitHashes: block.commits.map((c) => c.hash),
150
+ agents: block.turnCount > 0 ? [...(block.agents ?? ["claude-code"])] : [],
151
+ source: block.turnCount > 0 ? "agent" : "commit",
152
+ kind: "development",
153
+ branch: block.branch,
154
+ // El ticket se saca aquí: en la base solo quedan los hashes de los
155
+ // commits, y es en sus mensajes donde va el `AB#1234`.
156
+ workItems: (0, shared_1.extractWorkItems)(block.branch, block.commits.map((c) => c.subject), project.tracker),
157
+ };
158
+ }
159
+ //# sourceMappingURL=assign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.js","sourceRoot":"","sources":["../../src/billing/assign.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=assign.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.test.d.ts","sourceRoot":"","sources":["../../src/billing/assign.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const strict_1 = __importDefault(require("node:assert/strict"));
40
+ const node_fs_1 = require("node:fs");
41
+ const node_os_1 = require("node:os");
42
+ const node_path_1 = require("node:path");
43
+ const node_test_1 = require("node:test");
44
+ const shared_1 = require("@estela/shared");
45
+ const schema_js_1 = require("../db/schema.js");
46
+ const store = __importStar(require("../db/store.js"));
47
+ const paths_js_1 = require("../paths.js");
48
+ const assign_js_1 = require("./assign.js");
49
+ const sessionize_js_1 = require("./sessionize.js");
50
+ /**
51
+ * Las reglas de la recuperación de horas por raíz git, en el sitio donde se
52
+ * deciden. Esto acaba en facturas: lo que no puede pasar es mover horas de un
53
+ * proyecto a otro, o cambiar un día que alguien ya aprobó o facturó.
54
+ */
55
+ const n = (p) => (0, paths_js_1.normalizePath)(p);
56
+ /** main/ es un repo registrado como "web"; wt/ es un worktree suyo, sin registrar. */
57
+ function escenario() {
58
+ const base = (0, node_fs_1.realpathSync)((0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "estela-assign-")));
59
+ const main = (0, node_path_1.join)(base, "web");
60
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(main, ".git", "worktrees", "wt"), { recursive: true });
61
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(main, ".git", "worktrees", "wt", "commondir"), "../..\n");
62
+ const wt = (0, node_path_1.join)(base, "web-wt");
63
+ (0, node_fs_1.mkdirSync)(wt);
64
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(wt, ".git"), `gitdir: ${(0, node_path_1.join)(main, ".git", "worktrees", "wt")}\n`);
65
+ const db = (0, schema_js_1.openDatabase)(":memory:");
66
+ store.upsertClient(db, { id: "c", name: "C", currency: "EUR" });
67
+ store.upsertProject(db, { id: "web", clientId: "c", name: "Web", repoPaths: [n(main)], billable: true,
68
+ roundingMinutes: 0, aiCostPolicy: "absorbed", kind: "client" });
69
+ return { base, main, wt, db };
70
+ }
71
+ let k = 0;
72
+ /** Turnos seguidos de un minuto, en `cwd`, desde `start`. */
73
+ function sesion(cwd, start, minutos, branch = "main") {
74
+ return Array.from({ length: minutos }, (_, i) => ({
75
+ agent: "claude-code", turnId: `t${k++}`, sessionId: `s-${cwd}`,
76
+ at: new Date(start.getTime() + i * 60_000), model: "claude-sonnet-4-6",
77
+ repoPath: n(cwd), branch, producerVersion: null,
78
+ tokens: { input: 1, output: 1, cacheRead: 1, cacheWrite5m: 0, cacheWrite1h: 0 },
79
+ }));
80
+ }
81
+ const dia = (d, h = 10) => new Date(2026, 9, d, h, 0);
82
+ (0, node_test_1.test)("sin recuperar: el worktree se queda sin proyecto, como antes", () => {
83
+ const { main, wt, db } = escenario();
84
+ const blocks = (0, sessionize_js_1.sessionize)([...sesion(main, dia(5), 30), ...sesion(wt, dia(5, 14), 30, "feature")]);
85
+ const plan = (0, assign_js_1.planEntries)(db, blocks, { recover: false });
86
+ strict_1.default.deepEqual(plan.entries.map((e) => e.entry.branch), ["main"]);
87
+ strict_1.default.equal(plan.unassigned, 1);
88
+ });
89
+ (0, node_test_1.test)("recuperando: el worktree va a su proyecto, y se cuenta cuánto se recuperó", () => {
90
+ const { main, wt, db } = escenario();
91
+ const blocks = (0, sessionize_js_1.sessionize)([...sesion(main, dia(5), 30), ...sesion(wt, dia(5, 14), 30, "feature")]);
92
+ const plan = (0, assign_js_1.planEntries)(db, blocks, { recover: true });
93
+ const feature = plan.entries.find((e) => e.entry.branch === "feature");
94
+ strict_1.default.equal(feature.entry.projectId, "web");
95
+ strict_1.default.equal(feature.entry.id, (0, assign_js_1.entryId)("web", (0, shared_1.localDate)(dia(5)), "feature"));
96
+ strict_1.default.ok(feature.recoveredSeconds > 0);
97
+ strict_1.default.equal(plan.recovered.get("web"), feature.recoveredSeconds);
98
+ strict_1.default.equal(plan.unassigned, 0);
99
+ // Lo que ya estaba asignado no gana ni pierde nada.
100
+ strict_1.default.equal(plan.entries.find((e) => e.entry.branch === "main").recoveredSeconds, 0);
101
+ });
102
+ (0, node_test_1.test)("nunca mueve horas de un proyecto a otro: la carpeta registrada manda sobre la raíz git", () => {
103
+ // `web/packages/api` es su propio proyecto aunque su raíz git sea la de web.
104
+ const { main, db } = escenario();
105
+ const api = (0, node_path_1.join)(main, "packages", "api");
106
+ (0, node_fs_1.mkdirSync)(api, { recursive: true });
107
+ store.upsertProject(db, { id: "api", clientId: "c", name: "API", repoPaths: [n(api)], billable: true,
108
+ roundingMinutes: 0, aiCostPolicy: "absorbed", kind: "client" });
109
+ const plan = (0, assign_js_1.planEntries)(db, (0, sessionize_js_1.sessionize)(sesion(api, dia(6), 40)), { recover: true });
110
+ strict_1.default.deepEqual(plan.entries.map((e) => e.entry.projectId), ["api"]);
111
+ strict_1.default.equal(plan.recovered.size, 0);
112
+ });
113
+ (0, node_test_1.test)("un día aprobado o facturado no se toca: se informa con su fecha y sus horas", () => {
114
+ const { main, wt, db } = escenario();
115
+ // Lo de siempre, ya importado y aprobado el día 5.
116
+ const antes = (0, assign_js_1.planEntries)(db, (0, sessionize_js_1.sessionize)(sesion(main, dia(5), 30)), { recover: false });
117
+ for (const { entry } of antes.entries)
118
+ store.saveTimeEntry(db, entry);
119
+ db.prepare("UPDATE time_entries SET approved = 1 WHERE local_date = ?").run((0, shared_1.localDate)(dia(5)));
120
+ // Y uno facturado el día 6.
121
+ const otro = (0, assign_js_1.planEntries)(db, (0, sessionize_js_1.sessionize)(sesion(main, dia(6), 20)), { recover: false });
122
+ for (const { entry } of otro.entries)
123
+ store.saveTimeEntry(db, entry);
124
+ db.prepare(`INSERT INTO invoices (id, number, client_id, project_id, issued_at, cutoff_at, period_start,
125
+ currency, subtotal_minor, total_minor, total_seconds, lines_json) VALUES ('inv1', 'INF-1', 'c', 'web', ?, ?, ?, 'EUR', 0, 0, 0, '[]')`)
126
+ .run(dia(8).toISOString(), dia(6, 23).toISOString(), dia(1).toISOString());
127
+ db.prepare("UPDATE time_entries SET invoice_id = 'inv1' WHERE local_date = ?").run((0, shared_1.localDate)(dia(6)));
128
+ const blocks = (0, sessionize_js_1.sessionize)([
129
+ ...sesion(main, dia(5), 30), // lo que ya había
130
+ ...sesion(wt, dia(5, 14), 30), // worktree, misma rama y día aprobado: se fusionaría
131
+ ...sesion(wt, dia(6, 15), 25, "fix"), // worktree en día facturado
132
+ ...sesion(wt, dia(7, 9), 45, "feature"), // worktree en día libre
133
+ ]);
134
+ const plan = (0, assign_js_1.planEntries)(db, blocks, { recover: true });
135
+ // El día 5 se guarda exactamente como estaba: sin los minutos del worktree.
136
+ const del5 = plan.entries.find((e) => e.entry.id === (0, assign_js_1.entryId)("web", (0, shared_1.localDate)(dia(5)), "main"));
137
+ strict_1.default.equal(del5.entry.seconds, antes.entries[0].entry.seconds);
138
+ // El 6 no gana una imputación nueva; el 7 sí.
139
+ strict_1.default.ok(!plan.entries.some((e) => e.entry.id === (0, assign_js_1.entryId)("web", (0, shared_1.localDate)(dia(6)), "fix")));
140
+ strict_1.default.ok(plan.entries.some((e) => e.entry.id === (0, assign_js_1.entryId)("web", (0, shared_1.localDate)(dia(7)), "feature")));
141
+ strict_1.default.deepEqual(plan.blocked.map((b) => [b.projectId, b.day]).sort(), [["web", (0, shared_1.localDate)(dia(5))], ["web", (0, shared_1.localDate)(dia(6))]]);
142
+ strict_1.default.ok(plan.blocked.every((b) => b.seconds > 0));
143
+ strict_1.default.deepEqual([...plan.recovered.keys()], ["web"], "solo lo del día 7");
144
+ });
145
+ (0, node_test_1.test)("una sesión del worktree a la misma hora que la del repo no suma nada: se unen intervalos", () => {
146
+ // Dos sesiones a la vez son la misma persona: import une los intervalos, y
147
+ // recuperar no puede contar dos veces el mismo rato.
148
+ const { main, wt, db } = escenario();
149
+ const plan = (0, assign_js_1.planEntries)(db, (0, sessionize_js_1.sessionize)([...sesion(main, dia(9), 30), ...sesion(wt, dia(9), 30)]), { recover: true });
150
+ strict_1.default.equal(plan.recovered.size, 0);
151
+ strict_1.default.equal(plan.entries.length, 1);
152
+ });
153
+ //# sourceMappingURL=assign.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.test.js","sourceRoot":"","sources":["../../src/billing/assign.test.ts"],"names":[],"mappings":"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"}
package/dist/bin.js CHANGED
@@ -20,7 +20,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
20
20
  const node_version_js_1 = require("./node-version.js");
21
21
  const index_js_1 = require("./i18n/index.js");
22
22
  const MIN_NODE = "22.5.0";
23
- if ((0, node_version_js_1.tooOld)(process.version, MIN_NODE)) {
23
+ // `estela statusline` (y no `statusline install|uninstall`, que son de la CLI):
24
+ // lo ejecuta Claude Code en cada evento de la sesión y tiene 100 ms. Va por un
25
+ // camino aparte que no carga cli.js, y en un Node viejo imprime "estela" y
26
+ // sale con 0 en vez de un error: la status line no se rompe nunca.
27
+ const sub = process.argv[3];
28
+ const esStatusline = process.argv[2] === "statusline" &&
29
+ !["install", "uninstall", "help", "--help"].includes(sub ?? "");
30
+ if (esStatusline) {
31
+ // El aviso de que node:sqlite es experimental iría a stderr en cada evento.
32
+ process.removeAllListeners("warning");
33
+ process.on("warning", () => { });
34
+ if ((0, node_version_js_1.tooOld)(process.version, MIN_NODE)) {
35
+ process.stdout.write("estela\n");
36
+ }
37
+ else {
38
+ const i = process.argv.indexOf("--lang");
39
+ (0, index_js_1.setLang)((0, index_js_1.detectLang)({ flag: i >= 0 ? process.argv[i + 1] : undefined, env: process.env, platform: process.platform }));
40
+ void import("./statusline-run.js")
41
+ .then((m) => m.runStatusline(process.argv.slice(3)))
42
+ .catch(() => { process.stdout.write("estela\n"); });
43
+ }
44
+ }
45
+ else if ((0, node_version_js_1.tooOld)(process.version, MIN_NODE)) {
24
46
  // Aquí aún no se ha leído ningún argumento: `--lang` se busca a mano.
25
47
  const i = process.argv.indexOf("--lang");
26
48
  (0, index_js_1.setLang)((0, index_js_1.detectLang)({ flag: i >= 0 ? process.argv[i + 1] : undefined, env: process.env, platform: process.platform }));
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";;AAEA;;;;;;;;;;;;;;;GAeG;;AAEH,uDAA2D;AAC3D,8CAA0D;AAE1D,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAE1B,IAAI,IAAA,wBAAM,EAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;IACtC,sEAAsE;IACtE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAA,kBAAO,EAAC,IAAA,qBAAU,EAAC,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACtH,OAAO,CAAC,KAAK,CACX,IAAA,aAAE,EAAA,0BAA0B,QAAQ,wBAAwB,OAAO,CAAC,OAAO,eAAe;QAC1F,IAAA,aAAE,EAAA,kBAAkB,IAAA,gCAAc,EAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;IACnJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;KAAM,CAAC;IACN,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,2EAA2E;IAC3E,KAAK,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAC/C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli-import-recover.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-import-recover.test.d.ts","sourceRoot":"","sources":["../src/cli-import-recover.test.ts"],"names":[],"mappings":""}