diff --git a/graphify/skill-agents.md b/graphify/skill-agents.md index 190827d9a..e679e6909 100644 --- a/graphify/skill-agents.md +++ b/graphify/skill-agents.md @@ -348,10 +348,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -614,10 +615,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-aider.md b/graphify/skill-aider.md index 4996beb78..4a1a03456 100644 --- a/graphify/skill-aider.md +++ b/graphify/skill-aider.md @@ -346,10 +346,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('.graphify_semantic.json').write_text(json.dumps(merged, indent=2)) +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path(_tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f .graphify_cached.json .graphify_uncached.txt .graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -718,9 +719,13 @@ cost_path.write_text(json.dumps(cost, indent=2)) print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.graphify_labels.json']: + Path(_tmp).unlink(missing_ok=True) +for _chunk in Path('.').glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) +Path('graphify-out/.needs_update').unlink(missing_ok=True) " -rm -f .graphify_detect.json .graphify_extract.json .graphify_ast.json .graphify_semantic.json .graphify_analysis.json .graphify_labels.json; find . -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Tell the user (omit the obsidian line unless --obsidian was given): @@ -865,11 +870,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json .graphify_old.json` -Clean up after: `rm -f .graphify_old.json` --- diff --git a/graphify/skill-amp.md b/graphify/skill-amp.md index 190827d9a..e679e6909 100644 --- a/graphify/skill-amp.md +++ b/graphify/skill-amp.md @@ -348,10 +348,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -614,10 +615,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-claw.md b/graphify/skill-claw.md index abd2811d2..c28cb3d72 100644 --- a/graphify/skill-claw.md +++ b/graphify/skill-claw.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-codex.md b/graphify/skill-codex.md index af3f723c7..4b034fe54 100644 --- a/graphify/skill-codex.md +++ b/graphify/skill-codex.md @@ -348,10 +348,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -614,10 +615,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-copilot.md b/graphify/skill-copilot.md index abd2811d2..c28cb3d72 100644 --- a/graphify/skill-copilot.md +++ b/graphify/skill-copilot.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-devin.md b/graphify/skill-devin.md index f9be846cb..1a294bae0 100644 --- a/graphify/skill-devin.md +++ b/graphify/skill-devin.md @@ -409,10 +409,11 @@ merged = { } merged = sanitize_semantic_fragment(merged) Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2)) +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -836,9 +837,13 @@ cost_path.write_text(json.dumps(cost, indent=2)) print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.graphify_labels.json', '.graphify_incremental.json', '.graphify_transcripts.json', '.graphify_old.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json graphify-out/.graphify_labels.json graphify-out/.graphify_incremental.json graphify-out/.graphify_transcripts.json graphify-out/.graphify_old.json; find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Tell the user (omit the obsidian line unless --obsidian was given; omit the wiki line unless --wiki was given): @@ -1001,11 +1006,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skill-droid.md b/graphify/skill-droid.md index fd148d485..fa8df9c4e 100644 --- a/graphify/skill-droid.md +++ b/graphify/skill-droid.md @@ -348,10 +348,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -614,10 +615,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-kilo.md b/graphify/skill-kilo.md index 3e70b050a..754e46582 100644 --- a/graphify/skill-kilo.md +++ b/graphify/skill-kilo.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-kiro.md b/graphify/skill-kiro.md index abd2811d2..c28cb3d72 100644 --- a/graphify/skill-kiro.md +++ b/graphify/skill-kiro.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-opencode.md b/graphify/skill-opencode.md index 91ced6067..dbb21ace3 100644 --- a/graphify/skill-opencode.md +++ b/graphify/skill-opencode.md @@ -343,10 +343,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -609,10 +610,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-pi.md b/graphify/skill-pi.md index abd2811d2..c28cb3d72 100644 --- a/graphify/skill-pi.md +++ b/graphify/skill-pi.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-trae.md b/graphify/skill-trae.md index 050667bc2..286d96c12 100644 --- a/graphify/skill-trae.md +++ b/graphify/skill-trae.md @@ -349,10 +349,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -615,10 +616,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-vscode.md b/graphify/skill-vscode.md index 20c7c0835..32fe5137e 100644 --- a/graphify/skill-vscode.md +++ b/graphify/skill-vscode.md @@ -347,10 +347,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -613,10 +614,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill-windows.md b/graphify/skill-windows.md index d631821ec..273023aae 100644 --- a/graphify/skill-windows.md +++ b/graphify/skill-windows.md @@ -373,10 +373,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding="utf-8") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached["nodes"])} from cache, {len(new.get("nodes",[]))} new)') '@ | & (Get-Content graphify-out\.graphify_python) - ``` -Clean up temp files: `Remove-Item -Force -ErrorAction SilentlyContinue graphify-out\.graphify_cached.json, graphify-out\.graphify_uncached.txt, graphify-out\.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -639,10 +640,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding="u print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost["total_input_tokens"]:,} input, {cost["total_output_tokens"]:,} output ({len(cost["runs"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) '@ | & (Get-Content graphify-out\.graphify_python) - -Remove-Item -Force -ErrorAction SilentlyContinue graphify-out\.graphify_detect.json, graphify-out\.graphify_extract.json, graphify-out\.graphify_ast.json, graphify-out\.graphify_semantic.json, graphify-out\.graphify_analysis.json -Get-ChildItem graphify-out -Filter '.graphify_chunk_*.json' -File -ErrorAction SilentlyContinue | Remove-Item -Force -Remove-Item -Force -ErrorAction SilentlyContinue graphify-out\.needs_update ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skill.md b/graphify/skill.md index abd2811d2..c28cb3d72 100644 --- a/graphify/skill.md +++ b/graphify/skill.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/graphify/skills/agents/references/update.md b/graphify/skills/agents/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/agents/references/update.md +++ b/graphify/skills/agents/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/amp/references/update.md b/graphify/skills/amp/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/amp/references/update.md +++ b/graphify/skills/amp/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/claude/references/update.md b/graphify/skills/claude/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/claude/references/update.md +++ b/graphify/skills/claude/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/claw/references/update.md b/graphify/skills/claw/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/claw/references/update.md +++ b/graphify/skills/claw/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/codex/references/update.md b/graphify/skills/codex/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/codex/references/update.md +++ b/graphify/skills/codex/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/copilot/references/update.md b/graphify/skills/copilot/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/copilot/references/update.md +++ b/graphify/skills/copilot/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/droid/references/update.md b/graphify/skills/droid/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/droid/references/update.md +++ b/graphify/skills/droid/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/kilo/references/update.md b/graphify/skills/kilo/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/kilo/references/update.md +++ b/graphify/skills/kilo/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/kiro/references/update.md b/graphify/skills/kiro/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/kiro/references/update.md +++ b/graphify/skills/kiro/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/opencode/references/update.md b/graphify/skills/opencode/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/opencode/references/update.md +++ b/graphify/skills/opencode/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/pi/references/update.md b/graphify/skills/pi/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/pi/references/update.md +++ b/graphify/skills/pi/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/trae/references/update.md b/graphify/skills/trae/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/trae/references/update.md +++ b/graphify/skills/trae/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/vscode/references/update.md b/graphify/skills/vscode/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/vscode/references/update.md +++ b/graphify/skills/vscode/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/graphify/skills/windows/references/update.md b/graphify/skills/windows/references/update.md index 3632fd412..ab614fd99 100644 --- a/graphify/skills/windows/references/update.md +++ b/graphify/skills/windows/references/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tests/test_skill_cleanup_is_shell_free.py b/tests/test_skill_cleanup_is_shell_free.py new file mode 100644 index 000000000..0b5b0685f --- /dev/null +++ b/tests/test_skill_cleanup_is_shell_free.py @@ -0,0 +1,133 @@ +"""The runbook's temp-file cleanup must not depend on a shell. + +Cleanup was the only part of the pipeline that shelled out, with `rm -f` and +`find ... -delete`. On a host that gates the agent's shell, destructive verbs are +exactly what the policy withholds, so both calls were denied, the pipeline had no +fallback, and the intermediates stayed on disk (#2790). That is not just clutter: +Part C and Step B3 read `.graphify_chunk_*.json` and `.graphify_semantic_new.json` +unconditionally, so a stale chunk from a previous run can be merged into the next +`--update`. + +It is the third reported cause of one symptom -- #1172 was the fish/zsh no-match +glob, #464 the Codex/Windows leftovers -- and unlike those, retrying or switching +shell does not help, because the cause is a permission policy. + +These tests assert the property that kills the whole class: no shipped skill asks +a shell to delete anything, and the Python that replaced it actually removes the +files it names. +""" +import re +import subprocess +import sys +from pathlib import Path + +import pytest + +SKILLS_DIR = Path(__file__).resolve().parent.parent / "graphify" +SKILL_FILES = sorted(SKILLS_DIR.glob("skill*.md")) +REFERENCE_FILES = sorted((SKILLS_DIR / "skills").rglob("*.md")) + +# Shell verbs that delete. `cp` and `mkdir` are deliberately absent: they are not +# destructive, so they are not what a permission policy withholds, and #2790 is +# specifically about the delete step. +_DELETE_VERBS = ( + re.compile(r"(? list[str]: + return [ + line.strip() + for line in text.splitlines() + for pat in _DELETE_VERBS + if pat.search(line) + ] + + +@pytest.mark.parametrize("path", SKILL_FILES, ids=lambda p: p.name) +def test_no_shipped_skill_deletes_through_a_shell(path): + assert not _offending(path.read_text(encoding="utf-8")), ( + f"{path.name} deletes through a shell verb; a permission-gated host will " + f"deny it: {_offending(path.read_text(encoding='utf-8'))}" + ) + + +@pytest.mark.parametrize("path", REFERENCE_FILES, ids=lambda p: f"{p.parent.parent.name}/{p.name}") +def test_no_shipped_reference_deletes_through_a_shell(path): + assert not _offending(path.read_text(encoding="utf-8")), ( + f"{path} deletes through a shell verb" + ) + + +def test_every_skill_still_cleans_the_chunk_files(): + """The guard above passes trivially if cleanup were simply deleted. Every + skill that dispatches chunks must still remove them, in Python.""" + checked = 0 + for path in SKILL_FILES: + text = path.read_text(encoding="utf-8") + if ".graphify_chunk_" not in text: + continue + checked += 1 + assert re.search(r"for _chunk in .*glob\('\.graphify_chunk_\*\.json'\):", text), ( + f"{path.name} dispatches chunks but never cleans them up" + ) + assert "_chunk.unlink(missing_ok=True)" in text, path.name + assert checked >= 10, f"expected most skills to dispatch chunks, saw {checked}" + + +# --------------------------------------------------------------------------- +# The replacement actually works +# --------------------------------------------------------------------------- + +_CLEANUP = """ +from pathlib import Path +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) +""" + + +def test_the_cleanup_block_shipped_in_skill_md_is_the_one_under_test(): + """Pin the snippet below to what skill.md actually ships, so this file cannot + drift into testing something the runbook no longer says.""" + text = (SKILLS_DIR / "skill.md").read_text(encoding="utf-8") + for line in _CLEANUP.strip().splitlines()[1:]: # skip the import + assert line in text, f"skill.md no longer contains: {line!r}" + + +def _seed(root: Path) -> None: + out = root / "graphify-out" + out.mkdir(parents=True) + for name in (".graphify_detect.json", ".graphify_extract.json", ".graphify_ast.json", + ".graphify_semantic.json", ".graphify_analysis.json", ".needs_update", + ".graphify_chunk_01.json", ".graphify_chunk_02.json"): + (out / name).write_text("{}", encoding="utf-8") + (out / "graph.json").write_text('{"nodes":[],"links":[]}', encoding="utf-8") + (out / "GRAPH_REPORT.md").write_text("# report\n", encoding="utf-8") + + +def test_cleanup_removes_every_intermediate_and_keeps_the_outputs(tmp_path): + _seed(tmp_path) + subprocess.run([sys.executable, "-c", _CLEANUP], cwd=tmp_path, check=True) + + left = sorted(p.name for p in (tmp_path / "graphify-out").iterdir()) + assert left == ["GRAPH_REPORT.md", "graph.json"], left + + +def test_cleanup_is_idempotent_when_nothing_is_there(tmp_path): + """`rm -f` tolerated missing files; `unlink(missing_ok=True)` must too, or a + --no-viz / cluster-only run that never wrote a chunk would crash Step 9.""" + (tmp_path / "graphify-out").mkdir() + subprocess.run([sys.executable, "-c", _CLEANUP], cwd=tmp_path, check=True) + subprocess.run([sys.executable, "-c", _CLEANUP], cwd=tmp_path, check=True) + + +def test_cleanup_does_not_need_the_output_dir_to_exist(tmp_path): + """glob() on a missing directory yields nothing rather than raising.""" + subprocess.run([sys.executable, "-c", _CLEANUP], cwd=tmp_path, check=True) diff --git a/tests/test_skillgen.py b/tests/test_skillgen.py index cf116869f..a640aa265 100644 --- a/tests/test_skillgen.py +++ b/tests/test_skillgen.py @@ -403,9 +403,15 @@ def test_powershell_hosts_carry_no_bash_only_shell(): assert "'@ | & (Get-Content graphify-out\\.graphify_python) -" in core, ( f"[{key}] missing the here-string stdin python invocation" ) - # Cleanup went through Remove-Item / Get-ChildItem, not rm/find. - assert "Remove-Item -Force -ErrorAction SilentlyContinue" in core - assert "Get-ChildItem graphify-out -Filter '.graphify_chunk_*.json'" in core + # Cleanup no longer goes through a shell at all (#2790): it is folded + # into the tail of the Python program each block already runs, so there + # is nothing left for the translator to turn into Remove-Item, and a + # host that gates destructive verbs has nothing to deny. + assert "Remove-Item" not in core, f"[{key}] cleanup still uses a shell verb" + assert "Get-ChildItem" not in core, f"[{key}] cleanup still uses a shell verb" + assert "for _chunk in _out.glob('.graphify_chunk_*.json'):" in core, ( + f"[{key}] lost the Python chunk cleanup" + ) def test_windows_and_posix_cores_have_step_and_2490_parity(): diff --git a/tools/skillgen/expected/graphify__skill-agents.md b/tools/skillgen/expected/graphify__skill-agents.md index 190827d9a..e679e6909 100644 --- a/tools/skillgen/expected/graphify__skill-agents.md +++ b/tools/skillgen/expected/graphify__skill-agents.md @@ -348,10 +348,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -614,10 +615,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-aider.md b/tools/skillgen/expected/graphify__skill-aider.md index 4996beb78..4a1a03456 100644 --- a/tools/skillgen/expected/graphify__skill-aider.md +++ b/tools/skillgen/expected/graphify__skill-aider.md @@ -346,10 +346,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('.graphify_semantic.json').write_text(json.dumps(merged, indent=2)) +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path(_tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f .graphify_cached.json .graphify_uncached.txt .graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -718,9 +719,13 @@ cost_path.write_text(json.dumps(cost, indent=2)) print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.graphify_labels.json']: + Path(_tmp).unlink(missing_ok=True) +for _chunk in Path('.').glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) +Path('graphify-out/.needs_update').unlink(missing_ok=True) " -rm -f .graphify_detect.json .graphify_extract.json .graphify_ast.json .graphify_semantic.json .graphify_analysis.json .graphify_labels.json; find . -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Tell the user (omit the obsidian line unless --obsidian was given): @@ -865,11 +870,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json .graphify_old.json` -Clean up after: `rm -f .graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skill-amp.md b/tools/skillgen/expected/graphify__skill-amp.md index 190827d9a..e679e6909 100644 --- a/tools/skillgen/expected/graphify__skill-amp.md +++ b/tools/skillgen/expected/graphify__skill-amp.md @@ -348,10 +348,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -614,10 +615,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-claw.md b/tools/skillgen/expected/graphify__skill-claw.md index abd2811d2..c28cb3d72 100644 --- a/tools/skillgen/expected/graphify__skill-claw.md +++ b/tools/skillgen/expected/graphify__skill-claw.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-codex.md b/tools/skillgen/expected/graphify__skill-codex.md index af3f723c7..4b034fe54 100644 --- a/tools/skillgen/expected/graphify__skill-codex.md +++ b/tools/skillgen/expected/graphify__skill-codex.md @@ -348,10 +348,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -614,10 +615,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-copilot.md b/tools/skillgen/expected/graphify__skill-copilot.md index abd2811d2..c28cb3d72 100644 --- a/tools/skillgen/expected/graphify__skill-copilot.md +++ b/tools/skillgen/expected/graphify__skill-copilot.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-devin.md b/tools/skillgen/expected/graphify__skill-devin.md index f9be846cb..1a294bae0 100644 --- a/tools/skillgen/expected/graphify__skill-devin.md +++ b/tools/skillgen/expected/graphify__skill-devin.md @@ -409,10 +409,11 @@ merged = { } merged = sanitize_semantic_fragment(merged) Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2)) +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -836,9 +837,13 @@ cost_path.write_text(json.dumps(cost, indent=2)) print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.graphify_labels.json', '.graphify_incremental.json', '.graphify_transcripts.json', '.graphify_old.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json graphify-out/.graphify_labels.json graphify-out/.graphify_incremental.json graphify-out/.graphify_transcripts.json graphify-out/.graphify_old.json; find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Tell the user (omit the obsidian line unless --obsidian was given; omit the wiki line unless --wiki was given): @@ -1001,11 +1006,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skill-droid.md b/tools/skillgen/expected/graphify__skill-droid.md index fd148d485..fa8df9c4e 100644 --- a/tools/skillgen/expected/graphify__skill-droid.md +++ b/tools/skillgen/expected/graphify__skill-droid.md @@ -348,10 +348,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -614,10 +615,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-kilo.md b/tools/skillgen/expected/graphify__skill-kilo.md index 3e70b050a..754e46582 100644 --- a/tools/skillgen/expected/graphify__skill-kilo.md +++ b/tools/skillgen/expected/graphify__skill-kilo.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-kiro.md b/tools/skillgen/expected/graphify__skill-kiro.md index abd2811d2..c28cb3d72 100644 --- a/tools/skillgen/expected/graphify__skill-kiro.md +++ b/tools/skillgen/expected/graphify__skill-kiro.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-opencode.md b/tools/skillgen/expected/graphify__skill-opencode.md index 91ced6067..dbb21ace3 100644 --- a/tools/skillgen/expected/graphify__skill-opencode.md +++ b/tools/skillgen/expected/graphify__skill-opencode.md @@ -343,10 +343,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -609,10 +610,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-pi.md b/tools/skillgen/expected/graphify__skill-pi.md index abd2811d2..c28cb3d72 100644 --- a/tools/skillgen/expected/graphify__skill-pi.md +++ b/tools/skillgen/expected/graphify__skill-pi.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-trae.md b/tools/skillgen/expected/graphify__skill-trae.md index 050667bc2..286d96c12 100644 --- a/tools/skillgen/expected/graphify__skill-trae.md +++ b/tools/skillgen/expected/graphify__skill-trae.md @@ -349,10 +349,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -615,10 +616,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-vscode.md b/tools/skillgen/expected/graphify__skill-vscode.md index 20c7c0835..32fe5137e 100644 --- a/tools/skillgen/expected/graphify__skill-vscode.md +++ b/tools/skillgen/expected/graphify__skill-vscode.md @@ -347,10 +347,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -613,10 +614,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill-windows.md b/tools/skillgen/expected/graphify__skill-windows.md index d631821ec..273023aae 100644 --- a/tools/skillgen/expected/graphify__skill-windows.md +++ b/tools/skillgen/expected/graphify__skill-windows.md @@ -373,10 +373,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding="utf-8") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached["nodes"])} from cache, {len(new.get("nodes",[]))} new)') '@ | & (Get-Content graphify-out\.graphify_python) - ``` -Clean up temp files: `Remove-Item -Force -ErrorAction SilentlyContinue graphify-out\.graphify_cached.json, graphify-out\.graphify_uncached.txt, graphify-out\.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -639,10 +640,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding="u print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost["total_input_tokens"]:,} input, {cost["total_output_tokens"]:,} output ({len(cost["runs"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) '@ | & (Get-Content graphify-out\.graphify_python) - -Remove-Item -Force -ErrorAction SilentlyContinue graphify-out\.graphify_detect.json, graphify-out\.graphify_extract.json, graphify-out\.graphify_ast.json, graphify-out\.graphify_semantic.json, graphify-out\.graphify_analysis.json -Get-ChildItem graphify-out -Filter '.graphify_chunk_*.json' -File -ErrorAction SilentlyContinue | Remove-Item -Force -Remove-Item -Force -ErrorAction SilentlyContinue graphify-out\.needs_update ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skill.md b/tools/skillgen/expected/graphify__skill.md index abd2811d2..c28cb3d72 100644 --- a/tools/skillgen/expected/graphify__skill.md +++ b/tools/skillgen/expected/graphify__skill.md @@ -351,10 +351,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -617,10 +618,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/expected/graphify__skills__agents__references__update.md b/tools/skillgen/expected/graphify__skills__agents__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__agents__references__update.md +++ b/tools/skillgen/expected/graphify__skills__agents__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__amp__references__update.md b/tools/skillgen/expected/graphify__skills__amp__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__amp__references__update.md +++ b/tools/skillgen/expected/graphify__skills__amp__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__claude__references__update.md b/tools/skillgen/expected/graphify__skills__claude__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__claude__references__update.md +++ b/tools/skillgen/expected/graphify__skills__claude__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__claw__references__update.md b/tools/skillgen/expected/graphify__skills__claw__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__claw__references__update.md +++ b/tools/skillgen/expected/graphify__skills__claw__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__codex__references__update.md b/tools/skillgen/expected/graphify__skills__codex__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__codex__references__update.md +++ b/tools/skillgen/expected/graphify__skills__codex__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__copilot__references__update.md b/tools/skillgen/expected/graphify__skills__copilot__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__copilot__references__update.md +++ b/tools/skillgen/expected/graphify__skills__copilot__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__droid__references__update.md b/tools/skillgen/expected/graphify__skills__droid__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__droid__references__update.md +++ b/tools/skillgen/expected/graphify__skills__droid__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__kilo__references__update.md b/tools/skillgen/expected/graphify__skills__kilo__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__kilo__references__update.md +++ b/tools/skillgen/expected/graphify__skills__kilo__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__kiro__references__update.md b/tools/skillgen/expected/graphify__skills__kiro__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__kiro__references__update.md +++ b/tools/skillgen/expected/graphify__skills__kiro__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__opencode__references__update.md b/tools/skillgen/expected/graphify__skills__opencode__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__opencode__references__update.md +++ b/tools/skillgen/expected/graphify__skills__opencode__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__pi__references__update.md b/tools/skillgen/expected/graphify__skills__pi__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__pi__references__update.md +++ b/tools/skillgen/expected/graphify__skills__pi__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__trae__references__update.md b/tools/skillgen/expected/graphify__skills__trae__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__trae__references__update.md +++ b/tools/skillgen/expected/graphify__skills__trae__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__vscode__references__update.md b/tools/skillgen/expected/graphify__skills__vscode__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__vscode__references__update.md +++ b/tools/skillgen/expected/graphify__skills__vscode__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/expected/graphify__skills__windows__references__update.md b/tools/skillgen/expected/graphify__skills__windows__references__update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/expected/graphify__skills__windows__references__update.md +++ b/tools/skillgen/expected/graphify__skills__windows__references__update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/fragments/core/aider.md b/tools/skillgen/fragments/core/aider.md index 4996beb78..4a1a03456 100644 --- a/tools/skillgen/fragments/core/aider.md +++ b/tools/skillgen/fragments/core/aider.md @@ -346,10 +346,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('.graphify_semantic.json').write_text(json.dumps(merged, indent=2)) +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path(_tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f .graphify_cached.json .graphify_uncached.txt .graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -718,9 +719,13 @@ cost_path.write_text(json.dumps(cost, indent=2)) print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.graphify_labels.json']: + Path(_tmp).unlink(missing_ok=True) +for _chunk in Path('.').glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) +Path('graphify-out/.needs_update').unlink(missing_ok=True) " -rm -f .graphify_detect.json .graphify_extract.json .graphify_ast.json .graphify_semantic.json .graphify_analysis.json .graphify_labels.json; find . -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Tell the user (omit the obsidian line unless --obsidian was given): @@ -865,11 +870,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json .graphify_old.json` -Clean up after: `rm -f .graphify_old.json` --- diff --git a/tools/skillgen/fragments/core/core.md b/tools/skillgen/fragments/core/core.md index c527a1256..f5ac8a9a9 100644 --- a/tools/skillgen/fragments/core/core.md +++ b/tools/skillgen/fragments/core/core.md @@ -286,10 +286,11 @@ merged = { 'output_tokens': new.get('output_tokens', 0), } Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\") +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -552,10 +553,13 @@ cost_path.write_text(json.dumps(cost, indent=2, ensure_ascii=False), encoding=\" print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json -find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Replace INPUT_PATH with the actual path (same value used in Steps 4-5) so the manifest is relativized to the scan root. diff --git a/tools/skillgen/fragments/core/devin.md b/tools/skillgen/fragments/core/devin.md index f9be846cb..1a294bae0 100644 --- a/tools/skillgen/fragments/core/devin.md +++ b/tools/skillgen/fragments/core/devin.md @@ -409,10 +409,11 @@ merged = { } merged = sanitize_semantic_fragment(merged) Path('graphify-out/.graphify_semantic.json').write_text(json.dumps(merged, indent=2)) +for _tmp in ['.graphify_cached.json', '.graphify_uncached.txt', '.graphify_semantic_new.json']: + Path('graphify-out', _tmp).unlink(missing_ok=True) print(f'Extraction complete - {len(deduped)} nodes, {len(all_edges)} edges ({len(cached[\"nodes\"])} from cache, {len(new.get(\"nodes\",[]))} new)') " ``` -Clean up temp files: `rm -f graphify-out/.graphify_cached.json graphify-out/.graphify_uncached.txt graphify-out/.graphify_semantic_new.json` #### Part C - Merge AST + semantic into final extraction @@ -836,9 +837,13 @@ cost_path.write_text(json.dumps(cost, indent=2)) print(f'This run: {input_tok:,} input tokens, {output_tok:,} output tokens') print(f'All time: {cost[\"total_input_tokens\"]:,} input, {cost[\"total_output_tokens\"]:,} output ({len(cost[\"runs\"])} runs)') + +_out = Path('graphify-out') +for _tmp in ['.graphify_detect.json', '.graphify_extract.json', '.graphify_ast.json', '.graphify_semantic.json', '.graphify_analysis.json', '.graphify_labels.json', '.graphify_incremental.json', '.graphify_transcripts.json', '.graphify_old.json', '.needs_update']: + (_out / _tmp).unlink(missing_ok=True) +for _chunk in _out.glob('.graphify_chunk_*.json'): + _chunk.unlink(missing_ok=True) " -rm -f graphify-out/.graphify_detect.json graphify-out/.graphify_extract.json graphify-out/.graphify_ast.json graphify-out/.graphify_semantic.json graphify-out/.graphify_analysis.json graphify-out/.graphify_labels.json graphify-out/.graphify_incremental.json graphify-out/.graphify_transcripts.json graphify-out/.graphify_old.json; find graphify-out -maxdepth 1 -name '.graphify_chunk_*.json' -delete 2>/dev/null -rm -f graphify-out/.needs_update 2>/dev/null || true ``` Tell the user (omit the obsidian line unless --obsidian was given; omit the wiki line unless --wiki was given): @@ -1001,11 +1006,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/fragments/references/shared/update.md b/tools/skillgen/fragments/references/shared/update.md index 3632fd412..ab614fd99 100644 --- a/tools/skillgen/fragments/references/shared/update.md +++ b/tools/skillgen/fragments/references/shared/update.md @@ -191,11 +191,11 @@ if old_data: print('New nodes:', ', '.join(n['label'] for n in diff['new_nodes'][:5])) if diff['new_edges']: print('New edges:', len(diff['new_edges'])) +Path('graphify-out/.graphify_old.json').unlink(missing_ok=True) " ``` Before the merge step, save the old graph: `cp graphify-out/graph.json graphify-out/.graphify_old.json` -Clean up after: `rm -f graphify-out/.graphify_old.json` --- diff --git a/tools/skillgen/gen.py b/tools/skillgen/gen.py index 09e19ede0..5407ed1eb 100644 --- a/tools/skillgen/gen.py +++ b/tools/skillgen/gen.py @@ -919,6 +919,42 @@ def _is_chunk_cleanup_line(line: str) -> bool: return ".graphify_chunk_*.json" in line or ("find " in line and "-name '.graphify_chunk_" in line) +def _is_shell_free_cleanup_line(line: str) -> bool: + """Whether a line belongs to the shell-free rewrite of the temp-file cleanup. + + The cleanup steps were the only part of the runbook that shelled out, using + ``rm -f`` and ``find ... -delete``. Hosts that gate the agent's shell deny + destructive verbs as a matter of policy, so the cleanup silently did nothing + and a stale ``.graphify_chunk_*.json`` survived into the next ``--update``, + where Part C reads it unconditionally (graphify #2790). That is the third + reported cause of the same symptom, after the fish/zsh glob (#1172, see + :func:`_is_chunk_cleanup_line`) and the Codex/Windows leftovers (#464). + + The fix folds the cleanup into the tail of the Python program each block + already runs, so no shell verb is involved on any host and nothing new is + spawned. That deliberately adds no fence, no ``$(cat ...) -c`` invocation and + no import — only statements that name graphify's own intermediates — which is + what keeps this predicate narrow enough to be worth having. + + Both sides are matched so the multiset diff classifies the change: the removed + ``rm -f`` (bare command or inside a prose code span) and the added Python. + """ + s = line.strip() + if "rm -f " in s and (".graphify_" in s or ".needs_update" in s): + return True + if s == "_out = Path('graphify-out')" or s == "_chunk.unlink(missing_ok=True)": + return True + if s.startswith("for _tmp in [") and s.endswith("]:"): + return True + if s.startswith("for _chunk in ") and s.endswith("glob('.graphify_chunk_*.json'):"): + return True + if s.endswith(".unlink(missing_ok=True)") and ( + "_tmp" in s or ".graphify_" in s or ".needs_update" in s + ): + return True + return False + + def _is_trigger_line(line: str) -> bool: """Whether a line is the non-spec ``trigger:`` frontmatter field (#1180). @@ -1150,6 +1186,7 @@ def _is_community_label_export_fix_line(line: str) -> bool: _is_enum_line, _is_frontmatter_description_line, _is_chunk_cleanup_line, + _is_shell_free_cleanup_line, _is_directed_fix_line, _is_content_scope_fix_line, _is_cache_unlink_fix_line,