time2 2.5.0__py3-none-any.whl
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.
- time2-2.5.0.data/data/share/time2/docs/AI_INSIGHTS.md +188 -0
- time2-2.5.0.data/data/share/time2/docs/CODE_WALKTHROUGH.md +222 -0
- time2-2.5.0.data/data/share/time2/docs/DEVELOPER_GUIDE.md +738 -0
- time2-2.5.0.data/data/share/time2/docs/MANUAL.md +570 -0
- time2-2.5.0.data/data/share/time2/docs/MODULES.md +167 -0
- time2-2.5.0.data/data/share/time2/docs/PACKAGING.md +189 -0
- time2-2.5.0.data/data/share/time2/docs/TAILSCALE_PRIVATE_ACCESS.md +157 -0
- time2-2.5.0.data/data/share/time2/examples/time2_data.example.json +5 -0
- time2-2.5.0.data/data/share/time2/examples/time2_settings.example.json +85 -0
- time2-2.5.0.data/data/share/time2/time2_e2_component/index.html +575 -0
- time2-2.5.0.data/data/share/time2/time2_matrix_component/index.html +427 -0
- time2-2.5.0.data/data/share/time2/time2_task_list_component/index.html +191 -0
- time2-2.5.0.dist-info/METADATA +447 -0
- time2-2.5.0.dist-info/RECORD +38 -0
- time2-2.5.0.dist-info/WHEEL +5 -0
- time2-2.5.0.dist-info/entry_points.txt +2 -0
- time2-2.5.0.dist-info/licenses/LICENSE +21 -0
- time2-2.5.0.dist-info/top_level.txt +5 -0
- time2_ai_cache_worker.py +76 -0
- time2_app/__init__.py +14 -0
- time2_app/ai.py +1391 -0
- time2_app/app.py +885 -0
- time2_app/budget.py +261 -0
- time2_app/chat.py +512 -0
- time2_app/cli.py +307 -0
- time2_app/components.py +47 -0
- time2_app/config.py +106 -0
- time2_app/models.py +610 -0
- time2_app/reports.py +384 -0
- time2_app/storage.py +373 -0
- time2_app/streamlit_entry.py +11 -0
- time2_app/tailscale_utils.py +148 -0
- time2_app/transcription.py +62 -0
- time2_app/utils.py +869 -0
- time2_app/views.py +5422 -0
- time2_jupyter_launcher.py +69 -0
- time2_streamlit_app.py +12 -0
- time2_tailscale_jupyter_launcher.py +310 -0
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
# Developer Guide For time-2.0.5
|
|
2
|
+
|
|
3
|
+
This guide explains how the code is organized, how data moves through the app,
|
|
4
|
+
and where to begin when building the next version.
|
|
5
|
+
|
|
6
|
+
It is intentionally written for a future developer who may not remember the
|
|
7
|
+
conversation that created this app.
|
|
8
|
+
|
|
9
|
+
## Design Goals
|
|
10
|
+
|
|
11
|
+
time-2.0.5 is built around these priorities:
|
|
12
|
+
|
|
13
|
+
- Local-first data ownership.
|
|
14
|
+
- Simple Python code that can be run from JupyterLab.
|
|
15
|
+
- Dataclasses and JSON instead of a database for this version.
|
|
16
|
+
- Clear history instead of disappearing tasks.
|
|
17
|
+
- Attention-friendly workflows: visible progress, reschedule reasons, mind states,
|
|
18
|
+
spontaneous work, reserved backlog tasks, audio capture, transcripts, and
|
|
19
|
+
AI-ready summaries.
|
|
20
|
+
- Optional heavy dependencies: Whisper and llama-cpp are loaded only when used.
|
|
21
|
+
- Optional LLM provider choice: local llama.cpp or an OpenAI-compatible API.
|
|
22
|
+
|
|
23
|
+
## Runtime Shape
|
|
24
|
+
|
|
25
|
+
```mermaid
|
|
26
|
+
flowchart TD
|
|
27
|
+
User["User in browser/Jupyter iframe"] --> Streamlit["Streamlit app"]
|
|
28
|
+
Streamlit --> App["time2_app/app.py"]
|
|
29
|
+
App --> Views["time2_app/views.py"]
|
|
30
|
+
Views --> Models["time2_app/models.py"]
|
|
31
|
+
Views --> Storage["time2_app/storage.py"]
|
|
32
|
+
Views --> Budget["time2_app/budget.py"]
|
|
33
|
+
Views --> AI["time2_app/ai.py"]
|
|
34
|
+
Views --> Whisper["time2_app/transcription.py"]
|
|
35
|
+
Views --> Tailscale["time2_app/tailscale_utils.py"]
|
|
36
|
+
Storage --> JSON["Local JSON files"]
|
|
37
|
+
Budget --> BudgetJSON["Monthly budget JSON files"]
|
|
38
|
+
AI --> Cache["AI cache JSON files"]
|
|
39
|
+
Whisper --> Audio["Local audio files"]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Source File Explanation
|
|
43
|
+
|
|
44
|
+
### `time2_streamlit_app.py`
|
|
45
|
+
|
|
46
|
+
Tiny entrypoint used by Streamlit and JupyterLab.
|
|
47
|
+
|
|
48
|
+
It imports `run_app()` from `time2_app.app` and calls it. Keep this file small
|
|
49
|
+
so the launch command remains stable:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python -m streamlit run time2_streamlit_app.py
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### `time2_app/streamlit_entry.py`
|
|
56
|
+
|
|
57
|
+
Installed-package Streamlit entrypoint.
|
|
58
|
+
|
|
59
|
+
The `time2` CLI points Streamlit at this file after the package is installed
|
|
60
|
+
from a wheel. Keep it tiny; it should only import and call `run_app()`.
|
|
61
|
+
|
|
62
|
+
### `time2_app/cli.py`
|
|
63
|
+
|
|
64
|
+
Command-line interface exposed as:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
time2
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Responsibilities:
|
|
71
|
+
|
|
72
|
+
- `time2 run`: start the Streamlit app from an installed package.
|
|
73
|
+
- `time2 doctor`: check required and optional Python imports.
|
|
74
|
+
- `time2 install-optionals`: ask before installing Whisper/LLM extras.
|
|
75
|
+
- `time2 tailscale`: install/check/login/serve helpers for Tailscale.
|
|
76
|
+
|
|
77
|
+
The CLI should never install optional packages or system software without an
|
|
78
|
+
explicit yes/no confirmation.
|
|
79
|
+
|
|
80
|
+
### `pyproject.toml` and `MANIFEST.in`
|
|
81
|
+
|
|
82
|
+
Package metadata and source distribution rules.
|
|
83
|
+
|
|
84
|
+
Important packaging details:
|
|
85
|
+
|
|
86
|
+
- `project.scripts` defines the `time2` command.
|
|
87
|
+
- Optional extras are `whisper`, `llm`, and `all`.
|
|
88
|
+
- Streamlit component HTML is included as wheel data under `share/time2/`.
|
|
89
|
+
- `MANIFEST.in` keeps docs, examples, launchers, and component HTML in source
|
|
90
|
+
distributions.
|
|
91
|
+
|
|
92
|
+
### `time2_jupyter_launcher.py`
|
|
93
|
+
|
|
94
|
+
Portable launcher for JupyterLab.
|
|
95
|
+
|
|
96
|
+
Responsibilities:
|
|
97
|
+
|
|
98
|
+
- Find the app folder.
|
|
99
|
+
- Start Streamlit in a subprocess.
|
|
100
|
+
- Use port `8503`.
|
|
101
|
+
- Open the app in a browser.
|
|
102
|
+
- Display it in a Jupyter iframe.
|
|
103
|
+
|
|
104
|
+
This file should not contain a developer-specific absolute path.
|
|
105
|
+
|
|
106
|
+
### `time2_jupyter_launcher.ipynb`
|
|
107
|
+
|
|
108
|
+
Notebook wrapper around the launcher. It exists because `%run` can hit
|
|
109
|
+
permission/path issues in some JupyterLab setups. The notebook is the friendlier
|
|
110
|
+
launch surface.
|
|
111
|
+
|
|
112
|
+
### `time2_tailscale_jupyter_launcher.py`
|
|
113
|
+
|
|
114
|
+
JupyterLab-only private-access launcher.
|
|
115
|
+
|
|
116
|
+
Responsibilities:
|
|
117
|
+
|
|
118
|
+
- Start or restart the local Streamlit process.
|
|
119
|
+
- Find the Tailscale CLI in common macOS/Jupyter locations.
|
|
120
|
+
- Run `tailscale serve --bg http://127.0.0.1:8503`.
|
|
121
|
+
- Print the private tailnet HTTPS URL/status.
|
|
122
|
+
- Display the local app in a Jupyter iframe.
|
|
123
|
+
|
|
124
|
+
This file assumes Tailscale is already installed and signed in on the home
|
|
125
|
+
laptop.
|
|
126
|
+
|
|
127
|
+
### `time2_tailscale_jupyter_launcher.ipynb`
|
|
128
|
+
|
|
129
|
+
Notebook wrapper for the Tailscale launcher.
|
|
130
|
+
|
|
131
|
+
It has cells for:
|
|
132
|
+
|
|
133
|
+
- Starting the app and Tailscale Serve.
|
|
134
|
+
- Showing Tailscale Serve status again.
|
|
135
|
+
- Resetting Tailscale Serve and stopping the Streamlit subprocess.
|
|
136
|
+
|
|
137
|
+
### `time2_ai_cache_worker.py`
|
|
138
|
+
|
|
139
|
+
Optional background script.
|
|
140
|
+
|
|
141
|
+
Responsibilities:
|
|
142
|
+
|
|
143
|
+
- Load the same settings/data as the app.
|
|
144
|
+
- Refresh deterministic AI cache files.
|
|
145
|
+
- Optionally refresh LLM cache files.
|
|
146
|
+
- Run once or loop at an interval.
|
|
147
|
+
|
|
148
|
+
This is separate from Streamlit because Streamlit reruns are not a true
|
|
149
|
+
scheduler.
|
|
150
|
+
|
|
151
|
+
## Package Modules
|
|
152
|
+
|
|
153
|
+
### `time2_app/config.py`
|
|
154
|
+
|
|
155
|
+
Independent constants and defaults.
|
|
156
|
+
|
|
157
|
+
Contains:
|
|
158
|
+
|
|
159
|
+
- `APP_TITLE`
|
|
160
|
+
- `DATA_FILE`
|
|
161
|
+
- `SETTINGS_FILE`
|
|
162
|
+
- `DEFAULT_SETTINGS`
|
|
163
|
+
- `OPTION_FIELDS`
|
|
164
|
+
|
|
165
|
+
Add new setting defaults here first. Then normalize them in `utils.py`.
|
|
166
|
+
|
|
167
|
+
### `time2_app/utils.py`
|
|
168
|
+
|
|
169
|
+
General helper layer.
|
|
170
|
+
|
|
171
|
+
Contains:
|
|
172
|
+
|
|
173
|
+
- ID generation.
|
|
174
|
+
- Current timestamps.
|
|
175
|
+
- Date/time parsing and formatting.
|
|
176
|
+
- Deadline/urgency math.
|
|
177
|
+
- Energy labels.
|
|
178
|
+
- Settings load/save.
|
|
179
|
+
- Settings normalization.
|
|
180
|
+
- Theme CSS.
|
|
181
|
+
- Project and daily routine normalization.
|
|
182
|
+
- Option helpers for Streamlit selectboxes.
|
|
183
|
+
|
|
184
|
+
Keep this module free of Streamlit tab workflows. Small UI-independent helpers
|
|
185
|
+
belong here.
|
|
186
|
+
|
|
187
|
+
### `time2_app/models.py`
|
|
188
|
+
|
|
189
|
+
Core app meaning.
|
|
190
|
+
|
|
191
|
+
Defines:
|
|
192
|
+
|
|
193
|
+
- `Time2Comment`
|
|
194
|
+
- `Time2MindLog`
|
|
195
|
+
- `Time2AudioLog`
|
|
196
|
+
- `Time2Session`
|
|
197
|
+
- `Time2Reschedule`
|
|
198
|
+
- `Time2Item`
|
|
199
|
+
- `Time2Board`
|
|
200
|
+
|
|
201
|
+
Important model behavior:
|
|
202
|
+
|
|
203
|
+
- `Time2Item.start_session()`
|
|
204
|
+
- `Time2Item.stop_session()`
|
|
205
|
+
- `Time2Item.mark_done()`
|
|
206
|
+
- `Time2Item.undo_done()`
|
|
207
|
+
- `Time2Item.cancel()`
|
|
208
|
+
- `Time2Item.reschedule()`
|
|
209
|
+
- `Time2Item.sync_matrix_scores()`
|
|
210
|
+
- `Time2Board.stats()`
|
|
211
|
+
- `Time2Board.load()`
|
|
212
|
+
- `Time2Board.save()`
|
|
213
|
+
|
|
214
|
+
When adding fields, update:
|
|
215
|
+
|
|
216
|
+
1. Dataclass field.
|
|
217
|
+
2. `from_dict()` for backward compatibility.
|
|
218
|
+
3. Any table/rendering code in `views.py`.
|
|
219
|
+
4. Example data/settings if needed.
|
|
220
|
+
|
|
221
|
+
Reserved tasks use `Time2Item.reserved`. They are intentional unscheduled
|
|
222
|
+
backlog items. `sync_matrix_scores()` clears reserved mode once a planned date
|
|
223
|
+
or deadline exists, so the task returns to the normal color scheme.
|
|
224
|
+
|
|
225
|
+
### `time2_app/storage.py`
|
|
226
|
+
|
|
227
|
+
Disk and folder behavior.
|
|
228
|
+
|
|
229
|
+
Contains:
|
|
230
|
+
|
|
231
|
+
- Path resolution.
|
|
232
|
+
- Data folder handling.
|
|
233
|
+
- First-run folder creation.
|
|
234
|
+
- Main board JSON read/write support.
|
|
235
|
+
- Per-task file saving.
|
|
236
|
+
- Per-mind-log file saving.
|
|
237
|
+
- Audio file saving.
|
|
238
|
+
- Backup writing.
|
|
239
|
+
|
|
240
|
+
Important functions:
|
|
241
|
+
|
|
242
|
+
- `data_storage_folder(settings)`
|
|
243
|
+
- `data_file_path(settings)`
|
|
244
|
+
- `task_storage_folder(settings)`
|
|
245
|
+
- `mind_storage_folder(settings)`
|
|
246
|
+
- `audio_storage_folder(settings)`
|
|
247
|
+
- `backup_storage_folder(settings)`
|
|
248
|
+
- `ensure_data_folder_structure(settings)`
|
|
249
|
+
- `store_audio_upload(...)`
|
|
250
|
+
- `write_backup(...)`
|
|
251
|
+
|
|
252
|
+
Relative paths resolve from the app working directory. Absolute paths are used
|
|
253
|
+
directly.
|
|
254
|
+
|
|
255
|
+
### `time2_app/budget.py`
|
|
256
|
+
|
|
257
|
+
Budget data layer.
|
|
258
|
+
|
|
259
|
+
Defines:
|
|
260
|
+
|
|
261
|
+
- `BudgetEntry`
|
|
262
|
+
- `DEFAULT_BUDGET_CATEGORIES`
|
|
263
|
+
- `BUDGET_KINDS`
|
|
264
|
+
- `BUDGET_CLASSES`
|
|
265
|
+
|
|
266
|
+
Responsibilities:
|
|
267
|
+
|
|
268
|
+
- Normalize budget categories.
|
|
269
|
+
- Decide budget month from a custom month-end day.
|
|
270
|
+
- Read/write monthly budget files.
|
|
271
|
+
- Add budget entries.
|
|
272
|
+
- Build budget reports.
|
|
273
|
+
|
|
274
|
+
Budget files live under:
|
|
275
|
+
|
|
276
|
+
```text
|
|
277
|
+
time2_budget/budget_YYYY_MM.json
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Budget entries can contain:
|
|
281
|
+
|
|
282
|
+
- Item.
|
|
283
|
+
- Amount.
|
|
284
|
+
- Category.
|
|
285
|
+
- Kind: income, expense, savings.
|
|
286
|
+
- Date.
|
|
287
|
+
- Bank/account.
|
|
288
|
+
- Note.
|
|
289
|
+
- Audio log metadata.
|
|
290
|
+
- Transcript status/text.
|
|
291
|
+
|
|
292
|
+
### `time2_app/ai.py`
|
|
293
|
+
|
|
294
|
+
AI and deterministic analytics layer.
|
|
295
|
+
|
|
296
|
+
Responsibilities:
|
|
297
|
+
|
|
298
|
+
- Build daily/range reports.
|
|
299
|
+
- Calculate period scores.
|
|
300
|
+
- Calculate data availability.
|
|
301
|
+
- Build attention flags.
|
|
302
|
+
- Build next-action candidates.
|
|
303
|
+
- Create compact prompts for local or API LLM calls.
|
|
304
|
+
- Load and call `llama-cpp-python` only when requested.
|
|
305
|
+
- Call OpenAI-compatible `/chat/completions` APIs through the standard library.
|
|
306
|
+
- Write/read AI cache files.
|
|
307
|
+
|
|
308
|
+
This module should not edit tasks. It should read data and produce analysis.
|
|
309
|
+
|
|
310
|
+
### `time2_app/transcription.py`
|
|
311
|
+
|
|
312
|
+
Optional Whisper integration.
|
|
313
|
+
|
|
314
|
+
Responsibilities:
|
|
315
|
+
|
|
316
|
+
- Keep supported language mapping.
|
|
317
|
+
- Load Whisper lazily.
|
|
318
|
+
- Transcribe a stored audio file.
|
|
319
|
+
|
|
320
|
+
The lazy import matters. The app should still run when `openai-whisper` is not
|
|
321
|
+
installed.
|
|
322
|
+
|
|
323
|
+
Supported UI languages:
|
|
324
|
+
|
|
325
|
+
- Auto detect
|
|
326
|
+
- English
|
|
327
|
+
- German
|
|
328
|
+
- Spanish
|
|
329
|
+
- Bengali
|
|
330
|
+
- Hindi
|
|
331
|
+
|
|
332
|
+
`Auto detect` should remain the default. When it is selected,
|
|
333
|
+
`transcribe_audio_file()` should call Whisper without a forced `language`
|
|
334
|
+
keyword and then store Whisper's detected language code/name.
|
|
335
|
+
|
|
336
|
+
### `time2_app/tailscale_utils.py`
|
|
337
|
+
|
|
338
|
+
Optional Tailscale integration shared by the CLI and Settings screen.
|
|
339
|
+
|
|
340
|
+
Responsibilities:
|
|
341
|
+
|
|
342
|
+
- Detect the local `tailscale` command.
|
|
343
|
+
- Report download links and package-manager install commands.
|
|
344
|
+
- Ask callers to decide before install/sign-in/share actions.
|
|
345
|
+
- Start `tailscale up` for sign-in.
|
|
346
|
+
- Start `tailscale serve` for private tailnet access.
|
|
347
|
+
- Parse private `https://...ts.net` URLs from Serve status output.
|
|
348
|
+
|
|
349
|
+
This module should not import Streamlit. It should stay usable from both the
|
|
350
|
+
CLI and the app UI.
|
|
351
|
+
|
|
352
|
+
### `time2_app/components.py`
|
|
353
|
+
|
|
354
|
+
Registers custom Streamlit components.
|
|
355
|
+
|
|
356
|
+
Components:
|
|
357
|
+
|
|
358
|
+
- `time2_matrix_component`
|
|
359
|
+
- `time2_e2_component`
|
|
360
|
+
- `time2_task_list_component`
|
|
361
|
+
|
|
362
|
+
In a source checkout, browser-side component files live beside the Python
|
|
363
|
+
package:
|
|
364
|
+
|
|
365
|
+
```text
|
|
366
|
+
time2_matrix_component/index.html
|
|
367
|
+
time2_e2_component/index.html
|
|
368
|
+
time2_task_list_component/index.html
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
In an installed wheel, `pyproject.toml` installs those files under
|
|
372
|
+
`share/time2/`, and `components.py` checks both locations.
|
|
373
|
+
|
|
374
|
+
### `time2_app/views.py`
|
|
375
|
+
|
|
376
|
+
Most Streamlit UI code lives here.
|
|
377
|
+
|
|
378
|
+
Responsibilities:
|
|
379
|
+
|
|
380
|
+
- First-run setup screen.
|
|
381
|
+
- AI Insights tab UI.
|
|
382
|
+
- Planning tab.
|
|
383
|
+
- Deadlines tab.
|
|
384
|
+
- Matrix tab.
|
|
385
|
+
- E2 Plot tab.
|
|
386
|
+
- Mind Log tab.
|
|
387
|
+
- Budget tab.
|
|
388
|
+
- Settings tab.
|
|
389
|
+
- Task list rendering.
|
|
390
|
+
- Universal task editor.
|
|
391
|
+
- Audio upload/record/transcribe controls.
|
|
392
|
+
- Transcript display.
|
|
393
|
+
- Folder/file pickers.
|
|
394
|
+
|
|
395
|
+
Important functions:
|
|
396
|
+
|
|
397
|
+
- `save_board(board, settings=None, force_backup=False)`
|
|
398
|
+
- `render_first_run_setup(settings)`
|
|
399
|
+
- `render_planning_tab(board, settings)`
|
|
400
|
+
- `render_deadlines_tab(board, settings)`
|
|
401
|
+
- `render_eisenhower_tab(board, settings)`
|
|
402
|
+
- `render_e2_plot_tab(board, settings)`
|
|
403
|
+
- `render_mind_log_tab(board, settings)`
|
|
404
|
+
- `render_budget_tab(settings)`
|
|
405
|
+
- `render_settings_tab(settings, board)`
|
|
406
|
+
- `show_item_controls(board, item, settings, key_prefix="item", show_signal=False)`
|
|
407
|
+
- `save_audio_upload_log(...)`
|
|
408
|
+
- `transcribe_existing_audio_log(...)`
|
|
409
|
+
|
|
410
|
+
The universal task editor is especially important. Anything added to
|
|
411
|
+
`show_item_controls()` appears wherever a task is editable:
|
|
412
|
+
|
|
413
|
+
- Planning
|
|
414
|
+
- Pending
|
|
415
|
+
- Victory Board
|
|
416
|
+
- Cancelled
|
|
417
|
+
- Deadlines
|
|
418
|
+
- Matrix
|
|
419
|
+
- E2 Plot
|
|
420
|
+
|
|
421
|
+
### `time2_app/app.py`
|
|
422
|
+
|
|
423
|
+
Top-level app composition.
|
|
424
|
+
|
|
425
|
+
Responsibilities:
|
|
426
|
+
|
|
427
|
+
- Set page config.
|
|
428
|
+
- Load settings.
|
|
429
|
+
- Apply theme.
|
|
430
|
+
- Show first-run setup if settings do not exist.
|
|
431
|
+
- Load board.
|
|
432
|
+
- Show top metrics.
|
|
433
|
+
- Create the 16 tabs.
|
|
434
|
+
- Call view functions.
|
|
435
|
+
- Handle the Data tab import/restore workflow.
|
|
436
|
+
|
|
437
|
+
Add new tabs here, but implement the tab body in `views.py`.
|
|
438
|
+
|
|
439
|
+
The time-2.0.5 tabs added after AI Insights are:
|
|
440
|
+
|
|
441
|
+
- `AI Chat`: saved local/API conversations over selected data context.
|
|
442
|
+
- `Reports`: PDF/HTML/TXT/JSON exports for tasks, ranges, dashboard, mind logs,
|
|
443
|
+
budgets, chats, and raw snapshots.
|
|
444
|
+
|
|
445
|
+
## Data Flow
|
|
446
|
+
|
|
447
|
+
### Task Creation
|
|
448
|
+
|
|
449
|
+
1. User creates task in `Add`.
|
|
450
|
+
2. `app.py` collects form values.
|
|
451
|
+
3. `Time2Item` is created.
|
|
452
|
+
4. Optional task audio is saved through `save_audio_upload_log()`.
|
|
453
|
+
5. `Time2Board.add()` adds the task.
|
|
454
|
+
6. `save_board()` writes:
|
|
455
|
+
- Main board JSON.
|
|
456
|
+
- Per-task files.
|
|
457
|
+
- Per-mind-log files.
|
|
458
|
+
- Backup if due.
|
|
459
|
+
|
|
460
|
+
### Task Editing
|
|
461
|
+
|
|
462
|
+
1. User clicks a task card.
|
|
463
|
+
2. Custom task-list component sends selected ID.
|
|
464
|
+
3. `show_item_controls()` renders the universal editor.
|
|
465
|
+
4. User edits sessions, reschedules, deadlines, comments, details, audio, or status.
|
|
466
|
+
5. `save_board()` persists changes.
|
|
467
|
+
|
|
468
|
+
### Audio And Transcript
|
|
469
|
+
|
|
470
|
+
1. User uploads or records audio.
|
|
471
|
+
2. `store_audio_upload()` writes the file to `time2_audio/`.
|
|
472
|
+
3. A `Time2AudioLog` is created.
|
|
473
|
+
4. If `Transcribe` is on, `transcribe_audio_file()` runs Whisper.
|
|
474
|
+
5. Transcript status/text are stored on the audio log.
|
|
475
|
+
6. For mind logs and budget entries, transcript text is copied into the entry
|
|
476
|
+
for easier direct display.
|
|
477
|
+
|
|
478
|
+
### Budget Entry
|
|
479
|
+
|
|
480
|
+
1. User opens `Budget`.
|
|
481
|
+
2. Date determines budget year/month using `budget_period_for_date()`.
|
|
482
|
+
3. User adds income, expense, or savings.
|
|
483
|
+
4. Optional audio/transcript is saved.
|
|
484
|
+
5. `BudgetEntry` is written into the monthly JSON file.
|
|
485
|
+
6. `budget_report()` recalculates totals and category rows.
|
|
486
|
+
|
|
487
|
+
### AI Insights
|
|
488
|
+
|
|
489
|
+
1. User selects today, single day, or range.
|
|
490
|
+
2. `build_period_report()` gathers task, session, mind-log, project, audio, and
|
|
491
|
+
reschedule evidence.
|
|
492
|
+
3. `score_period()` uses Settings-backed score weights and thresholds.
|
|
493
|
+
4. `build_ai_insight_modules()` adds the deterministic attention support detectors.
|
|
494
|
+
5. Deterministic scores/flags/modules are shown.
|
|
495
|
+
6. Optional local or API LLM receives the compact report.
|
|
496
|
+
7. AI cache can save common deterministic reports. LLM cache is local-model only
|
|
497
|
+
in time-2.0.5.
|
|
498
|
+
|
|
499
|
+
## Storage Files
|
|
500
|
+
|
|
501
|
+
### Main board JSON
|
|
502
|
+
|
|
503
|
+
```text
|
|
504
|
+
time2_data.json
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
Contains:
|
|
508
|
+
|
|
509
|
+
- `items`
|
|
510
|
+
- `mind_logs`
|
|
511
|
+
- `audio_logs`
|
|
512
|
+
|
|
513
|
+
### Task files
|
|
514
|
+
|
|
515
|
+
```text
|
|
516
|
+
time2_tasks/
|
|
517
|
+
index.json
|
|
518
|
+
item_xxxxxxxx.json
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
Used when per-task file storage is enabled.
|
|
522
|
+
|
|
523
|
+
### Mind log files
|
|
524
|
+
|
|
525
|
+
```text
|
|
526
|
+
time2_mind_logs/
|
|
527
|
+
index.json
|
|
528
|
+
mind_xxxxxxxx.json
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
Used when per-mind-log file storage is enabled.
|
|
532
|
+
|
|
533
|
+
### Audio files
|
|
534
|
+
|
|
535
|
+
```text
|
|
536
|
+
time2_audio/
|
|
537
|
+
audio_xxxxxxxx_original_name.wav
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
The main JSON stores metadata and transcript text.
|
|
541
|
+
|
|
542
|
+
### Budget files
|
|
543
|
+
|
|
544
|
+
```text
|
|
545
|
+
time2_budget/
|
|
546
|
+
budget_2026_07.json
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
Each month file stores budget entries for that budget period.
|
|
550
|
+
|
|
551
|
+
### Backups
|
|
552
|
+
|
|
553
|
+
```text
|
|
554
|
+
time2_backups/
|
|
555
|
+
time2_backup_YYYYMMDD_HHMMSS.json
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
Backup payload:
|
|
559
|
+
|
|
560
|
+
- `created_at`
|
|
561
|
+
- `board`
|
|
562
|
+
- `settings`
|
|
563
|
+
|
|
564
|
+
### AI cache
|
|
565
|
+
|
|
566
|
+
```text
|
|
567
|
+
time2_ai_cache/
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
Stores deterministic and optional LLM report payloads.
|
|
571
|
+
|
|
572
|
+
## Settings Flow
|
|
573
|
+
|
|
574
|
+
When adding settings:
|
|
575
|
+
|
|
576
|
+
1. Add default in `DEFAULT_SETTINGS` in `config.py`.
|
|
577
|
+
2. Normalize in `load_settings()` in `utils.py`.
|
|
578
|
+
3. Add controls in `render_settings_tab()` or a helper in `views.py`.
|
|
579
|
+
4. Update `examples/time2_settings.example.json`.
|
|
580
|
+
5. Update docs.
|
|
581
|
+
|
|
582
|
+
## Compatibility Rules
|
|
583
|
+
|
|
584
|
+
The app should continue to open old JSON files.
|
|
585
|
+
|
|
586
|
+
When adding fields:
|
|
587
|
+
|
|
588
|
+
- Always use `.get()` with defaults in `from_dict()`.
|
|
589
|
+
- Do not assume old data has new keys.
|
|
590
|
+
- Do not delete unknown runtime data.
|
|
591
|
+
- Prefer adding fields rather than reshaping existing fields.
|
|
592
|
+
|
|
593
|
+
## Testing Checklist
|
|
594
|
+
|
|
595
|
+
Run this after code changes:
|
|
596
|
+
|
|
597
|
+
```bash
|
|
598
|
+
python -m py_compile time2_streamlit_app.py time2_jupyter_launcher.py time2_tailscale_jupyter_launcher.py time2_ai_cache_worker.py time2_app/*.py tests/time2_regression_checks.py
|
|
599
|
+
python tests/time2_regression_checks.py
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
Run a Streamlit AppTest smoke test:
|
|
603
|
+
|
|
604
|
+
```bash
|
|
605
|
+
python -c "from streamlit.testing.v1 import AppTest; at=AppTest.from_file('time2_streamlit_app.py', default_timeout=30); at.run(timeout=30); print([tab.label for tab in at.tabs]); print('exceptions', len(at.exception)); [print(e.value) for e in at.exception]"
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
Expected full tab list:
|
|
609
|
+
|
|
610
|
+
```text
|
|
611
|
+
Add
|
|
612
|
+
Planning
|
|
613
|
+
Deadlines
|
|
614
|
+
Matrix
|
|
615
|
+
E2 Plot
|
|
616
|
+
Mind Log
|
|
617
|
+
Pending
|
|
618
|
+
Victory Board
|
|
619
|
+
Cancelled
|
|
620
|
+
Dashboard
|
|
621
|
+
Budget
|
|
622
|
+
AI Insights
|
|
623
|
+
AI Chat
|
|
624
|
+
Reports
|
|
625
|
+
Settings
|
|
626
|
+
Data
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
Recommended extra checks:
|
|
630
|
+
|
|
631
|
+
- Fresh unzip with no `time2_settings.json` shows First-time setup.
|
|
632
|
+
- Seeded settings opens all tabs.
|
|
633
|
+
- `time2 doctor` runs after editable install.
|
|
634
|
+
- `time2 run --open-browser` starts the app from the installed package entry.
|
|
635
|
+
- Reserved task can be added without planned date/deadline and turns non-reserved
|
|
636
|
+
when a planned date or deadline is saved.
|
|
637
|
+
- Task with attached audio opens in E2 without nested expander error.
|
|
638
|
+
- Task transcript is visible.
|
|
639
|
+
- Task comment audio transcript is visible under the same task.
|
|
640
|
+
- Mind transcript is visible.
|
|
641
|
+
- Budget transcript is visible.
|
|
642
|
+
- AI Chat works with local provider settings and API provider settings.
|
|
643
|
+
- Settings private-access section detects Tailscale or shows the install link.
|
|
644
|
+
- Zip contains no `__pycache__` or `.pyc`.
|
|
645
|
+
- Zip contains no private local paths.
|
|
646
|
+
|
|
647
|
+
## Packaging Checklist
|
|
648
|
+
|
|
649
|
+
For pip package publishing, see `docs/PACKAGING.md`.
|
|
650
|
+
|
|
651
|
+
Build package artifacts:
|
|
652
|
+
|
|
653
|
+
```bash
|
|
654
|
+
python -m pip install --upgrade build twine
|
|
655
|
+
python -m build
|
|
656
|
+
python -m twine check dist/*
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
Then install the wheel in a clean environment and verify:
|
|
660
|
+
|
|
661
|
+
```bash
|
|
662
|
+
python -m pip install dist/time2_local-2.0.5-py3-none-any.whl
|
|
663
|
+
time2 doctor
|
|
664
|
+
time2 run --open-browser
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
Do not include runtime/private data in any release zip, wheel, source
|
|
668
|
+
distribution, or repository upload.
|
|
669
|
+
|
|
670
|
+
## Next Version Starting Points
|
|
671
|
+
|
|
672
|
+
### Local accounts
|
|
673
|
+
|
|
674
|
+
Files to touch:
|
|
675
|
+
|
|
676
|
+
- `models.py`: add user model or owner fields.
|
|
677
|
+
- `storage.py`: save/load user auth data.
|
|
678
|
+
- `views.py`: login/settings UI.
|
|
679
|
+
- `app.py`: gate the app after settings load.
|
|
680
|
+
|
|
681
|
+
Use password hashing such as Argon2id or bcrypt.
|
|
682
|
+
|
|
683
|
+
### SQLite migration
|
|
684
|
+
|
|
685
|
+
Files to add/touch:
|
|
686
|
+
|
|
687
|
+
- New `database.py`.
|
|
688
|
+
- `models.py` for conversion helpers.
|
|
689
|
+
- `storage.py` for import/export compatibility.
|
|
690
|
+
- `views.py` Data tab for migration controls.
|
|
691
|
+
|
|
692
|
+
Keep JSON export/import.
|
|
693
|
+
|
|
694
|
+
### Transcript search
|
|
695
|
+
|
|
696
|
+
Files to touch:
|
|
697
|
+
|
|
698
|
+
- `models.py`: ensure transcript fields are indexed in summaries.
|
|
699
|
+
- `views.py`: add search UI in Dashboard or new Search tab.
|
|
700
|
+
- `ai.py`: include transcript snippets in evidence payloads.
|
|
701
|
+
|
|
702
|
+
### Budget editing
|
|
703
|
+
|
|
704
|
+
Files to touch:
|
|
705
|
+
|
|
706
|
+
- `budget.py`: update/delete entry helpers.
|
|
707
|
+
- `views.py`: add edit controls inside Budget tab.
|
|
708
|
+
- Docs/manual.
|
|
709
|
+
|
|
710
|
+
### Calendar integration
|
|
711
|
+
|
|
712
|
+
Files to add/touch:
|
|
713
|
+
|
|
714
|
+
- New `calendar_export.py`.
|
|
715
|
+
- `views.py`: export/import controls.
|
|
716
|
+
- `models.py`: stable event/task mapping.
|
|
717
|
+
|
|
718
|
+
## Known Design Tradeoffs
|
|
719
|
+
|
|
720
|
+
- JSON storage is easy to inspect but not ideal for simultaneous multi-user
|
|
721
|
+
editing.
|
|
722
|
+
- Whisper runs synchronously in the app, so long audio can block the UI.
|
|
723
|
+
- Local LLM generation can be slow on laptops.
|
|
724
|
+
- Streamlit is excellent for fast local tools but not a full multi-user web app
|
|
725
|
+
framework without extra care.
|
|
726
|
+
- The app has no login yet. Tailscale is the current private access layer.
|
|
727
|
+
|
|
728
|
+
## Commenting Policy
|
|
729
|
+
|
|
730
|
+
The source code uses:
|
|
731
|
+
|
|
732
|
+
- Module-level dependency notes.
|
|
733
|
+
- Clear function names.
|
|
734
|
+
- Focused comments before non-obvious blocks.
|
|
735
|
+
|
|
736
|
+
It intentionally does not comment every single line. Line-by-line comments make
|
|
737
|
+
the code harder to maintain. This guide is the detailed explanation layer for
|
|
738
|
+
future development.
|