Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ jobs:
with:
auto-update-conda: true
python-version: ${{ env.PYTHON_VERSION }}
activate-environment: BLOOM
environment-file: bloom_env.yaml
activate-environment: BLOOM-local
environment-file: environment.yaml
auto-activate-base: false

- name: Install bloom in editable mode
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ bloom db seed
bloom server start --port 8912
```

`source ./activate <deploy-name>` creates the deployment-scoped conda environment from repo-root `environment.yaml` when it is missing, then activates it and installs only the Bloom repo editable.

The supported local workflow is CLI-first and uses Bloom’s own environment/bootstrap path.

Delete-only teardown is also available:
Expand Down
10 changes: 5 additions & 5 deletions activate
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,9 @@ if command -v conda &> /dev/null; then
fi
else
echo -e " ${_YELLOW}⚠${_NC} Conda environment '${_BLOOM_CONDA_ENV_NAME}' not found."
if [[ -f "$BLOOM_ROOT/bloom_env.yaml" ]]; then
echo -e " ${_CYAN}→${_NC} Installing conda environment from bloom_env.yaml..."
if conda env create -n "${_BLOOM_CONDA_ENV_NAME}" -f "$BLOOM_ROOT/bloom_env.yaml"; then
if [[ -f "$BLOOM_ROOT/environment.yaml" ]]; then
echo -e " ${_CYAN}→${_NC} Installing conda environment from environment.yaml..."
if conda env create -n "${_BLOOM_CONDA_ENV_NAME}" -f "$BLOOM_ROOT/environment.yaml"; then
Comment on lines +232 to +234
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update CI to use renamed conda environment file

Switching activation to environment.yaml and deleting bloom_env.yaml leaves GitHub Actions pointing at a file that no longer exists (.github/workflows/ci.yml:177 still sets environment-file: bloom_env.yaml). In this state, the test job cannot create its conda env on a fresh runner, so CI will fail immediately after this migration unless the workflow is updated in the same change.

Useful? React with 👍 / 👎.

echo -e " ${_GREEN}✓${_NC} Conda environment created successfully"
conda activate "${_BLOOM_CONDA_ENV_NAME}"
if [[ -n "$CONDA_PREFIX" ]] && [[ -d "$CONDA_PREFIX/bin" ]]; then
Expand All @@ -241,7 +241,7 @@ if command -v conda &> /dev/null; then
echo -e " ${_YELLOW}⚠${_NC} Failed to create conda environment."
fi
else
echo -e " ${_YELLOW}⚠${_NC} bloom_env.yaml not found."
echo -e " ${_YELLOW}⚠${_NC} environment.yaml not found."
fi
fi
else
Expand All @@ -251,7 +251,7 @@ fi

if [[ "${CONDA_DEFAULT_ENV:-}" != "${_BLOOM_CONDA_ENV_NAME}" ]] || [[ -z "${CONDA_PREFIX:-}" ]] || [[ ! -x "${CONDA_PREFIX}/bin/python" ]]; then
echo -e " ${_YELLOW}⚠${_NC} ${_BLOOM_CONDA_ENV_NAME} conda environment is required."
echo -e " ${_CYAN}→${_NC} Run 'conda env create -n ${_BLOOM_CONDA_ENV_NAME} -f bloom_env.yaml' if needed, then retry 'source ./activate <deploy-name>'."
echo -e " ${_CYAN}→${_NC} Run 'conda env create -n ${_BLOOM_CONDA_ENV_NAME} -f environment.yaml' if needed, then retry 'source ./activate <deploy-name>'."
return 1
fi

Expand Down
34 changes: 0 additions & 34 deletions bloom_env.yaml

This file was deleted.

134 changes: 134 additions & 0 deletions docs/remove_siblings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Multi-Agent Rollout: Remove Sibling Repo Installs From Active-Service Activation

## Summary

- Remove sibling-repo rebinding from activation flows across the active service repo set: `bloom`, `lsmc-atlas`, `daylily-ursa`, `dewey`, and `zebra_day`.
- Keep self-install behavior in `activate` where it exists today so each repo can still put its own CLI on `PATH`.
- Standardize the policy: activation uses packaged dependencies only; it never installs `../daylily-tapdb`, `../daylily-cognito`, `../cli-core-yo`, or `../lims_repos/*`.
- Make old sibling-rebinding env vars a hard error, not a silent fallback.
- Update Dayhoff service metadata so it no longer advertises sibling bootstrap behavior for the active repos.
- Prerequisite: fix packaged dependency coherence first, especially `zebra_day`, because removing sibling installs will expose current version mismatches immediately.

## Agent Topology

1. `Agent 0 — Coordinator`
Owns sequencing, policy consistency, merge order, and final verification. No repo code changes.

2. `Agent 1 — zebra_day + Dependency Alignment`
Owns `/Users/jmajor/projects/daylily/zebra_day`.
Responsibilities:
- Remove unconditional sibling installs from `activate`.
- Keep only zebra_day self-install.
- Update packaged dependency pins so the repo is solvable without sibling rebinding.
- Release a new packaged version before downstream repos rely on it.
Reason: `zebra_day==3.5.0` still pins `daylily-tapdb==3.2.0`, which currently breaks a clean packaged Bloom env.

3. `Agent 2 — Bloom`
Owns `/Users/jmajor/projects/daylily/bloom`.
Responsibilities:
- Remove sibling path resolution and sibling install logic from `activate`.
- Remove the stale Dayhoff-artifact rebinding escape hatch.
- Keep Bloom self-install.
- Replace sibling fallback with packaged-dependency validation and hard failure on legacy `USE_LOCAL_*`.

4. `Agent 3 — Atlas`
Owns `/Users/jmajor/projects/lsmc/lsmc-atlas`.
Responsibilities:
- Remove `USE_LOCAL_DAYLILY_TAPDB`, `USE_LOCAL_DAYLILY_COGNITO`, and `USE_LOCAL_CLI_CORE_YO` rebinding from `activate`.
- Keep Atlas self-install.
- Add explicit packaged-dependency validation and hard failure on legacy env vars.

5. `Agent 4 — Ursa`
Owns `/Users/jmajor/projects/daylily/daylily-ursa`.
Responsibilities:
- Remove sibling repo resolution/install paths from `activate`.
- Keep Ursa self-install.
- Convert `USE_LOCAL_*` sibling-rebinding flow into hard failure with a clear message.

6. `Agent 5 — Dewey`
Owns `/Users/jmajor/projects/daylily/dewey`.
Responsibilities:
- Remove sibling repo resolution/install paths from `activate`.
- Keep Dewey self-install.
- Convert `USE_LOCAL_*` sibling-rebinding flow into hard failure with a clear message.

7. `Agent 6 — Kahlo Audit`
Owns `/Users/jmajor/projects/lsmc/kahlo`.
Responsibilities:
- Confirm Kahlo has no sibling install logic beyond self-install.
- Make no code change unless hidden sibling rebinding is found elsewhere in its operator/bootstrap flow.

8. `Agent 7 — Dayhoff Metadata`
Owns `/Users/jmajor/projects/dayhoff`.
Responsibilities:
- Update active-service metadata so it no longer suggests sibling bootstrap behavior.
- Remove or neutralize `bootstrap_repos` for `atlas`, `bloom`, `ursa`, `dewey`, and `kahlo` in service catalog/config.
- Keep service-directory ownership and repo catalog intact.

## Key Changes

### Activation Contract
- `activate` must not inspect or install sibling repos from:
- `../daylily-tapdb`
- `../daylily-cognito`
- `../cli-core-yo`
- `../lims_repos/*`
- `activate` may continue to install the current repo editable so the repo’s own CLI works.
- Legacy sibling-rebinding env vars become unsupported operator inputs:
- `USE_LOCAL_DAYLILY_TAPDB`
- `USE_LOCAL_DAYLILY_COGNITO`
- `USE_LOCAL_CLI_CORE_YO`
- New default when any of those vars are set: hard fail activation with a clear message that sibling rebinding is no longer supported from `activate` and packaged dependencies must be installed instead.

### Packaged Dependency Validation
- After env activation and self-install, each repo validates required packaged deps by import or distribution lookup.
- Missing packaged deps must fail clearly and name the package, not offer a sibling checkout fallback.
- `zebra_day` must be released first with compatible packaged pins so downstream repos can activate cleanly without sibling installs.

### Dayhoff Metadata
- Remove/update active-service `bootstrap_repos` metadata so it matches the new packaged-deps-only activation policy.
- Do not change Dayhoff auth logic; this is metadata/policy cleanup only.

## Execution Waves

### Wave 1 — Dependency Coherence
- Agent 1 updates `zebra_day` so its published package no longer pins stale shared-lib versions.
- Agent 0 verifies that packaged active-service envs can resolve current shared versions without local sibling repos.

### Wave 2 — Parallel Activation Cleanup
- Agents 2 through 5 remove sibling-install logic from `bloom`, `atlas`, `ursa`, and `dewey` in parallel.
- Agent 6 audits `kahlo`; only edits if hidden sibling rebinding exists.
- Agent 7 updates Dayhoff service metadata in parallel.

### Wave 3 — Verification and Convergence
- Agent 0 verifies all active repos now have the same activation policy:
- self-install allowed
- sibling installs removed
- legacy `USE_LOCAL_*` values hard fail
- packaged deps validated explicitly
- Only after that, cut repo-specific releases/tags where shipped activation behavior changed.

## Test Plan

- For each changed service repo:
- Fresh shell `source ./activate <deploy-name>` succeeds without any sibling checkout present.
- The repo’s own CLI is on `PATH`.
- No `pip install -e ../...` or sibling path probing occurs during activation.
- Setting any legacy `USE_LOCAL_*` var causes activation to fail with the new explicit error.
- Required packaged deps import successfully from the activated env.
- Repo-specific smoke:
- Bloom: existing GUI/auth callback test slice still passes under packaged deps.
- Atlas: existing Cognito/auth test slice still passes.
- Ursa: existing deployment/auth smoke still passes.
- Dewey: existing UI session auth slice still passes.
- zebra_day: activation and packaged import smoke pass without sibling repos.
- Dayhoff:
- Metadata tests or config assertions confirm active services no longer declare sibling bootstrap repos.

## Assumptions and Defaults

- Keep self-editable install behavior in `activate`; only sibling installs are removed.
- Legacy sibling-rebinding env vars are removed as supported behavior and become hard errors.
- `kahlo` is audit-only unless new sibling-rebinding logic is discovered.
- `daylily-tapdb` and `daylily-cognito` are not changed for this rollout beyond audit; they do not install sibling repos today.
- `zebra_day` dependency alignment is a required prerequisite, not optional cleanup, because current packaged pins still hide behind sibling rebinding.
66 changes: 66 additions & 0 deletions environment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# =============================================================================
# BLOOM LIMS Conda Environment Definition
# =============================================================================
# Environment Name: BLOOM-local (deployment-specific names are supplied at activation time)
#
# Setup:
# conda env create -n BLOOM-local -f environment.yaml
# conda activate BLOOM-local
#
# Update existing environment:
# conda env update -f environment.yaml --prune
#
# NOTE: This project uses CONDA for environment management, NOT pip/poetry/venv.
# See pyproject.toml [tool.bloom] section for more configuration details.
# =============================================================================

name: BLOOM-local

channels:
- conda-forge
dependencies:
- ipython=8.18.1
- parallel=20230922
- pip=23.3.1
- postgresql=16.1
- psycopg2=2.9.9
- python=3.12.0
- djlint
- jq
- fd-find
- rclone
- setuptools<81
- pip:
- black>=24.0.0
- cli-core-yo>=0.5.1
- boto3>=1.34.0
- daylily-cognito==0.4.1
- daylily-tapdb==3.2.2
- moto>=5.0.0
- fastapi>=0.110.0
- httpx>=0.27.2
- itsdangerous>=2.1.2
- Jinja2>=3.0.3
- matplotlib>=3.8.0
- mypy>=1.0
- pandas>=2.2.0
- playwright>=1.42.0
- pydantic>=2.6.0
- pydantic-settings>=2.0.0
- PyJWT>=2.8.0
- python-multipart>=0.0.9
- pytest>=8.0
- pytest-asyncio>=0.23.0
- pytest-cov>=4.1.0
- pytest-playwright>=0.4.4
- psutil>=5.9.0
- PyYAML>=6.0
- requests>=2.28.2
- requests-mock>=1.11.0
- rich>=13.0
- ruff>=0.1.0
- sqlalchemy>=2.0.23
- starlette>=0.35.1
- uvicorn>=0.28.0
- zebra-day==3.5.2
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align zebra-day pin with project dependency contract

The new conda contract pins zebra-day==3.5.2, but the package metadata still requires zebra-day==4.0.0 in pyproject.toml. Because activation performs editable install with --no-deps, this mismatch is not corrected automatically, so fresh environments can run Bloom against an older zebra-day than the declared requirement, which risks runtime incompatibilities.

Useful? React with 👍 / 👎.

- daylily-carrier-tracking==0.5.1
20 changes: 10 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
# BLOOM LIMS Project Configuration
# =============================================================================
# ENVIRONMENT MANAGEMENT: This project uses CONDA for environment management.
# The conda environment is named "BLOOM" (all caps).
# The supported local entrypoint is `source ./activate <deploy-name>`.
# Activation creates a deployment-scoped conda environment named
# `BLOOM-<deploy-name>` from repo-root `environment.yaml`.
#
# To set up the environment:
# conda env create -f bloom_env.yaml
# conda activate BLOOM
# source ./activate <deploy-name>
#
# See bloom_env.yaml for the full list of dependencies.
# See environment.yaml for the full list of dependencies.
# =============================================================================

[build-system]
Expand Down Expand Up @@ -103,20 +104,19 @@ bloom_lims = ["etc/*.yaml"]
# Environment management method - DO NOT USE pip/poetry/venv for this project
environment_manager = "conda"

# The conda environment name (IMPORTANT: all caps)
conda_environment_name = "BLOOM"
# The deployment-scoped conda environment name pattern
conda_environment_name = "BLOOM-<deploy-name>"

# The conda environment definition file
conda_environment_file = "bloom_env.yaml"
conda_environment_file = "environment.yaml"

# Commands to set up the development environment
setup_commands = [
"conda env create -f bloom_env.yaml",
"conda activate BLOOM",
"source ./activate <deploy-name>",
]

# Command to run tests (must activate conda environment first)
test_command = "conda run -n BLOOM pytest"
test_command = "source ./activate <deploy-name> && pytest"

# =============================================================================
# Tool Configurations
Expand Down
1 change: 0 additions & 1 deletion requirements.txt

This file was deleted.

20 changes: 20 additions & 0 deletions tests/test_deploy_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parents[1]


def test_root_environment_contract_uses_environment_yaml() -> None:
assert (PROJECT_ROOT / "environment.yaml").is_file()
assert not (PROJECT_ROOT / "bloom_env.yaml").exists()
assert not (PROJECT_ROOT / "requirements.txt").exists()


def test_activate_only_references_root_environment_yaml() -> None:
activate = (PROJECT_ROOT / "activate").read_text(encoding="utf-8")
environment = (PROJECT_ROOT / "environment.yaml").read_text(encoding="utf-8")

assert "environment.yaml" in activate
assert "bloom_env.yaml" not in activate
assert "requirements.txt" not in activate
assert "pip install --no-deps -e" in activate
assert "-e ." not in environment
Loading