AIAG-645: v0.1.0-alpha release milestones — open source readiness, templates, CI, and changelog#1
Merged
Merged
Conversation
Add RuntimeConfig dataclass with named presets and custom env-var overrides. CANOPY_RUNTIME env var selects the runtime (default: claude-code). "custom" reads individual CANOPY_RUNTIME_BIN, CANOPY_RUNTIME_RUN_FLAGS, CANOPY_RUNTIME_OUTPUT, etc. Unrecognized values raise a helpful error listing available options. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded 'claude' binary and '--name' flag with runtime.bin and runtime.connect_flags from get_runtime_config(). Banner now shows the actual command being used. Supports any configured runtime. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded 'claude --print --output-format stream-json' with runtime.bin + runtime.run_flags_template. Add output_format branch: stream-json uses existing NDJSON parser with summary line; text mode is a plain passthrough to stdout. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- utils.py: remove hardcoded L1_FILES/L1_DIRS/L3_DIR constants; set_l1_readonly() now takes RuntimeConfig; resolve_template_path() accepts config_file parameter for runtime-specific indicator file - create.py: pass runtime to set_l1_readonly and resolve_template_path; use runtime.l3_dir for memory directory initialization - info.py: use runtime.l1_files/l1_dirs/l3_dir for layer counts; use runtime.config_file for identity preview Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Rename specs/06-claude-code-runtime.md → specs/06-runtime.md - Rewrite doc: introduces abstract 4-point runtime interface, then scopes Claude Code as the reference implementation - Add "Configuring the Runtime" section with CANOPY_RUNTIME env vars - Add "Other Runtimes" section for custom runtime guidance - Fix all cross-references: specs/05, specs/01, README, CLAUDE.md Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- cli/README.md: add Runtime Configuration section with full env var table and custom runtime example; update Workspace Structure to reflect runtime-configurable L1/L3 paths - README.md: update Docker analogy row and Status section to mention configurable runtime Marks flexible-runtime plan complete. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
config.py:
- Change list[str] fields to tuple[str, ...] on frozen dataclass so
immutability is genuine, not just field rebind protection
- Use shlex.split for CANOPY_RUNTIME_CONNECT_FLAGS (was .split())
- Validate CANOPY_RUNTIME_OUTPUT against known set; fail loudly on typos
- _parse_list → _parse_tuple, returns tuple[str, ...]
- Add import shlex; drop unused dataclasses.field
utils.py:
- Remove TYPE_CHECKING guard; use a direct top-level import of RuntimeConfig
(no circular import exists to defend against)
run.py:
- Replace shell=True + string concat with list argv + cwd=workspace_path,
eliminating the shell injection surface entirely
- Replace assert process.stdout is not None with an explicit RuntimeError
- Replace process.wait(timeout=) with a threading.Timer watchdog that kills
the process if it hangs without producing output within the timeout window
info.py:
- Gate _read_mcp_servers on runtime.name == "claude-code"; other runtimes
don't have .claude/settings.json
create.py:
- Add comment documenting the {l3_dir}/default/memory/ structure assumption
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Replace Olly-specific file matrix in review-agent.md with extension-based generic patterns; remove all Olly/Shadow/apps/api references - Create .claude/commands/review.md with scope detection, parallel agent dispatch (review-agent + code-quality-specialist), and consolidated report - Mark both plan tasks complete Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
config.py:
- Add {prompt} presence validation in CANOPY_RUNTIME_RUN_FLAGS
- Reject CANOPY_RUNTIME_BIN with path separators (/ or \)
- Add settings_file field to RuntimeConfig (claude-code: .claude/settings.json)
- Add docstring to _parse_tuple explaining CSV vs shlex semantics
- Use shlex.split for CANOPY_RUNTIME_CONNECT_FLAGS (was .split())
run.py:
- Simplify argv construction: split base flags, append prompt directly
(eliminates shlex.quote + shlex.split double-pass quoting complexity)
- Change stderr=PIPE to stderr=sys.stderr (prevents deadlock on verbose runs)
- Wrap subprocess.Popen in try/except FileNotFoundError for clear error
- Extract _kill to module-level _kill_process function with explicit params
- Add try/except OSError in _kill_process for Ctrl-C race condition
- Remove redundant process.wait() in timeout path (already called in finally)
- Add comment about monotonic text-diff assumption in _extract_text_delta
info.py:
- Update _read_mcp_servers to accept settings_file parameter
- Remove magic-string runtime.name == "claude-code" gate; use runtime.settings_file
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Create comprehensive blackbox end-to-end tests for all CLI commands: - Subprocess-based testing (real canopy binary invocation) - Uses real Claude CLI as runtime for true integration testing - 6 milestones covering ~45+ tests - API tests marked with @pytest.mark.api for selective execution - Tests workspace lifecycle, run/connect commands, config, error handling - Minimal prompts to reduce API costs Prerequisite for open-source-readiness plan. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Completes the e2e-testing plan: 14/14 tasks done. Full suite: 51 tests pass (+ 8 api-marked skipped without key). Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…mands Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Adds a 5s sleep before each real API test call (configurable via CANOPY_TEST_API_DELAY_SECS). Sleep fires after the skip guard so no-key runs are unaffected. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Consolidate three identical "hello" tests into test_run_success with all three assertions; remove artificial timeout=120 from two happy-path tests; bump CANOPY_TEST_API_DELAY_SECS default from 5s to 10s. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Replace fixed inter-test delay (120s) with transparent exponential backoff in run_cli: retries up to 3x (30s, 60s, 120s) when subprocess output contains a 429 rate-limit error. Resets requires_api_key delay to 10s. All 6 tests in test_run.py pass cleanly (~50s total, zero 429 errors). Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…template_path Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
….json Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…y specs Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- LICENSE: Coralogix → Canopy Contributors - docs/cc-stream-format.md: remove coralogix MCP server name - CLAUDE.md: remove Shadow/Olly internal product references - specs/07-adoption-guide.md: fix broken README link (./README.md → ../README.md) - cli/pyproject.toml: add license, authors, keywords, classifiers, URLs - cli/canopy_cli/py.typed: add PEP 561 marker - .github/workflows/ci.yml: GitHub Actions lint + test on push/PR - CONTRIBUTING.md, SECURITY.md: OSS community files - .github/ISSUE_TEMPLATE/: bug + feature request templates - .github/PULL_REQUEST_TEMPLATE.md: PR checklist template - .gitignore: add context-analysis.md and scheduled_tasks.lock Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
… load_env_file, set_l1_readonly Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
… test_config.py Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Replace YOUR_ORG with coralogix in pyproject.toml URLs and CONTRIBUTING.md - Gitignore .claude/agents/ and .claude/commands/ (internal dev tooling) - Remove .claude/agents/review-agent.md and .claude/commands/review.md from tracking - Update CLAUDE.md status: tests and CI now exist Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Reframe "powered by Claude Code" to "pluggable runtimes" - Qualify all Claude Code references with "when using Claude Code" or "(default)" - Update philosophy: "The runtime is the CPU" not "Claude Code is the runtime" - Add runtime-agnostic language guideline to CLAUDE.md writing guidelines Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add Supported Runtimes table (Claude Code default + custom) - Rename "Reference Implementation" to "Default Runtime" - Note isolation as a security contract for all runtimes Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Replace "CC runs against it" with "the agent runtime runs against it" - Qualify .claude/ paths as Claude Code conventions - Rename "Mapping to Claude Code Primitives" to "Mapping to Runtime Primitives" - Generalize all CC references to "the runtime" with CC qualifiers Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…time-agnostic framing - Replace "CC process" with "runtime process" throughout - Replace "CC's sandboxing" with "runtime sandboxing" - Qualify Claude Code-specific features (--resume, --max-turns) - Generalize all unqualified Claude Code references Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…me-agnostic framing - Adoption guide: replace CC-specific language with runtime-generic, keep CC in examples - cli/README: soften to "agent session (Claude Code by default)" - Templates: update all CC references to runtime-agnostic language Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add 3 example templates: codebase-navigator, release-pilot, daily-standup - codebase-navigator: docs-as-database + skills (explain-architecture, find-examples) - release-pilot: multi-step skills (changelog-draft, pre-release-audit) - daily-standup: per-user memory (morning-briefing, standup-summary) - Update resolve_template_path() to support bare template names and examples/ dir - Default template changed from example-template/ to examples/codebase-navigator/ - Remove example-template/ (SRE agent) and update all references - Add Quick Start section and template descriptions to README Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Move examples/ into cli/canopy_cli/examples/ so pip install includes them - Update _find_examples_dir() to find bundled examples first, then walk-up fallback - Add .github/workflows/publish.yml for PyPI OIDC trusted publisher on v* tags - Verified: wheel contains all 12 template files; canopy --help works from install Note: PyPI OIDC setup requires configuring a Trusted Publisher on pypi.org (Settings -> Trusted Publisher -> GitHub Actions -> coralogix/canopy, workflow: publish.yml) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Aligns with Docker (Moby) and Kubernetes licensing. Apache 2.0 includes an explicit patent grant, which is standard for infrastructure tooling and preferred by enterprise teams. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- DTZ011: replace date.today() with datetime.now(tz=UTC).date() in create.py - RUF019: replace redundant key checks with data.get() in test_create.py - RUF059: prefix unused unpacked variables with _ in test_delete.py, test_edge_cases.py - B011: replace assert False with raise AssertionError in test_edge_cases.py - I001: fix unsorted imports in test_run.py - RUF043: use raw string for regex match pattern in test_utils.py - ci.yml: upgrade actions/checkout and astral-sh/setup-uv to v5 (Node.js 24) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ive) - M5 Pre-Release Polish: CHANGELOG only (can be done anytime) - M6 Go Live: README badges + PyPI Trusted Publisher setup + tag - Tagging triggers PyPI — moves to M6 so it's explicit and deliberate Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
niv-hertz
approved these changes
Apr 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
AIAG-645
Summary
Test plan
canopy createcorrectly bundles and provisions example templates🤖 Generated with Claude Code