From: Thomas Walker Lynch Date: Thu, 20 Nov 2025 04:12:43 +0000 (+0000) Subject: cleanup X-Git-Url: https://git.reasoningtechnology.com/style/static/gitweb.js?a=commitdiff_plain;h=970af177a37fc694a109093c9d6db7d41c31fb59;p=Harmony.git cleanup --- diff --git a/tool/deprecated/skeleton_check b/tool/deprecated/skeleton_check deleted file mode 100755 index 7051acb..0000000 --- a/tool/deprecated/skeleton_check +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env python3 -# -*- mode: python; coding: utf-8; python-indent-offset: 2; indent-tabs-mode: nil -*- - -""" -skeleton_check — CLI front-end for skeleton_diff -""" - -import sys -from pathlib import Path -from typing import List - -from skeleton_commands import ( - work_environment, - work_structure, - work_import, - work_export, - work_suspicious, - work_addendum, - work_version, - work_usage, -) -from skeleton_diff_docs import work_help - - -def CLI() -> int: - args_list = sys.argv[1:] - - program_name = Path(sys.argv[0]).name or "skeleton_check" - - if not args_list: - work_usage(program_name) - return 1 - - # 1. Global dominating commands: usage, help, version - global_dom_commands_set = { - "usage", - "help", - "version", - } - - for token in args_list: - if token in global_dom_commands_set: - if token == "usage": - work_usage(program_name) - elif token == "help": - work_help() - elif token == "version": - work_version() - return 0 - - # 2. Commands that never require a project, and those that do - commands_no_other_set = { - "environment", - } - - commands_require_other_set = { - "structure", - "import", - "export", - "suspicious", - "addendum", - "all", - } - - all_commands_set = commands_no_other_set | commands_require_other_set - - commands_list: List[str] = [] - other_root_path: Path | None = None - project_needed_flag = False - earliest_requires_index: int | None = None - - n_args = len(args_list) - last_index = n_args - 1 - - for index, token in enumerate(args_list): - if token in all_commands_set: - # If we already saw a project-requiring command earlier, and this is - # the last token, interpret it as the project path instead of a command. - if project_needed_flag and index == last_index and earliest_requires_index is not None: - other_root_path = Path(token) - break - - # Normal command - commands_list.append(token) - if token in commands_require_other_set and earliest_requires_index is None: - earliest_requires_index = index - project_needed_flag = True - - else: - # Not a known command: may be the project path, but only if a command - # that requires a project has already been seen and this is the last arg. - if project_needed_flag and index == last_index and earliest_requires_index is not None: - other_root_path = Path(token) - break - - print(f"ERROR: unknown command '{token}'.", file=sys.stderr) - work_usage(program_name) - return 1 - - # 3. Post-parse checks - if project_needed_flag: - # We saw at least one command that requires . - if other_root_path is None: - # First project-requiring command was also the last argument: no project path left. - last_command = commands_list[-1] if commands_list else "" - print( - f"ERROR: missing after command '{last_command}'.", - file=sys.stderr, - ) - work_usage(program_name) - return 1 - - if not other_root_path.is_dir(): - print(f"ERROR: {other_root_path} is not a directory.", file=sys.stderr) - work_usage(program_name) - return 1 - - # 4. Expand 'all' into its constituent checks - expanded_commands_list: List[str] = [] - if "all" in commands_list and len(commands_list) > 1: - print("ERROR: 'all' cannot be combined with other commands.", file=sys.stderr) - work_usage(program_name) - return 1 - - for command in commands_list: - if command == "all": - expanded_commands_list.extend([ - "environment", - "structure", - "import", - "export", - "suspicious", - "addendum", - ]) - else: - expanded_commands_list.append(command) - - commands_list = expanded_commands_list - - # 5. Execute commands - other_root: Path | None = other_root_path - - for command in commands_list: - print(f"\\n--- Running: {command} ---") - if command == "environment": - work_environment() - elif command == "structure": - if other_root is None: - print("ERROR: 'structure' requires .", file=sys.stderr) - work_usage(program_name) - return 1 - work_structure(other_root) - elif command == "import": - if other_root is None: - print("ERROR: 'import' requires .", file=sys.stderr) - work_usage(program_name) - return 1 - work_import(other_root) - elif command == "export": - if other_root is None: - print("ERROR: 'export' requires .", file=sys.stderr) - work_usage(program_name) - return 1 - work_export(other_root) - elif command == "suspicious": - if other_root is None: - print("ERROR: 'suspicious' requires .", file=sys.stderr) - work_usage(program_name) - return 1 - work_suspicious(other_root) - elif command == "addendum": - if other_root is None: - print("ERROR: 'addendum' requires .", file=sys.stderr) - work_usage(program_name) - return 1 - work_addendum(other_root) - else: - # Should be unreachable because we validated commands_list. - print(f"Unknown command: {command}") - work_usage(program_name) - return 1 - - return 0 - - -if __name__ == "__main__": - sys.exit(CLI()) diff --git a/tool/deprecated/skeleton_commands.py b/tool/deprecated/skeleton_commands.py deleted file mode 100644 index 32520c0..0000000 --- a/tool/deprecated/skeleton_commands.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/env python3 -""" -skeleton_commands — user-facing command implementations for skeleton_diff -""" - -import os -import sys -from pathlib import Path -from typing import List - -from skeleton_config import HARMONY_ROOT, VERSION -from skeleton_paths import index_project -from skeleton_compare import compare_harmony_to_other - - -# ---------------------------------------------------------------------- -# environment -# ---------------------------------------------------------------------- -def work_environment() -> int: - print("=== Environment ===") - print(f"REPO_HOME = {HARMONY_ROOT}") - for key, value in sorted(os.environ.items()): - if key.startswith(("HARMONY_", "REPO_", "PATH")) or "tool" in key.lower(): - print(f"{key} = {value}") - return 0 - - -# ---------------------------------------------------------------------- -# structure -# ---------------------------------------------------------------------- -def work_structure(other_root: Path) -> int: - print("=== Structure Comparison ===") - - results = compare_harmony_to_other(other_root) - - # Only consider directories for structural reports - skeleton_dir_list = [ - rel for rel, info in results.skeleton_dict.items() - if info.path_type == "dir" - ] - other_dir_list = [ - rel for rel, info in results.other_dict.items() - if info.path_type == "dir" - ] - - skeleton_dir_set = set(skeleton_dir_list) - other_dir_set = set(other_dir_list) - - missing_dir_list = sorted( - skeleton_dir_set - other_dir_set, - key=lambda p: (len(p.parts), str(p)), - ) - - new_dir_list = sorted( - other_dir_set - skeleton_dir_set, - key=lambda p: (len(p.parts), str(p)), - ) - - if missing_dir_list: - print("Missing Harmony directories in :") - for rel_dir in missing_dir_list: - print(f" [MISSING] {rel_dir}") - print() - - if new_dir_list: - print("New directories present only in :") - for rel_dir in new_dir_list: - print(f" [NEW] {rel_dir}") - print() - - if not missing_dir_list and not new_dir_list: - print("No structural directory differences detected.") - - return 0 - - -# ---------------------------------------------------------------------- -# import / export -# ---------------------------------------------------------------------- -def work_import(other_root: Path) -> int: - print("=== Import Commands (newer → Harmony) ===") - - results = compare_harmony_to_other(other_root) - newer_list = results.newer_list - - if not newer_list: - print(" No newer files in to import.") - return 0 - - for rel_path in newer_list: - src = other_root / rel_path - dst = HARMONY_ROOT / rel_path - print(f"cp {src} {dst} # clobbers older Harmony file") - - return 0 - - -def work_export(other_root: Path) -> int: - print("=== Export Commands (Harmony → ) ===") - - results = compare_harmony_to_other(other_root) - older_list = results.older_list - - if not older_list: - print(" No stale files in to export.") - return 0 - - for rel_path in older_list: - src = HARMONY_ROOT / rel_path - dst = other_root / rel_path - print(f"cp {src} {dst} # clobbers stale file in ") - - return 0 - - -# ---------------------------------------------------------------------- -# suspicious -# ---------------------------------------------------------------------- -USER_OWNED_TOP = { - "developer", - "tester", - "release", -} -TOOL_TOP = { - "tool", - "tool_shared", -} - - -def work_suspicious(other_root: Path) -> int: - print("=== Suspicious Files (clutter outside expected zones) ===") - - results = compare_harmony_to_other(other_root) - skeleton_dict = results.skeleton_dict - other_dict = results.other_dict - - suspicious_list: List[Path] = [] - - for rel_path, other_info in other_dict.items(): - if other_info.path_type != "file": - continue - - if rel_path == Path("."): - continue - - top_component = rel_path.parts[0] - - # Skip user-owned zones - if top_component in USER_OWNED_TOP: - continue - - # Skip tool zones - if top_component in TOOL_TOP: - continue - - # If Harmony knows about this file, it is not suspicious. - if rel_path in skeleton_dict: - continue - - suspicious_list.append(rel_path) - - suspicious_list.sort(key=lambda p: (len(p.parts), str(p))) - - if suspicious_list: - for rel_path in suspicious_list: - print(f" [SUSPICIOUS] {rel_path}") - else: - print(" None found.") - - return 0 - - -# ---------------------------------------------------------------------- -# addendum -# ---------------------------------------------------------------------- -def work_addendum(other_root: Path) -> int: - print("=== Addendum: New Tools in ===") - - results = compare_harmony_to_other(other_root) - skeleton_dict = results.skeleton_dict - other_dict = results.other_dict - - addendum_list: List[Path] = [] - - for rel_path, other_info in other_dict.items(): - if other_info.path_type != "file": - continue - - if rel_path == Path("."): - continue - - parts = rel_path.parts - if not parts: - continue - - top_component = parts[0] - if top_component not in TOOL_TOP: - continue - - if rel_path not in skeleton_dict: - addendum_list.append(rel_path) - - addendum_list.sort(key=lambda p: (len(p.parts), str(p))) - - if addendum_list: - for rel_path in addendum_list: - print(f" [ADDENDUM] {rel_path}") - else: - print(" None found.") - - return 0 - - -# ---------------------------------------------------------------------- -# version / usage / help (help text lives in skeleton_diff_docs) -# ---------------------------------------------------------------------- -def work_version() -> int: - print(f"skeleton_diff version {VERSION}") - return 0 - - -def work_usage(program_name: str) -> int: - print(f"Usage: {program_name} []... []") - print() - print(" is required if any commands are specified that") - print("require a project to analyze.") - print() - print("Commands:") - print(" version Show program version (Major.Minor)") - print(" help Long-form documentation") - print(" usage This short summary") - print(" environment Show key environment variables (including $REPO_HOME)") - print(" structure Compare directory structure") - print(" import Print shell commands for pulling newer skeleton") - print(" files into Harmony") - print(" export Print shell commands for pushing Harmony skeleton") - print(" files into ") - print(' suspicious List "between" files that are not in the skeleton') - print(" addendum List tool files in that do not exist in") - print(" the Harmony skeleton (project-local additions)") - print(" all Run the full set of analyses") - print() - print("Examples:") - print(f" {program_name} usage") - print(f" {program_name} structure import ../subu") - print(f" {program_name} all ../subu") - print() - print(f"Run '{program_name} help' for detailed explanations.") - return 0 diff --git a/tool/deprecated/skeleton_compare.py b/tool/deprecated/skeleton_compare.py deleted file mode 100644 index ac76673..0000000 --- a/tool/deprecated/skeleton_compare.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 -""" -skeleton_compare — comparison logic between Harmony skeleton and -""" - -from dataclasses import dataclass -from pathlib import Path -from typing import Dict, List, Set - -from skeleton_config import HARMONY_ROOT -from skeleton_paths import NodeInfo, index_project - - -@dataclass -class ComparisonResults: - skeleton_dict: Dict[Path, NodeInfo] - other_dict: Dict[Path, NodeInfo] - missing_list: List[Path] - addendum_list: List[Path] - newer_list: List[Path] - older_list: List[Path] - - -def compare_harmony_to_other(other_root: Path) -> ComparisonResults: - """ - Build Harmony and indexes and compare them. - - - missing_list: paths present in Harmony, absent in . - - addendum_list: paths present in , absent in Harmony. - - newer_list: file paths where is newer than Harmony. - - older_list: file paths where is older than Harmony. - """ - other_root = other_root.resolve() - - skeleton_dict = index_project(HARMONY_ROOT) - other_dict = index_project(other_root) - - skeleton_paths_set: Set[Path] = set(skeleton_dict.keys()) - other_paths_set: Set[Path] = set(other_dict.keys()) - - missing_list: List[Path] = sorted( - skeleton_paths_set - other_paths_set, - key=lambda p: (len(p.parts), str(p)), - ) - - addendum_list: List[Path] = sorted( - other_paths_set - skeleton_paths_set, - key=lambda p: (len(p.parts), str(p)), - ) - - newer_list: List[Path] = [] - older_list: List[Path] = [] - - for rel_path in sorted( - skeleton_paths_set & other_paths_set, - key=lambda p: (len(p.parts), str(p)), - ): - skeleton_info = skeleton_dict[rel_path] - other_info = other_dict[rel_path] - - if skeleton_info.path_type != "file" or other_info.path_type != "file": - continue - - if other_info.mtime > skeleton_info.mtime: - newer_list.append(rel_path) - elif other_info.mtime < skeleton_info.mtime: - older_list.append(rel_path) - - return ComparisonResults( - skeleton_dict=skeleton_dict, - other_dict=other_dict, - missing_list=missing_list, - addendum_list=addendum_list, - newer_list=newer_list, - older_list=older_list, - ) diff --git a/tool/deprecated/skeleton_config.py b/tool/deprecated/skeleton_config.py deleted file mode 100644 index 1724b20..0000000 --- a/tool/deprecated/skeleton_config.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 -""" -skeleton_config — shared configuration for skeleton_diff - -Version: Major.Minor = 0.6 -Author: Thomas Walker Lynch, with Grok and Vaelorin -Date: 2025-11-18 -""" - -import os -import sys -from pathlib import Path - -MAJOR = 0 -MINOR = 6 -VERSION = f"{MAJOR}.{MINOR}" - - -def _discover_harmony_root() -> Path: - repo_home = os.getenv("REPO_HOME") - if repo_home: - root_path = Path(repo_home).resolve() - else: - # Fallback: assume current working directory is inside Harmony - root_path = Path.cwd().resolve() - if not root_path.exists(): - print("ERROR: $REPO_HOME not set or invalid. Source env_toolsmith.", file=sys.stderr) - sys.exit(1) - return root_path - - -HARMONY_ROOT = _discover_harmony_root() diff --git a/tool/deprecated/skeleton_diff_docs.py b/tool/deprecated/skeleton_diff_docs.py deleted file mode 100644 index 3db2d1e..0000000 --- a/tool/deprecated/skeleton_diff_docs.py +++ /dev/null @@ -1,298 +0,0 @@ -#!/usr/bin/env python3 -""" -skeleton_diff_docs — long-form help text for skeleton_diff -""" - -from pathlib import Path -from skeleton_config import VERSION - - -def work_help() -> int: - help_text = f""" -skeleton_diff — Harmony Skeleton Auditor -======================================== - -Version: {VERSION} - -1. Purpose -1.1 The skeleton_diff tool compares a Harmony project (the skeleton) with - another project () that was originally cloned from Harmony. -1.2 Over time, individual projects tend to evolve: - - Some improvements are made in projects but never pulled back to the - Harmony skeleton. - - Some improvements make it back into Harmony, leaving older projects - with stale copies of skeleton files. - - Extra directories and files appear in projects, some intentional and - some accidental. -1.3 skeleton_diff helps you see that drift clearly so that you can: - - Pull newer tooling back into the skeleton. - - Push newer skeleton files out into projects. - - Spot suspicious clutter and structural misuse of the skeleton. - -2. Invocation and Argument Rules -2.1 Basic command line form: - skeleton_diff []... [] -2.2 is required if any of the specified commands - require a project to analyze. -2.3 Commands are parsed from left to right as a list. The final argument - is interpreted as only if: - 2.3.1 At least one command that requires a project appears earlier in - the argument list, and - 2.3.2 There is at least one argument left after that command. -2.4 Dominating commands: - 2.4.1 If any of the following appear anywhere on the command line: - usage, help, version - then that command is executed and all other arguments are - ignored (including other commands and paths). - 2.4.2 This makes: - skeleton_diff usage - skeleton_diff usage . - skeleton_diff version structure ../subu - all behave as simple “usage” or “version” calls. -2.5 Commands that require : - 2.5.1 structure - 2.5.2 import - 2.5.3 export - 2.5.4 suspicious - 2.5.5 addendum - 2.5.6 all (which expands to a sequence of project commands) -2.6 Commands that do not require a project: - 2.6.1 version - 2.6.2 help - 2.6.3 usage - 2.6.4 environment -2.7 Missing project argument: - 2.7.1 If the first command that requires a project is also the last - argument, there is no argument left to serve as - , and skeleton_diff reports an error. - 2.7.2 If a command that requires a project appears before the last - argument, the last argument is interpreted as , even if - its spelling matches a command name. -2.8 Effect of “all”: - 2.8.1 The special command “all” is shorthand for: - environment, structure, import, export, suspicious, addendum - 2.8.2 “all” may not be combined with other commands. If present, it - must be the only non-dominating command on the line. - -3. Environment Expectations -3.1 Before running skeleton_diff you are expected to: - 3.1.1 Be inside a Harmony-derived project. - 3.1.2 Have already run: - source env_toolsmith - which in turn sources: - tool_shared/bespoke/env - 3.1.3 Have $REPO_HOME set to your Harmony project root. -3.2 All paths reported by skeleton_diff are relative to $REPO_HOME unless - otherwise stated. -3.3 The tool does not modify any files. It only reports differences and - prints suggested copy commands for you to run (or edit) manually. - -4. Key Concepts -4.1 Harmony root - 4.1.1 The Harmony skeleton lives at: - $REPO_HOME - 4.1.2 The tool treats $REPO_HOME as the reference layout. -4.2 project root - 4.2.1 The project root is the final argument when a project - is required, and must be a directory. - 4.2.2 It is expected to have been created by cloning the Harmony - skeleton at some point. -4.3 “Between” and “below” paths - 4.3.1 A skeleton directory is any directory that exists in the Harmony - tree, rooted at $REPO_HOME. - 4.3.2 “Between” paths: - - Consider any traversal from the project root down to a known - Harmony skeleton directory (for example, tool/, developer/, - tester/, document/, etc.). - - Any extra directories that appear along those routes in - , but do not exist in the Harmony skeleton, are - “between” paths. - - Example: Harmony has tool/CLI/, but has tool/custom/CLI/. - The inserted custom/ is a “between” directory. - - These often indicate that the developer has modified the - skeleton’s core structural spine. - 4.3.3 “Below” paths: - - Directories that are nested under existing skeleton - directories (for example, tool/custom/new_script.py under - tool/). - - These are usually normal and represent project-specific - organization and additions. - 4.3.4 skeleton_diff reports both: - - “Between” additions, which are more likely to be structural - misuse or deliberate skeleton changes. - - “Below” additions, which are more likely to be healthy - extensions of the skeleton. -4.4 User-owned vs shared zones - 4.4.1 Some areas are explicitly owned by a role and are not audited as - suspicious: - - $REPO_HOME/developer - - $REPO_HOME/tester - - $REPO_HOME/release - 4.4.2 Tools are expected under: - - $REPO_HOME/tool - - $REPO_HOME/tool_shared - 4.4.3 Directories that are covered by a .gitignore are treated as - intentionally messy and are not reported as suspicious clutter. - -5. Commands -5.1 version, help, usage (dominating, no project required) - 5.1.1 version - - Prints: - skeleton_diff version . - - Major and Minor are integers, not a decimal number. - 5.1.2 help - - Shows this detailed documentation. - 5.1.3 usage - - Shows a short, to-the-point command summary and examples. - 5.1.4 If any of these appear, skeleton_diff executes that command and - ignores all other arguments. - -5.2 environment (no project required) - 5.2.1 Prints the key environment context that skeleton_diff relies on: - - $REPO_HOME - - Other Harmony-related variables (e.g., HARMONY_* and REPO_*) - - PATH and selected tool-related variables. - 5.2.2 Useful for debugging configuration or confirming that - env_toolsmith has been sourced correctly. - -5.3 structure (requires ) - 5.3.1 Goal: discover structural drift in directories between Harmony - and . - 5.3.2 Step 1: missing Harmony directories in - - Walk the Harmony skeleton to find all directories under - $REPO_HOME. - - For each Harmony directory, skeleton_diff checks whether the - corresponding directory exists at the same relative path in - . - - Any directory that is present in Harmony but missing in - is reported as: - [MISSING] - 5.3.3 Step 2: new directories in that are not in Harmony - - Walk all directories in . - - Any directory that does not appear in Harmony at the same - relative path is considered “new”. - - New directories are classified as “between” or “below” - according to the rules in section 4.3 and reported so you can - see both structural misuse and legitimate extensions. - -5.4 import / export (both require ) - 5.4.1 Internal files step: - - Both import and export depend on a traversal of skeleton and - project files to classify them as missing/newer/older. - - The traversal is performed automatically as needed; there is no - user-visible “files” command. - 5.4.2 import - - Goal: help you pull improvements *from* *into* Harmony. - - Uses the list of files where is newer than Harmony to - generate shell commands of the form: - cp / $REPO_HOME/ - - Commands overwrite the older skeleton file. The old version is - preserved by git history. - 5.4.3 export - - Goal: help you push newer skeleton files *from* Harmony *into* - . - - Uses the list of files where is older than Harmony to - generate shell commands of the form: - cp $REPO_HOME/ / - - Commands overwrite stale files in . - 5.4.4 Both commands only print shell commands; they never execute them. - -5.5 suspicious (requires ) - 5.5.1 Goal: find “clutter” files that look out of place relative to the - Harmony skeleton. - 5.5.2 A file is not considered suspicious if it is: - - Under $REPO_HOME/developer, which is owned by the developer. - - Under $REPO_HOME/tester, which is owned by the tester. - - Under $REPO_HOME/release, which is deliberately customized by - the developer. - - Under $REPO_HOME/tool or $REPO_HOME/tool_shared, where tools - are expected to live (including substructures). - - In a directory that carries a .gitignore file, which signals - that local clutter is intended and version-control rules exist. - - Present in the Harmony skeleton itself at the same relative - path (i.e., an expected file). - 5.5.3 Any other file that appears in but has no corresponding - skeleton file and is not in the roles’ owned zones or .gitignored - directories is reported as: - [SUSPICIOUS] - 5.5.4 These “between” files are candidates to: - - Move under proper tool directories. - - Add to the skeleton. - - Remove from the project. - -5.6 addendum (requires ) - 5.6.1 Goal: find project-specific tools that might be candidates to - promote back into the Harmony skeleton. - 5.6.2 For each tool directory in : - - tool/ - - tool_shared/ - skeleton_diff walks all files under those directories and - compares them to the Harmony tool directories at the same - relative paths. - 5.6.3 Any file that exists in ’s tool or tool_shared directory - but not in the Harmony skeleton is reported as: - [ADDENDUM] - 5.6.4 These represent project-local tooling; you decide whether to: - - Keep them project-specific, or - - Move them into the shared skeleton. - -5.7 all (requires ) - 5.7.1 all is shorthand for running: - environment - structure - import - export - suspicious - addendum - 5.7.2 It may not be combined with other commands. If you need a - different sequence, list the commands explicitly. - -6. Example Workflows -6.1 Inspect a specific project’s drift - 6.1.1 From a Harmony project: - source env_toolsmith - skeleton_diff all ../subu - 6.1.2 Read: - - environment: sanity-check $REPO_HOME and related variables. - - structure: to see missing or extra directories. - - import/export: to copy improvements across. - - suspicious/addendum: to see clutter and candidate tools. -6.2 Import improvements from a project - 6.2.1 Run: - skeleton_diff import ../subu - 6.2.2 Review the printed cp commands, then run them selectively. -6.3 Refresh a stale project from the skeleton - 6.3.1 Run: - skeleton_diff export ../some_project - 6.3.2 Review cp commands, run them, and then commit in . -6.4 Quick environment and doc checks - 6.4.1 Without a project: - skeleton_diff usage - skeleton_diff help - skeleton_diff version - skeleton_diff environment - -7. Safety and Limitations -7.1 No automatic writes - 7.1.1 skeleton_diff never changes files itself. It only prints commands - and reports. -7.2 Time-based comparison - 7.2.1 “Newer” and “older” are based on filesystem modification times. - If clocks or timestamps are misleading, results may need manual - interpretation. -7.3 Directory semantics - 7.3.1 “Between” and “below” classification is a heuristic based on - the current Harmony skeleton. Some edge cases may require human - judgment. -7.4 Git integration - 7.4.1 The tool assumes that Harmony is a git repository and relies on - git history for old versions. It does not attempt to archive or - back up overwritten files. -7.5 Exit Status - 7.5.1 skeleton_diff returns: - - 0 on success (even if differences are found). - - Non-zero if arguments are invalid (e.g., missing project path) - or if a subcommand fails before producing output. -""" - print(help_text.strip()) - return 0 diff --git a/tool/deprecated/skeleton_paths.py b/tool/deprecated/skeleton_paths.py deleted file mode 100644 index 521d728..0000000 --- a/tool/deprecated/skeleton_paths.py +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env python3 -""" -skeleton_paths — filesystem indexing and ignore logic for skeleton_diff -""" - -import os -from dataclasses import dataclass -from pathlib import Path -from typing import Dict, Set, List - - -# ---------------------------------------------------------------------- -# Node information -# ---------------------------------------------------------------------- - -@dataclass -class NodeInfo: - path_type: str # "file", "dir", or "other" - mtime: float - is_leaf_flag: bool = False - - -# ---------------------------------------------------------------------- -# Built-in ignore rules and helper -# ---------------------------------------------------------------------- - -def _is_builtin_ignored(rel_path: Path) -> bool: - """ - Cheap ignore filter for common junk: - - .git tree - - __pycache__ and Python bytecode - - notebook / pytest caches - - editor backup files (*~, *.bak) - """ - parts = rel_path.parts - - # Ignore anything under a .git directory - if ".git" in parts: - return True - - name = parts[-1] if parts else "" - - # Directories by name - if name in { - "__pycache__", - ".ipynb_checkpoints", - ".pytest_cache", - }: - return True - - # Python bytecode / compiled - lower_name = name.lower() - if lower_name.endswith(".pyc") or lower_name.endswith(".pyo") or lower_name.endswith(".pyd"): - return True - - # Editor backup / temp - if lower_name.endswith("~") or lower_name.endswith(".bak"): - return True - - return False - - -def should_ignore_node(project_root: Path, rel_path: Path) -> bool: - """ - Single "ignore this?" decision point. - - For now we: - - apply built-in patterns, and - - treat any directory that has a .gitignore file as fully ignored - (except for the .gitignore file itself). - - TODO: - - Parse .gitignore files properly and obey their patterns. - """ - if not rel_path.parts: - # Root is never ignored. - return False - - # Built-in patterns - if _is_builtin_ignored(rel_path): - return True - - absolute_path = project_root / rel_path - parent_dir = absolute_path.parent - - # If parent directory has a .gitignore, ignore this node. - # (We do not ignore the .gitignore file itself.) - if (parent_dir / ".gitignore").exists() and absolute_path.name != ".gitignore": - return True - - return False - - -# ---------------------------------------------------------------------- -# Indexing -# ---------------------------------------------------------------------- - -def _make_node_info(path: Path) -> NodeInfo: - if path.is_file(): - path_type = "file" - elif path.is_dir(): - path_type = "dir" - else: - path_type = "other" - - try: - mtime = path.stat().st_mtime - except OSError: - mtime = 0.0 - - return NodeInfo( - path_type=path_type, - mtime=mtime, - is_leaf_flag=False, - ) - - -def index_project(project_root: Path) -> Dict[Path, NodeInfo]: - """ - Walk an entire project tree and build a dictionary mapping - relative paths -> NodeInfo, applying the ignore filter. - - The relative path Path(".") is used for the project root. - """ - project_root = project_root.resolve() - node_dict: Dict[Path, NodeInfo] = {} - - # Always register the root - root_rel_path = Path(".") - node_dict[root_rel_path] = _make_node_info(project_root) - - for dirpath_str, dirnames_list, filenames_list in os.walk(project_root): - dirpath = Path(dirpath_str) - rel_dir = dirpath.relative_to(project_root) - - # Filter directory traversal in-place so os.walk will skip ignored dirs. - keep_dirnames_list: List[str] = [] - for dirname in dirnames_list: - child_rel = (rel_dir / dirname) if rel_dir != Path(".") else Path(dirname) - if should_ignore_node(project_root, child_rel): - continue - keep_dirnames_list.append(dirname) - dirnames_list[:] = keep_dirnames_list - - # Ensure directory node itself is recorded - if rel_dir not in node_dict: - node_dict[rel_dir] = _make_node_info(dirpath) - - # Record files - for filename in filenames_list: - rel_file = (rel_dir / filename) if rel_dir != Path(".") else Path(filename) - if should_ignore_node(project_root, rel_file): - continue - abs_file = dirpath / filename - node_dict[rel_file] = _make_node_info(abs_file) - - # Second pass: mark leaf directories - parent_dir_set: Set[Path] = set() - for rel_path in node_dict.keys(): - if rel_path == Path("."): - continue - parent = rel_path.parent - parent_dir_set.add(parent) - - for rel_path, info in node_dict.items(): - if info.path_type == "dir": - if rel_path not in parent_dir_set: - info.is_leaf_flag = True - - return node_dict diff --git a/tool/skel.tgz b/tool/skel.tgz deleted file mode 100644 index 7e2bf1a..0000000 Binary files a/tool/skel.tgz and /dev/null differ