Split monolithic coworker.py into modular CLIs and add root Makefile - #92
Split monolithic coworker.py into modular CLIs and add root Makefile#92prksandeep wants to merge 1 commit into
Conversation
- Decompose monolithic framework into three standalone CLI tools: * compiler.py: Verification, package schema validation, delegation graph checks, prompt/skill generation, and harness translation (Claude Code & Codex). * installer.py: Interactive/non-interactive installation, environment question coercion, file collision detection, non-destructive config merges, and uninstallation rollback. * runtime.py: Standalone embedded runtime for target workspaces supporting collision-free run namespaces (start-run), SHA256 artifact descriptors (describe-artifact), and deterministic JSON schema validation. - Remove monolithic coworker.py and test_coworker.py in favor of specialized tools. - Update compiler to bundle only runtime.py and utils.py into generated distributions and emit agent instructions targeting runtime.py. - Update maxkernel_package_converter.py to reference compiler.py for package verification. - Update BUILD with dedicated binary targets (:compiler_bin, :installer_bin, :runtime_bin) and modular test targets. - Update framework README.md with the modular architecture and commands. - Add root Makefile with test, test-nexus, and clean targets for local developer workflows. - Add dedicated test suites: test_compiler.py, test_installer.py, test_runtime.py, and test_utils.py. Testing: - make test (ran all 14 unit tests across compiler, installer, runtime, and utils with 100% pass rate). - Verified standalone CLI help and execution for compiler.py, installer.py, and runtime.py.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
cc @jacobrplatin @learning-to-play for review. |
There was a problem hiding this comment.
Code Review
This pull request modularizes the Coworker framework by splitting the monolithic coworker.py script into three specialized modules: compiler.py (for package verification and translation), installer.py (for distribution installation and rollback), and runtime.py (for run namespace isolation and artifact validation). The build configurations, documentation, and unit tests have been updated to reflect this new architecture. The review feedback highlights two robustness improvements in compiler.py: handling potential KeyError exceptions when parsing compatibility targets, and raising explicit errors if required runtime scripts are missing during translation.
| # Validate version constraint syntax | ||
| parse_version_range(target["versions"]) | ||
|
|
||
| # Verify target satisfies all required capabilities | ||
| required = set(manifest.get("required_capabilities", [])) | ||
| available = {k for k, v in target.get("capabilities", {}).items() if v} | ||
| missing = required - available | ||
| if missing: | ||
| raise CoworkerError( | ||
| f"target {target['name']} cannot preserve required capabilities:" | ||
| f" {', '.join(sorted(missing))}" | ||
| ) |
There was a problem hiding this comment.
If the compatibility target configuration is missing the versions or name keys, a KeyError will be raised instead of a clean CoworkerError. It is safer to use .get() or validate their presence beforehand.
| # Validate version constraint syntax | |
| parse_version_range(target["versions"]) | |
| # Verify target satisfies all required capabilities | |
| required = set(manifest.get("required_capabilities", [])) | |
| available = {k for k, v in target.get("capabilities", {}).items() if v} | |
| missing = required - available | |
| if missing: | |
| raise CoworkerError( | |
| f"target {target['name']} cannot preserve required capabilities:" | |
| f" {', '.join(sorted(missing))}" | |
| ) | |
| versions = target.get("versions") | |
| if versions is None: | |
| raise CoworkerError(f"compatibility target for {harness} is missing 'versions'") | |
| parse_version_range(versions) | |
| # Verify target satisfies all required capabilities | |
| required = set(manifest.get("required_capabilities", [])) | |
| available = {k for k, v in target.get("capabilities", {}).items() if v} | |
| missing = required - available | |
| if missing: | |
| target_name = target.get("name", harness) | |
| raise CoworkerError( | |
| f"target {target_name} cannot preserve required capabilities:" | |
| f" {', '.join(sorted(missing))}" | |
| ) |
| for script_name in ("runtime.py", "utils.py"): | ||
| script_path = framework_dir / script_name | ||
| if script_path.is_file(): | ||
| shutil.copy2(script_path, runtime_dir / script_name) |
There was a problem hiding this comment.
If any of the required runtime scripts (runtime.py or utils.py) are missing from the framework directory, the compiler will silently skip copying them, resulting in a broken distribution. It is safer to raise an error if a required script is not found.
| for script_name in ("runtime.py", "utils.py"): | |
| script_path = framework_dir / script_name | |
| if script_path.is_file(): | |
| shutil.copy2(script_path, runtime_dir / script_name) | |
| for script_name in ("runtime.py", "utils.py"): | |
| script_path = framework_dir / script_name | |
| if not script_path.is_file(): | |
| raise CoworkerError(f"Required runtime script missing: {script_path}") | |
| shutil.copy2(script_path, runtime_dir / script_name) |
| test-nexus: | ||
| PYTHONPATH=$(FRAMEWORK_DIR) $(PYTHON) -m unittest discover -s $(FRAMEWORK_DIR)/tests -v | ||
|
|
||
| clean: |
There was a problem hiding this comment.
This is fine for now, but should just be in the gitignore -- easier that way
Summary of Changes
compiler.py: Package verification, JSON schema validation, delegation graph checks, prompt/skill generation, and harness translation (Claude Code & Codex).installer.py: Interactive/non-interactive installation, environment question coercion, file collision detection, non-destructive config merges, and uninstallation rollback.runtime.py: Standalone embedded runtime for target workspaces supporting collision-free run namespaces (start-run), SHA256 artifact descriptors (describe-artifact), and deterministic JSON schema validation.coworker.pyandtest_coworker.pyin favor of specialized tools.compiler.pyto bundle onlyruntime.pyandutils.pyinto generated distributions and emit agent instructions targetingruntime.py.maxkernel_package_converter.pyto referencecompiler.pyfor package verification.BUILDwith dedicated binary targets (:compiler_bin,:installer_bin,:runtime_bin) and modular test targets.README.mdwith modular architecture, guarantees, and commands.Makefilewithtest,test-nexus, andcleantargets.test_compiler.py,test_installer.py,test_runtime.py,test_utils.py).Scope
nexus/directory and rootMakefile.Testing
make testexecuted all 14 unit tests across compiler, installer, runtime, and utils with 100% pass rate.compiler.py,installer.py, andruntime.py.