77from pathlib import Path
88from datetime import datetime
99
10+
1011def create_individual_exhibits ():
1112 """Create individual Exhibit A files for each contributor."""
12-
13+
1314 # Read the JSON inventory
1415 inventory_file = Path ("legal_inventory_main/basic_memory_inventory_20250730_101521.json" )
15-
16+
1617 if not inventory_file .exists ():
1718 print (f"Error: { inventory_file } not found" )
1819 return
19-
20- with open (inventory_file , 'r' ) as f :
20+
21+ with open (inventory_file , "r" ) as f :
2122 data = json .load (f )
22-
23- files = data [' files' ]
24-
23+
24+ files = data [" files" ]
25+
2526 # Create output directory
2627 output_dir = Path ("legal_exhibits" )
2728 output_dir .mkdir (exist_ok = True )
28-
29+
2930 # Contributors we need exhibits for (based on copyright assignments)
3031 target_contributors = {
31- ' jope-bm' : 'Joseph "Joe" [Last Name]' , # Need to get his full name
32- ' Drew Cain' : ' Drew Cain'
32+ " jope-bm" : 'Joseph "Joe" [Last Name]' , # Need to get his full name
33+ " Drew Cain" : " Drew Cain" ,
3334 }
34-
35+
3536 print ("Creating individual contributor exhibits..." )
36-
37+
3738 for contributor_key , full_name in target_contributors .items ():
3839 # Find files for this contributor
3940 contributor_files = []
40-
41+
4142 for file_info in files :
4243 # Check if this contributor is listed in the file's contributors
43- for contrib in file_info .get (' contributors' , []):
44- if contributor_key in contrib [' name' ]:
44+ for contrib in file_info .get (" contributors" , []):
45+ if contributor_key in contrib [" name" ]:
4546 contributor_files .append (file_info )
4647 break
47-
48+
4849 if not contributor_files :
4950 print (f"No files found for { contributor_key } " )
5051 continue
51-
52+
5253 # Sort files by path
53- contributor_files .sort (key = lambda x : x [' path' ])
54-
54+ contributor_files .sort (key = lambda x : x [" path" ])
55+
5556 # Create exhibit markdown
5657 exhibit_content = f"""# Exhibit A - Assigned Works
5758## Copyright Assignment: { full_name } to Basic Memory LLC
@@ -62,44 +63,44 @@ def create_individual_exhibits():
6263
6364## Summary
6465- **Total Files:** { len (contributor_files )}
65- - **Total Size:** { sum (f [' size_bytes' ] for f in contributor_files ):,} bytes
66- - **Categories:** { ', ' .join (set (f [' category' ] for f in contributor_files ))}
66+ - **Total Size:** { sum (f [" size_bytes" ] for f in contributor_files ):,} bytes
67+ - **Categories:** { ", " .join (set (f [" category" ] for f in contributor_files ))}
6768
6869## Detailed File List
6970
7071"""
71-
72+
7273 # Group by category
7374 categories = {}
7475 for file_info in contributor_files :
75- category = file_info [' category' ]
76+ category = file_info [" category" ]
7677 if category not in categories :
7778 categories [category ] = []
7879 categories [category ].append (file_info )
79-
80+
8081 # Add files by category
8182 for category , category_files in sorted (categories .items ()):
8283 exhibit_content += f"### { category .replace ('_' , ' ' ).title ()} \n \n "
83-
84+
8485 for file_info in category_files :
8586 exhibit_content += f"**{ file_info ['path' ]} **\n "
8687 exhibit_content += f"- Size: { file_info ['size_bytes' ]:,} bytes\n "
8788 exhibit_content += f"- Modified: { file_info ['modified_time' ][:10 ]} \n "
8889 exhibit_content += f"- Primary Author: { file_info ['primary_author' ]} \n "
89-
90+
9091 # Show all contributors for this file
91- if len (file_info [' contributors' ]) > 1 :
92- contributors_list = ', ' .join ([c [' name' ] for c in file_info [' contributors' ]])
92+ if len (file_info [" contributors" ]) > 1 :
93+ contributors_list = ", " .join ([c [" name" ] for c in file_info [" contributors" ]])
9394 exhibit_content += f"- All Contributors: { contributors_list } \n "
94-
95+
9596 exhibit_content += f"- SHA-256: `{ file_info ['sha256_hash' ]} `\n \n "
96-
97+
9798 # Add verification section
9899 exhibit_content += f"""
99100## Verification
100101This exhibit lists all files in the Basic Memory repository where { full_name } is identified as a contributor based on git commit history analysis.
101102
102- **Analysis Date:** { datetime .now ().strftime (' %Y-%m-%d' )}
103+ **Analysis Date:** { datetime .now ().strftime (" %Y-%m-%d" )}
103104**Repository State:** Basic Memory main branch
104105**Method:** Git history analysis via `git log --follow` for each file
105106
@@ -110,54 +111,55 @@ def create_individual_exhibits():
110111
111112*This exhibit is attached to and forms part of the Copyright Assignment Agreement between { full_name } and Basic Memory LLC.*
112113"""
113-
114+
114115 # Write exhibit file
115- safe_name = contributor_key .replace (' ' , '_' ).replace ('-' , '_' ).lower ()
116+ safe_name = contributor_key .replace (" " , "_" ).replace ("-" , "_" ).lower ()
116117 exhibit_file = output_dir / f"exhibit_a_{ safe_name } .md"
117-
118- with open (exhibit_file , 'w' ) as f :
118+
119+ with open (exhibit_file , "w" ) as f :
119120 f .write (exhibit_content )
120-
121+
121122 print (f"Created exhibit for { full_name } : { exhibit_file } " )
122123 print (f" - { len (contributor_files )} files" )
123124 print (f" - { sum (f ['size_bytes' ] for f in contributor_files ):,} bytes" )
124-
125+
125126 # Create overall summary exhibit (for Paul's assignment to Basic Machines LLC)
126127 create_overall_summary_exhibit (data , output_dir )
127128
129+
128130def create_overall_summary_exhibit (data , output_dir ):
129131 """Create overall summary exhibit for Company Agreement."""
130-
131- files = data [' files' ]
132- summary = data [' summary' ]
133- contributors = data [' contributors' ]
134-
132+
133+ files = data [" files" ]
134+ summary = data [" summary" ]
135+ contributors = data [" contributors" ]
136+
135137 summary_content = f"""# Basic Memory Repository - Complete IP Inventory
136138## For Basic Memory LLC Company Agreement
137139
138- **Analysis Date:** { summary [' scan_date' ][:10 ]}
139- **Repository:** { summary [' repository_path' ]}
140+ **Analysis Date:** { summary [" scan_date" ][:10 ]}
141+ **Repository:** { summary [" repository_path" ]}
140142
141143## Executive Summary
142- - **Total Files:** { summary [' total_files' ]:,}
143- - **Total Size:** { summary [' total_size_bytes' ]:,} bytes
144- - **Contributors:** { summary [' contributor_count' ]}
145- - **Primary Author:** Paul Hernandez ({ len (contributors .get (' Paul Hernandez' , {}).get (' files' , []))} files)
144+ - **Total Files:** { summary [" total_files" ]:,}
145+ - **Total Size:** { summary [" total_size_bytes" ]:,} bytes
146+ - **Contributors:** { summary [" contributor_count" ]}
147+ - **Primary Author:** Paul Hernandez ({ len (contributors .get (" Paul Hernandez" , {}).get (" files" , []))} files)
146148
147149## File Categories
148150"""
149-
150- for category , count in sorted (summary [' categories' ].items ()):
151+
152+ for category , count in sorted (summary [" categories" ].items ()):
151153 summary_content += f"- **{ category .replace ('_' , ' ' ).title ()} :** { count } files\n "
152-
154+
153155 summary_content += """
154156
155157## Contributor Summary
156158"""
157-
158- for contrib in summary [' top_contributors' ]:
159+
160+ for contrib in summary [" top_contributors" ]:
159161 summary_content += f"- **{ contrib ['name' ]} ** ({ contrib ['email' ]} ): { contrib ['file_count' ]} files, { contrib ['commit_count' ]} commits\n "
160-
162+
161163 summary_content += """
162164
163165## Legal Significance
@@ -177,32 +179,33 @@ def create_overall_summary_exhibit(data, output_dir):
177179## Repository Contents by Category
178180
179181"""
180-
182+
181183 # Add sample files by category (first 10 in each category)
182- for category in sorted (summary [' categories' ].keys ()):
183- category_files = [f for f in files if f [' category' ] == category ][:10 ]
184+ for category in sorted (summary [" categories" ].keys ()):
185+ category_files = [f for f in files if f [" category" ] == category ][:10 ]
184186 if category_files :
185187 summary_content += f"### { category .replace ('_' , ' ' ).title ()} (Sample)\n \n "
186188 for file_info in category_files :
187189 summary_content += f"- `{ file_info ['path' ]} ` ({ file_info ['size_bytes' ]:,} bytes)\n "
188-
189- if len ([f for f in files if f [' category' ] == category ]) > 10 :
190- remaining = len ([f for f in files if f [' category' ] == category ]) - 10
190+
191+ if len ([f for f in files if f [" category" ] == category ]) > 10 :
192+ remaining = len ([f for f in files if f [" category" ] == category ]) - 10
191193 summary_content += f"- *... and { remaining } more files*\n "
192194 summary_content += "\n "
193-
195+
194196 summary_content += f"""
195197---
196198
197- *This inventory was generated automatically from git repository analysis and represents the complete intellectual property foundation of Basic Memory as of { summary [' scan_date' ][:10 ]} .*
199+ *This inventory was generated automatically from git repository analysis and represents the complete intellectual property foundation of Basic Memory as of { summary [" scan_date" ][:10 ]} .*
198200"""
199-
201+
200202 # Write summary file
201203 summary_file = output_dir / "basic_memory_complete_inventory.md"
202- with open (summary_file , 'w' ) as f :
204+ with open (summary_file , "w" ) as f :
203205 f .write (summary_content )
204-
206+
205207 print (f"Created complete inventory summary: { summary_file } " )
206208
207- if __name__ == '__main__' :
208- create_individual_exhibits ()
209+
210+ if __name__ == "__main__" :
211+ create_individual_exhibits ()
0 commit comments