Skip to content

feat: install amplihack-rs (Rust CLI) on all new VMs#948

Open
rysweet wants to merge 6 commits intomainfrom
feat/install-amplihack-rs
Open

feat: install amplihack-rs (Rust CLI) on all new VMs#948
rysweet wants to merge 6 commits intomainfrom
feat/install-amplihack-rs

Conversation

@rysweet
Copy link
Copy Markdown
Owner

@rysweet rysweet commented Apr 5, 2026

Adds cargo install --git https://github.com/rysweet/amplihack-rs amplihack to the cloud-init provisioning so all new azlin VMs have the Rust amplihack CLI available.

Also adds cmake to the default dev packages (required for ladybugdb build dependency).

Changes:

  • rust/crates/azlin-azure/src/cloud_init.rs: Added amplihack-rs install command and cmake package
  • terraform/azdoit-test/cloud-init.yml: Same additions for Terraform-based provisioning

All 27 cloud-init tests pass.

Ubuntu and others added 6 commits March 19, 2026 14:45
Resolves #878 by propagating errors instead of swallowing them
Resolves #879 by enforcing UTF-8 encoding in all file I/O
Resolves #880 by validating required 'command' field in examples

Changes:
- Add DocumentationError exception class to models.py
- example_manager.py: propagate ValueError, use encoding='utf-8', validate required fields
- extractor.py: raise DocumentationError instead of printing warnings
- hasher.py: use encoding='utf-8', raise on failure
- sync_manager.py: use encoding='utf-8', narrow except clauses
- scripts/__init__.py: new empty file making scripts/ a Python package
- pyproject.toml: add pythonpath and dev dependencies for tests
- Add comprehensive test suite in tests/unit/test_cli_documentation.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Per TDD methodology (Step 7), write tests that:
- FAIL on main (DocumentationError does not yet exist in models.py)
- PASS once the implementation in this PR is merged

Test coverage (41 tests across 5 groups):

TestDocumentationError (3):
  - DocumentationError is an Exception subclass
  - Can be raised with a message
  - Exported in models.__all__

TestCLIHasherErrorHandling (9):
  - Corrupt JSON raises DocumentationError (not silent {})
  - Missing file returns empty dict (first-run behaviour)
  - JSONDecodeError is chained via 'from e' (SEC-R-14)
  - save_hashes() uses encoding='utf-8' (SEC-R-10)
  - Unicode hash round-trip
  - OSError on save raises DocumentationError

TestExampleManagerValidation (16):
  - Missing/empty/None 'command' field raises DocumentationError (SEC-R-11)
  - Valid 'command' field returns examples
  - load/save use encoding='utf-8' (SEC-R-10)
  - Unicode content survives round-trip
  - ValueError from _sanitize_command_name propagates (SEC-R-08)
  - yaml.safe_load rejects !!python/object (SEC-R-09)
  - Corrupt YAML raises DocumentationError

TestDocSyncManagerExceptionNarrowing (8):
  - DocumentationError is caught; AttributeError/TypeError propagate (SEC-R-12)
  - write_text() uses encoding='utf-8' (SEC-R-10)
  - Path traversal rejected in _get_output_path

TestCLIExtractorSecurity (5):
  - ALLOWED_MODULES whitelist unchanged (SEC-R-13)
  - Unlisted module rejected
  - Parse failure raises DocumentationError (not silent None)
  - Missing command returns None (not found != error)
  - yaml.load() absence verified in source

Also adds tests/conftest.py with repo-root sys.path setup so both
azlin and scripts.cli_documentation are importable during tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… in cli_documentation

_extract_from_click_command now raises DocumentationError instead of
returning None, so the `if metadata:` and `if sub_metadata:` guards in
the callers were unreachable dead code. Remove them and update the return
type annotation from `CLIMetadata | None` to `CLIMetadata`.

Also remove the redundant `{e}` interpolation in save_examples()
DocumentationError — the cause is already chained via `from e`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ator

hasher.py: replace bare `except Exception` with specific handlers for
  json.JSONDecodeError and OSError, each carrying a file-path-aware
  message — satisfies SEC-R-14 (exception chaining).

validator.py: pass encoding='utf-8' to path.read_text() — closes the
  last remaining instance of the locale-dependent I/O pattern from #879.

Resolves #878 (error-swallowing detail)
Closes #879 (encoding='utf-8' — final file)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PATCH bump for bug fixes in issues #878, #879, #880 (cli_documentation quality).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 'cargo install --git .../amplihack-rs amplihack' to cloud-init
- Add cmake to default dev packages (required for ladybugdb build)
- Update both Rust cloud_init.rs and Terraform cloud-init.yml
- All 27 cloud-init tests pass

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant