22import os
33import subprocess
44import sys
5- from datetime import date
5+ from datetime import date , datetime
66
77def run_command (command ):
88 result = subprocess .run (command , capture_output = True , text = True , shell = True )
@@ -13,21 +13,21 @@ def main():
1313 journal_path = f"journal/{ today } .md"
1414
1515 # Scan for changes (staged, modified, untracked)
16- # git status --porcelain shows all changes
1716 res = run_command ("git status --porcelain" )
1817 changed_files = [line [3 :] for line in res .stdout .strip ().splitlines () if line ]
1918
2019 if not changed_files :
2120 return 0
2221
23- # Run make
24- print ("Running validation (make test)..." )
25- res = run_command ("make test" )
26- if res .returncode != 0 :
27- print ("Validation failed:" )
28- print (res .stdout )
29- print (res .stderr )
30- return res .returncode
22+ # Run make test (if makefile exists)
23+ if os .path .exists ("makefile" ):
24+ print ("Running validation (make test)..." )
25+ res = run_command ("make test" )
26+ if res .returncode != 0 :
27+ print ("Validation failed:" )
28+ print (res .stdout )
29+ print (res .stderr )
30+ return res .returncode
3131
3232 # Calculate max(mtime) for all changed files (excluding .gemini/ and the journal)
3333 meaningful_changes = [f for f in changed_files if not f .startswith (".gemini/" ) and f != journal_path ]
@@ -37,20 +37,46 @@ def main():
3737
3838 max_mtime = 0
3939 for f in meaningful_changes :
40+ # git status might show deleted files, check if exists
4041 if os .path .exists (f ):
4142 mtime = os .path .getmtime (f )
4243 if mtime > max_mtime :
4344 max_mtime = mtime
4445
45- # Check journal mtime
46+ # Check journal entry
4647 if not os .path .exists (journal_path ):
47- print (f"Error: Updated journal required (create { journal_path } with a summary of recent changes)." )
48+ print (f"Error: Updated journal required. Please read the latest entries in journal/ to understand context," )
49+ print (f"then use: python3 .gemini/scripts/journal.py 'one line summary of changes'" )
4850 return 1
4951
50- journal_mtime = os .path .getmtime (journal_path )
52+ with open (journal_path , "r" ) as f :
53+ lines = [l .strip () for l in f .readlines () if l .strip ()]
5154
52- if journal_mtime < max_mtime :
53- print (f"Error: Updated journal required (update { journal_path } to include a summary of recent changes)." )
55+ if not lines :
56+ print (f"Error: Journal { journal_path } is empty." )
57+ print (f"Please use: python3 .gemini/scripts/journal.py 'one line summary of changes'" )
58+ return 1
59+
60+ last_line = lines [- 1 ]
61+ # Expected format: [timestamp ISO] - description
62+ if not (last_line .startswith ("[" ) and "] - " in last_line ):
63+ print (f"Error: Invalid journal entry format in { journal_path } : '{ last_line } '" )
64+ print (f"Expected format: '[YYYY-MM-DDTHH:MM:SS] - description'" )
65+ print (f"Please use: python3 .gemini/scripts/journal.py 'one line summary of changes'" )
66+ return 1
67+
68+ try :
69+ ts_str = last_line [1 :last_line .index ("]" )]
70+ last_entry_time = datetime .fromisoformat (ts_str ).timestamp ()
71+ except (ValueError , IndexError ):
72+ print (f"Error: Could not parse timestamp from journal entry: '{ last_line } '" )
73+ print (f"Please use: python3 .gemini/scripts/journal.py 'one line summary of changes'" )
74+ return 1
75+
76+ if last_entry_time < max_mtime :
77+ print (f"Error: Last journal entry is older than recent changes." )
78+ print (f"Please read { journal_path } to catch up, then add a summary of your latest work using:" )
79+ print (f"python3 .gemini/scripts/journal.py 'one line summary of changes'" )
5480 return 1
5581
5682 return 0
0 commit comments