inventory_inputs.py
python · 227 lines · Sanitized derivative
Sanitized derivative: private paths or personal test identities use explicit placeholders. Original line count is preserved.
Version & provenance · data-cm7
Recorded SHA-256 79c7ee0364216138ae4a15b17be117d0176ac4a392e2f05354e6e886c8083183Rendered SHA-256 1cb9091cc30fd7c1e01769cef8e10e4765acdf34fbd6c520f310c4b3c412f8ff
Apache-2.0 original project code; dependencies retain their own licenses. License notes. Line links are stable within this snapshot. CM-7 completed implementation source; original and public rendered hashes recorded. Host-specific paths use /work placeholders; inspect reproduction instructions before running. Separate Rust helper retains its GPL license.
1"""CPU-only inventory. No training output is published by this program."""
2import argparse, collections, hashlib, io, json, sqlite3, sys, time, zipfile
3from pathlib import Path
4from acquire_inputs import ROOT, BOOKS, guard, save, sha
5
6PROJECT=Path('/work/source/2026-10-27/task-14/causal-chess-v1')
7sys.path.insert(0,str(PROJECT/'state-v2'))
8sys.path.insert(0,str(PROJECT/'elite-continuation-v1'))
9import codec as c
10import chess.pgn, chess.syzygy
11from chessdata.reader import _read_shard
12STATE=Path('/work/causal-chess-state-v2-20261029')
13
14def protection():
15 m=json.loads((STATE/'manifest.json').read_text());done=json.loads((STATE/'completion.json').read_text())
16 if sha(STATE/'manifest.json')!=done['manifest_sha256']:raise ValueError('seal mismatch')
17 identity=json.dumps(m['identity'],sort_keys=True,separators=(',',':')).encode()
18 if hashlib.sha256(identity).hexdigest()!=m['identity_sha256']:raise ValueError('identity mismatch')
19 if sha(PROJECT/'state-v2'/'codec.py')!=m['identity']['code']['codec.py']:raise ValueError('codec changed')
20 config=m['identity']['config']
21 for r in config['references']:
22 if sha(Path(r['root'])/'manifest.json')!=r['manifest_sha256']:raise ValueError('historical source changed')
23 db=sqlite3.connect('file:'+str(STATE/'journal.sqlite')+'?mode=ro',uri=True)
24 db.execute('PRAGMA query_only=ON')
25 if db.execute("SELECT v FROM settings WHERE k='identity'").fetchone()[0]!=m['identity_sha256']:raise ValueError('protection identity')
26 if db.execute("SELECT v FROM progress WHERE k='protection_complete'").fetchone()!=('true',):raise ValueError('protection unfinished')
27 for table,field in [('protected','protected_positions'),('protected_games','protected_game_aliases')]:
28 if db.execute('SELECT COUNT(*) FROM '+table).fetchone()[0]!=done[field]:raise ValueError('protection count')
29 save('protection-receipt.json',dict(manifest_sha256=done['manifest_sha256'],identity_sha256=m['identity_sha256'],
30 protected_positions=done['protected_positions'],protected_game_aliases=done['protected_game_aliases'],
31 journal_open_mode='read-only; no copy',references_verified=config['references']))
32 return db,config
33
34def is_protected(db,key):return db.execute('SELECT 1 FROM protected WHERE k=?',(key,)).fetchone() is not None
35
36def aliases(meta):return ['seq:'+meta['sequence_sha256']]+['id:'+x for x in set(meta.get('game_ids',[])+([meta['game_id']] if meta.get('game_id') else []))]
37
38def replay(tokens,meta):
39 if tokens[0]!=c.BOS or tokens[-1]!=c.EOS or (len(tokens)-2)%3:raise ValueError('token contract')
40 board=c.chess.Board();boards=[];moves=[]
41 for start in range(1,len(tokens)-1,3):
42 move=c.decode(list(tokens[start:start+3]))
43 if board.is_game_over(claim_draw=False) or move not in board.legal_moves:raise ValueError('post-terminal or illegal game')
44 if len(board.piece_map())<=5:
45 boards.append((board.copy(stack=True),len(moves),move.uci()))
46 board.push(move);moves.append(move.uci())
47 if len(moves)!=meta['plies'] or board.fen()!=meta['final_fen'] or hashlib.sha256(' '.join(moves).encode()).hexdigest()!=meta['sequence_sha256']:
48 raise ValueError('source game identity')
49 return boards
50
51def books():
52 protected,_=protection()
53 path=ROOT/'opening-inventory.sqlite'
54 if path.exists():raise ValueError('opening inventory exists; do not overwrite')
55 db=sqlite3.connect(path)
56 db.executescript('''PRAGMA journal_mode=DELETE; PRAGMA synchronous=NORMAL;
57 CREATE TABLE positions(k BLOB PRIMARY KEY,fen TEXT,protected INTEGER) WITHOUT ROWID;
58 CREATE TABLE provenance(k BLOB,book TEXT,first_line INTEGER,first_ply INTEGER,n INTEGER,endpoints INTEGER,
59 PRIMARY KEY(k,book)) WITHOUT ROWID;
60 CREATE TABLE edges(k BLOB,move TEXT,book TEXT,n INTEGER,PRIMARY KEY(k,move,book)) WITHOUT ROWID;''')
61 counts={}
62 for name in BOOKS:
63 stats=collections.Counter();start=time.monotonic()
64 with zipfile.ZipFile(ROOT/(name+'.zip')) as z,io.TextIOWrapper(z.open(name),encoding='utf-8') as f:
65 while (game:=chess.pgn.read_game(f)) is not None:
66 stats['lines']+=1;line=stats['lines'];board=game.board();pending=[]
67 moves=list(game.mainline_moves())
68 if game.errors or type(board)!=c.chess.Board or board.chess960 or not board.is_valid():
69 stats['rejected_lines']+=1;continue
70 valid=True
71 for ply,move in enumerate(moves):
72 if board.is_game_over(claim_draw=False) or move not in board.legal_moves:valid=False;break
73 pending.append((c.position_key(board),board.fen(en_passant='fen'),ply,move.uci(),0))
74 board.push(move)
75 if not valid:stats['rejected_lines']+=1;continue
76 pending.append((c.position_key(board),board.fen(en_passant='fen'),len(moves),None,1))
77 for key,fen,ply,move,endpoint in pending:
78 if not db.execute('SELECT 1 FROM positions WHERE k=?',(key,)).fetchone():
79 db.execute('INSERT INTO positions VALUES(?,?,?)',(key,fen,int(is_protected(protected,key))))
80 db.execute('INSERT INTO provenance VALUES(?,?,?,?,1,?) ON CONFLICT(k,book) DO UPDATE SET n=n+1,endpoints=endpoints+excluded.endpoints',
81 (key,name,line,ply,endpoint))
82 if move:db.execute('INSERT INTO edges VALUES(?,?,?,1) ON CONFLICT(k,move,book) DO UPDATE SET n=n+1',(key,move,name))
83 stats['legal_lines']+=1;stats['decision_occurrences']+=len(moves)
84 if line%5000==0:
85 db.commit();guard(32_000_000)
86 print(json.dumps(dict(book=name,lines=line,elapsed=time.monotonic()-start)),flush=True)
87 db.commit()
88 stats['unique_positions_including_endpoints']=db.execute('SELECT COUNT(*) FROM provenance WHERE book=?',(name,)).fetchone()[0]
89 stats['unique_endpoints']=db.execute('SELECT COUNT(*) FROM provenance WHERE book=? AND endpoints>0',(name,)).fetchone()[0]
90 stats['unprotected_positions_including_endpoints']=db.execute('SELECT COUNT(*) FROM provenance q JOIN positions p USING(k) WHERE q.book=? AND p.protected=0',(name,)).fetchone()[0]
91 counts[name]=dict(stats)
92 result=dict(sources=counts,unique_positions=db.execute('SELECT COUNT(*) FROM positions').fetchone()[0],
93 protected_unique_positions=db.execute('SELECT COUNT(*) FROM positions WHERE protected=1').fetchone()[0],
94 unique_decision_positions=db.execute('SELECT COUNT(DISTINCT k) FROM edges').fetchone()[0],
95 unprotected_unique_decision_positions=db.execute('SELECT COUNT(DISTINCT e.k) FROM edges e JOIN positions p USING(k) WHERE p.protected=0').fetchone()[0],
96 label_kind='opening_supported candidates, not verified optimal moves',
97 independent_human_frequency='not measured by book occurrence counts',training_records_published=0)
98 db.close();result['sqlite_bytes']=path.stat().st_size;save('opening-inventory.json',result);print(json.dumps(result),flush=True)
99
100def family(board):
101 sides=[]
102 for color in (True,False):
103 sides.append('K'+''.join(p*len(board.pieces(t,color)) for t,p in [(5,'Q'),(4,'R'),(3,'B'),(2,'N'),(1,'P')]))
104 return chess.syzygy.normalize_tablename('v'.join(sides))
105
106def raw_probe(tb,board,children=False,full_history=False):
107 c.check_board(board)
108 if board.castling_rights or len(board.piece_map())>5:raise ValueError('unsupported tablebase board')
109 if board.is_game_over(claim_draw=False):raise ValueError('terminal has no decision')
110 result=dict(fen=board.fen(en_passant='fen'),halfmove_clock=board.halfmove_clock,
111 raw_wdl=tb.probe_wdl(board),raw_dtz=tb.probe_dtz(board),
112 repetition_status='known_full_game_history' if full_history else 'unknown',
113 label_scope='raw Syzygy zero-counter semantics; not actual-clock root move labels')
114 if children:
115 out=[]
116 for move in board.legal_moves:
117 child=board.copy(stack=True);zero=child.is_zeroing(move);child.push(move)
118 out.append(dict(move=move.uci(),zeroing=zero,halfmove_clock=child.halfmove_clock,
119 raw_child_wdl=tb.probe_wdl(child),raw_child_dtz=tb.probe_dtz(child),
120 checkmate=child.is_checkmate(),stalemate=child.is_stalemate()))
121 result['children']=out
122 # Preserve ties without presenting them as clock-correct winning moves.
123 best=max(-r['raw_child_wdl'] for r in out)
124 result['raw_wdl_tied_moves']=[r['move'] for r in out if -r['raw_child_wdl']==best]
125 return result
126
127def endgames():
128 protected,config=protection();seen=set();rows=[];counts=collections.Counter();families=collections.Counter()
129 source_sequences=set();early_samples=[]
130 tb=chess.syzygy.open_tablebase(str(ROOT),max_fds=32)
131 start=time.monotonic()
132 for source,ref in enumerate(config['sources']):
133 root=Path(ref['root']);m=json.loads((root/'manifest.json').read_text());n=0
134 shards=[s for s in m['shards'] if s['split']=='train']
135 shards.sort(key=lambda s:hashlib.sha256(('curriculum-v1:'+','.join(sorted(s['files']))).encode()).digest())
136 for shard in shards:
137 tokens,offsets,metas=_read_shard(root,shard)
138 for a,b,meta in zip(offsets,offsets[1:],metas):
139 if n>=2000 or len(rows)>=20000 or time.monotonic()-start>1200:break
140 n+=1;counts['source'+str(source)+'_games_scanned']+=1
141 if any(protected.execute('SELECT 1 FROM protected_games WHERE k=?',(x,)).fetchone() for x in aliases(meta)):
142 counts['heldout_games']+=1;continue
143 try:boards=replay(tokens[a:b],meta)
144 except ValueError:counts['invalid_or_post_terminal_games']+=1;continue
145 if meta['sequence_sha256'] in source_sequences:counts['duplicate_games']+=1;continue
146 source_sequences.add(meta['sequence_sha256'])
147 early=c.chess.Board()
148 for j in range(a+1,min(b-1,a+1+16*3),3):
149 move=c.decode(list(tokens[j:j+3]));key=c.position_key(early)
150 early_samples.append([key.hex(),meta['sequence_sha256'],source,move.uci()])
151 early.push(move)
152 for board,ply,move in boards:
153 if len(rows)>=20000:break
154 counts['endgame_occurrences']+=1;key=c.position_key(board)
155 if is_protected(protected,key):counts['protected_positions']+=1;continue
156 if key in seen:counts['duplicate_positions']+=1;continue
157 if board.castling_rights:counts['unsupported_castling']+=1;continue
158 seen.add(key);fam=family(board);families[fam]+=1
159 probe=raw_probe(tb,board,children=len(rows)<250,full_history=True)
160 probe.update(position_key=key.hex(),source_kind='human_main' if source==0 else 'human_elite',
161 source_sequence_sha256=meta['sequence_sha256'],game_aliases=aliases(meta),ply=ply,
162 actual_move=move,material_family=fam,history_uci=[m.uci() for m in c.genuine_history(board)],
163 can_claim_fifty_moves=board.can_claim_fifty_moves(),can_claim_threefold=board.can_claim_threefold_repetition())
164 rows.append(probe);counts['raw_wdl_'+str(probe['raw_wdl'])]+=1
165 counts['zero_halfmove' if board.halfmove_clock==0 else 'nonzero_halfmove']+=1
166 if n>=2000 or len(rows)>=20000 or time.monotonic()-start>1200:break
167 print(json.dumps(dict(source=source,games=n,unique=len(rows),elapsed=time.monotonic()-start)),flush=True)
168 guard(32_000_000)
169 if n>=2000 or len(rows)>=20000 or time.monotonic()-start>1200:break
170 if len(rows)>=20000 or time.monotonic()-start>1200:break
171 guard(32_000_000)
172 p=ROOT/'endgame-candidates.jsonl'
173 with p.open('x') as f:
174 for row in rows:f.write(json.dumps(row,separators=(',',':'))+'\n')
175 result=dict(counts=dict(counts),unique_unprotected_candidates=len(rows),material_families=dict(families.most_common()),
176 candidate_file_bytes=p.stat().st_size,candidate_sha256=sha(p),elapsed_seconds=time.monotonic()-start,
177 source_game_cap_per_source=2000,actual_clock_policy_verified=False,training_records_published=0,
178 limitations=['bounded deterministic shard sample, not population frequency',
179 'raw WDL/DTZ and child ties are not yet actual-clock exact policy labels'])
180 save('human-opening-sample.json',dict(games=len(source_sequences),rows=early_samples))
181 save('endgame-inventory.json',result);print(json.dumps(result),flush=True);tb.close()
182
183def support():
184 sample=json.loads((ROOT/'human-opening-sample.json').read_text())
185 opening=sqlite3.connect(ROOT/'opening-inventory.sqlite')
186 opening.execute('CREATE TABLE IF NOT EXISTS human_support(k BLOB,sequence TEXT,source INTEGER,move TEXT,PRIMARY KEY(k,sequence)) WITHOUT ROWID')
187 for k,seq,src,move in sample['rows']:
188 key=bytes.fromhex(k)
189 if opening.execute('SELECT 1 FROM positions WHERE k=? AND protected=0',(key,)).fetchone():
190 opening.execute('INSERT OR IGNORE INTO human_support VALUES(?,?,?,?)',(key,seq,src,move))
191 opening.commit()
192 supported=list(opening.execute('SELECT hex(k),COUNT(*) FROM human_support GROUP BY k HAVING COUNT(*)>=3 ORDER BY COUNT(*) DESC,k'))
193 save('opening-human-support.json',dict(sample_games=sample['games'],positions_with_at_least_three_games=len(supported),
194 positions_with_any_game=opening.execute('SELECT COUNT(DISTINCT k) FROM human_support').fetchone()[0],
195 supported_positions=[dict(position_key=k.lower(),distinct_games=n) for k,n in supported],
196 scope='first 16 plies of bounded existing-game sample; unprotected opening positions only',optimal_move_verified=False))
197 opening.close()
198
199def children():
200 """Complete raw child inventory without claiming rule-aware move policy."""
201 inventory=json.loads((ROOT/'endgame-inventory.json').read_text())
202 path=ROOT/'endgame-candidates.jsonl'
203 if sha(path)!=inventory['candidate_sha256']:raise ValueError('candidate identity changed')
204 temp=ROOT/'endgame-candidates.enriched.tmp';counts=collections.Counter()
205 tb=chess.syzygy.open_tablebase(str(ROOT),max_fds=32)
206 guard(100_000_000)
207 with path.open() as src,temp.open('x') as out:
208 for n,line in enumerate(src,1):
209 r=json.loads(line)
210 if 'children' not in r:
211 probe=raw_probe(tb,c.chess.Board(r['fen']),children=True)
212 r['children']=probe['children'];r['raw_wdl_tied_moves']=probe['raw_wdl_tied_moves']
213 counts['positions_with_at_most_two_raw_wdl_tied_moves']+=len(r['raw_wdl_tied_moves'])<=2
214 counts['positions_with_promotion_move']+=any(len(x['move'])==5 for x in r['children'])
215 counts['positions_with_stalemating_move']+=any(x['stalemate'] for x in r['children'])
216 out.write(json.dumps(r,separators=(',',':'))+'\n')
217 if n%1000==0:
218 out.flush();guard(10_000_000)
219 print(json.dumps(dict(child_positions=n)),flush=True)
220 tb.close();temp.replace(path)
221 inventory.update(candidate_file_bytes=path.stat().st_size,candidate_sha256=sha(path),
222 raw_child_inventory=dict(counts),all_candidate_children_probed=True)
223 save('endgame-inventory.json',inventory)
224
225if __name__=='__main__':
226 p=argparse.ArgumentParser();p.add_argument('phase',choices=['books','endgames','support','children']);args=p.parse_args();globals()[args.phase]()
227