1313
1414ROOT = Path (__file__ ).resolve ().parent .parent
1515DAILY = ROOT / "daily"
16- DAILY_ARCHIVE = DAILY / "archive"
1716RECURRENCE = ROOT / "dtm" / "recurring-tasks.json"
1817
1918SECTIONS = [
@@ -43,6 +42,14 @@ class DTMError(RuntimeError):
4342 """A safe, user-actionable DTM configuration or lifecycle failure."""
4443
4544
45+ def vault_root () -> Path :
46+ return DAILY .parent
47+
48+
49+ def daily_archive_dir () -> Path :
50+ return DAILY / "archive"
51+
52+
4653def parse_date (value : str ) -> date :
4754 try :
4855 return date .fromisoformat (value )
@@ -55,7 +62,7 @@ def active_note_path(day: date) -> Path:
5562
5663
5764def archived_note_path (day : date ) -> Path :
58- return DAILY_ARCHIVE / f"{ day .isoformat ()} .md"
65+ return daily_archive_dir () / f"{ day .isoformat ()} .md"
5966
6067
6168def note_path (day : date ) -> Path :
@@ -73,7 +80,7 @@ def note_exists(day: date) -> bool:
7380
7481
7582def note_link (day : date ) -> str :
76- return note_path (day ).relative_to (ROOT ).with_suffix ("" ).as_posix ()
83+ return note_path (day ).relative_to (vault_root () ).with_suffix ("" ).as_posix ()
7784
7885
7986def active_note_files () -> list [Path ]:
@@ -82,7 +89,7 @@ def active_note_files() -> list[Path]:
8289
8390def all_note_files () -> list [Path ]:
8491 active = active_note_files ()
85- archived = sorted (path for path in DAILY_ARCHIVE .glob ("*.md" ) if path .name != "README.md" )
92+ archived = sorted (path for path in daily_archive_dir () .glob ("*.md" ) if path .name != "README.md" )
8693 return active + archived
8794
8895
@@ -322,7 +329,7 @@ def replace_frontmatter_value(text: str, field: str, value: str) -> str:
322329def close_day (day : date , next_day : date | None = None ) -> bool :
323330 path = note_path (day )
324331 if not path .exists ():
325- print (f"No Daily Note to close: { path .relative_to (ROOT )} " )
332+ print (f"No Daily Note to close: { path .relative_to (vault_root () )} " )
326333 return False
327334 text = path .read_text (encoding = "utf-8" )
328335 changed = replace_frontmatter_value (text , "status" , "closed" )
@@ -332,21 +339,21 @@ def close_day(day: date, next_day: date | None = None) -> bool:
332339 )
333340 if changed != text :
334341 path .write_text (changed , encoding = "utf-8" )
335- print (f"Closed { path .relative_to (ROOT )} " )
342+ print (f"Closed { path .relative_to (vault_root () )} " )
336343 else :
337- print (f"Already closed { path .relative_to (ROOT )} " )
344+ print (f"Already closed { path .relative_to (vault_root () )} " )
338345 return True
339346
340347
341348def open_day (day : date ) -> bool :
342349 path = active_note_path (day )
343350 if path .exists ():
344- print (f"Already open/present: { path .relative_to (ROOT )} " )
351+ print (f"Already open/present: { path .relative_to (vault_root () )} " )
345352 return False
346353 previous_text = read_note (day - timedelta (days = 1 ))
347354 path .parent .mkdir (parents = True , exist_ok = True )
348355 path .write_text (render_note (day , previous_text ), encoding = "utf-8" )
349- print (f"Created { path .relative_to (ROOT )} " )
356+ print (f"Created { path .relative_to (vault_root () )} " )
350357 return True
351358
352359
@@ -365,10 +372,10 @@ def append_activity(day: date, actor: str, message: str, timestamp: str | None =
365372 text = path .read_text (encoding = "utf-8" )
366373 notes_match = re .search (r"^## Notes & Activity\s*$" , text , re .M )
367374 if notes_match is None :
368- raise DTMError (f"{ path .relative_to (ROOT )} is missing the Notes & Activity section" )
375+ raise DTMError (f"{ path .relative_to (vault_root () )} is missing the Notes & Activity section" )
369376 decisions_match = re .search (r"^## Decisions\s*$" , text , re .M )
370377 if decisions_match is None :
371- raise DTMError (f"{ path .relative_to (ROOT )} is missing the Decisions section" )
378+ raise DTMError (f"{ path .relative_to (vault_root () )} is missing the Decisions section" )
372379
373380 entry = f"- { time_value } — { actor .strip ()} — { message .strip ()} "
374381 notes_heading = "## Notes & Activity"
@@ -381,7 +388,7 @@ def append_activity(day: date, actor: str, message: str, timestamp: str | None =
381388 notes_body = text [notes_end :marker_start ]
382389 notes_lines = notes_body .rstrip ("\n " ).splitlines ()
383390 if entry in notes_lines :
384- print (f"Activity already present in { path .relative_to (ROOT )} " )
391+ print (f"Activity already present in { path .relative_to (vault_root () )} " )
385392 return False
386393 if notes_lines and notes_lines [- 1 ].strip ():
387394 notes_lines .append (entry )
@@ -391,7 +398,7 @@ def append_activity(day: date, actor: str, message: str, timestamp: str | None =
391398
392399 updated_before = f"{ notes_prefix } { notes_heading } \n { chr (10 ).join (notes_lines )} \n "
393400 path .write_text (f"{ updated_before } ## Decisions{ after } " , encoding = "utf-8" )
394- print (f"Updated { path .relative_to (ROOT )} " )
401+ print (f"Updated { path .relative_to (vault_root () )} " )
395402 return True
396403
397404
@@ -412,19 +419,20 @@ def archive_notes(keep: int) -> int:
412419 if len (note_files ) <= keep :
413420 print (f"No Daily Notes archived; { len (note_files )} active note(s) within keep window { keep } ." )
414421 return 0
415- DAILY_ARCHIVE .mkdir (parents = True , exist_ok = True )
422+ archive_dir = daily_archive_dir ()
423+ archive_dir .mkdir (parents = True , exist_ok = True )
416424 to_move = note_files [:- keep ]
417425 moved_days : list [date ] = []
418426 for path in to_move :
419427 if not DATE_RE .fullmatch (path .stem ):
420- raise DTMError (f"Cannot archive non-date Daily Note { path .relative_to (ROOT )} " )
428+ raise DTMError (f"Cannot archive non-date Daily Note { path .relative_to (vault_root () )} " )
421429 day = date .fromisoformat (path .stem )
422430 target = archived_note_path (day )
423431 if target .exists ():
424- raise DTMError (f"Archive destination already exists: { target .relative_to (ROOT )} " )
432+ raise DTMError (f"Archive destination already exists: { target .relative_to (vault_root () )} " )
425433 path .rename (target )
426434 moved_days .append (day )
427- print (f"Archived { path .relative_to (ROOT ) } -> { target .relative_to (ROOT )} " )
435+ print (f"Archived { path .relative_to (vault_root ()) } -> { target .relative_to (vault_root () )} " )
428436 affected_days = set (moved_days )
429437 for moved_day in moved_days :
430438 affected_days .add (moved_day - timedelta (days = 1 ))
0 commit comments