@@ -79,10 +79,11 @@ def _add_annotations_to_source(self, workflow_path: Path, content: str) -> None:
7979 hash_value = self .compute_hash (expanded )
8080 rel_cache_path = cache_path .relative_to (self .base_path )
8181
82- # Create annotation
82+ # Create annotation with explicit "project root" note
8383 indent = len (line ) - len (line .lstrip ())
8484 annotation = (
85- " " * indent + f"# you see: <{ rel_cache_path } > <{ hash_value } >"
85+ " " * indent
86+ + f"# you see: <{ rel_cache_path } > (project root) <{ hash_value } >"
8687 )
8788 added_annotations [import_path ] = annotation
8889
@@ -129,7 +130,8 @@ def _expand_imports(self, content: str, base_path: Path, cache: bool = True) ->
129130 # Add annotation BEFORE import line (with matching indent)
130131 indent = len (line ) - len (line .lstrip ())
131132 annotation = (
132- " " * indent + f"# you see: <{ rel_cache_path } > <{ hash_value } >"
133+ " " * indent
134+ + f"# you see: <{ rel_cache_path } > (project root) <{ hash_value } >"
133135 )
134136 output .append (annotation )
135137
@@ -170,25 +172,27 @@ def _fetch_remote(self, url: str) -> str:
170172 raise RuntimeError (f"Failed to fetch { url } : { e } " ) from e
171173
172174 def _get_import_cache_path (self , import_path : str , base_path : Path ) -> Path :
173- """Get cache file path for a single import .
175+ """Get cache file path using hash-based naming (flat structure) .
174176
175- Each import is cached independently with a clear name.
177+ Design:
178+ - Cache files named by content hash prefix + original filename
179+ - Flat structure (no deep directories)
180+ - Deduplication: same content = same cache file
181+ - User reads import line for source, cache is internal storage
176182 """
183+ # Fetch content to compute hash
184+ imported_content = self ._fetch_import (import_path , base_path )
185+ content_hash = hashlib .sha256 (imported_content .encode ("utf-8" )).hexdigest ()[:16 ]
186+
187+ # Extract original filename for readability
177188 if import_path .startswith (("http://" , "https://" )):
178- # URL: create path from URL structure
179- # https://raw.githubusercontent.com/user/repo/main/file.workflow.list
180- # → .imports/raw.githubusercontent.com/user/repo/main/file.workflow.list
181- url_parts = (
182- import_path .replace ("https://" , "" ).replace ("http://" , "" ).split ("/" )
183- )
184- cache_path = self .imports_dir / "/" .join (url_parts )
189+ original_name = import_path .split ("/" )[- 1 ]
185190 else :
186- # Local path: preserve relative structure
187- if Path (import_path ).is_absolute ():
188- rel_path = Path (import_path ).relative_to (base_path )
189- else :
190- rel_path = Path (import_path )
191- cache_path = self .imports_dir / rel_path
191+ original_name = Path (import_path ).name
192+
193+ # Format: <hash-prefix>-<original-name>
194+ cache_filename = f"{ content_hash } -{ original_name } "
195+ cache_path = self .imports_dir / cache_filename
192196
193197 cache_path .parent .mkdir (parents = True , exist_ok = True )
194198 return cache_path
@@ -199,8 +203,8 @@ def compute_hash(self, content: str) -> str:
199203 return f"sha256:{ hash_value } "
200204
201205 def validate_cache_annotation (self , annotation : str ) -> tuple [str , str ] | None :
202- """Validate cache annotation format: # you see: <path> <algo:hash>."""
203- pattern = r"# you see: <([\w./-]+)> <(sha256|md5):([a-f0-9]+)>"
206+ """Validate cache annotation format: # you see: <path> (project root) <algo:hash>."""
207+ pattern = r"# you see: <([\w./-]+)> \(project root\) <(sha256|md5):([a-f0-9]+)>"
204208 match = re .match (pattern , annotation .strip ())
205209 if not match :
206210 return None
0 commit comments