Skip to content

release: fix runtime module discovery failures#560

Merged
djm81 merged 452 commits into
mainfrom
dev
May 7, 2026
Merged

release: fix runtime module discovery failures#560
djm81 merged 452 commits into
mainfrom
dev

Conversation

@djm81
Copy link
Copy Markdown
Collaborator

@djm81 djm81 commented May 7, 2026

Summary

Fix runtime discovery failures reported in #552, #553, and #554 via the dedicated User Story #557.

  • Load active installed module src/ roots before lazy command app loading so installed marketplace modules can import dependency modules.
  • Preserve lazy-loader failure reasons and surface installed-but-unloadable modules as availability diagnostics instead of false "not installed" messages.
  • Improve environment-manager detection for rootless monorepos and add explicit specfact init ide --env-manager <auto|uv|hatch|poetry|pip>.
  • Add a CI runtime discovery smoke script that installs project/codebase/code-review modules from a local marketplace, checks upgrade command availability, validates init ide auto/uv behavior, and verifies specfact code, code review run, and code import command loading across direct, pip-editable, and uvx launchers.
  • Bump package version to 0.46.19 and bundled init/module-registry manifests for touched bundled module code.

Root Cause

Installed module command loading could resolve command metadata while still missing dependency module src roots at lazy-load time. The fallback diagnostics then treated the provider as absent, so users saw Module 'nold-ai/specfact-codebase' is not installed even when specfact module list showed it installed and enabled. Rootless monorepo environment detection also stopped too early when markers existed only below package directories.

Validation

  • OpenSpec: openspec validate runtime-01-discovery-reliability --strict
  • Unit/e2e targeted suites for module loading, availability diagnostics, env-manager detection, and init command behavior
  • Real-world smoke against sibling specfact-cli-modules and specfact-demo-repo
  • hatch run runtime-discovery-smoke --launcher direct
  • hatch run runtime-discovery-smoke --launcher pip-editable
  • hatch run runtime-discovery-smoke --launcher uvx
  • hatch run pytest tests/integration/scripts/test_runtime_discovery_smoke.py -q
  • hatch run check-version-sources
  • hatch run verify-modules-signature-pr
  • Pre-commit completed for commit 86feb9c2

Cross-Repo Companion

Companion modules PR: nold-ai/specfact-cli-modules#262.

While validating this branch, local specfact code review run exposed a separate specfact-code-review module defect: its Semgrep runner created a temp HOME and set XDG_CONFIG_HOME/XDG_CACHE_HOME inside it without creating those directories. The companion modules PR fixes that, bumps nold-ai/specfact-code-review to 0.47.15, and updates checksum-only integrity for CI signing.

Notes

Local specfact at /home/dom/.local/bin/specfact was still version 0.46.18 and reproduced the original bug. The patched worktree command (hatch run python -m specfact_cli.cli ...) successfully ran code review run, and the tightened smoke now covers code review run --help.

djm81 and others added 30 commits February 27, 2026 11:58
* feat(backlog): summarize Markdown normalization and TTY/CI rendering

* chore(openspec): drop implementation snapshot from change

* Update title

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
* feat(cli): category groups and flat shims using real module Typer

- Add category groups (code, backlog, project, spec, govern) with flatten same-name member
- Sort commands under backlog/project groups A–Z
- Fix flat shims to expose real module Typer so 'specfact sync bridge' and 'specfact plan update-idea' work
- Add first-run init, module grouping, OpenSpec change for 0.40.x remove-flat-shims
- Bump version to 0.39.0, CHANGELOG and OpenSpec updates

Made-with: Cursor

* Fix signature

* fix: resolve module grouping regressions and stabilize CI
  tests

* fix: keep uncategorized modules flat during grouped registration

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
* docs: add module-migration-02-bundle-extraction to CHANGE_ORDER.md

* feat: implement module-migration-02 bundle extraction

* fix(ci): checkout module bundles repo for test jobs

* Fix test failures

* fix(modules): load local bundle sources in compatibility aliases

* fix: run worktree policy code in tests/CI and silence reexport deprecation

- Prefer src/<name>/main.py over app.py when SPECFACT_REPO_ROOT is set so
  policy init uses worktree templates.py (SPECFACT_POLICY_TEMPLATES_DIR).
- Policy engine module-package.yaml: version 0.1.5 and re-signed checksum.
- conftest: set SPECFACT_REPO_ROOT, SPECFACT_POLICY_TEMPLATES_DIR; add
  bundle package roots when specfact-cli-modules present.
- Policy engine integration tests: rely on conftest env, clear registry
  and re-register before invoke so loader uses worktree.
- test_reexport_shims: filter deprecation warning for legacy analyze import.

Made-with: Cursor

* fix: defer specfact_backlog import in shims so CI can register bridges

- backlog and policy_engine __init__.py: import specfact_backlog only in
  __getattr__ (cached), not at module load. Allows loading .src.adapters.*
  for bridge registration without requiring specfact_backlog installed.
- Re-sign backlog and policy_engine module-package.yaml after init changes.
- openspec: update module-migration-02 tasks.md.

Made-with: Cursor

* fix: defer bundle import in all module shims to fix CI collection errors

- Apply deferred import (only in __getattr__, cached) to analyze, contract,
  drift, enforce, generate, import_cmd, migrate, patch_mode, plan, project,
  repro, sdd, spec, sync, validate. Matches backlog and policy_engine.
- Prevents ImportError when tests import specfact_cli.modules.<name>.src.*
  without specfact_backlog/specfact_govern/specfact_project/specfact_spec
  installed (e.g. CI). Fixes 78 collection errors.
- Re-sign all affected module-package.yaml manifests.

Made-with: Cursor

* fix(ci): include module shims in hatch cache key so CI uses current code

* feat(modules): registry descriptions, --bump-version for publish, tasks and format fixes

- Add description to registry index entries in publish-module.py (module search)
- Add --bump-version patch|minor|major for bundle re-publish in publish-module.py
- Format fixes in validate-modules-repo-sync.py (SIM108, B007)
- Mark completed tasks in module-migration-02-bundle-extraction tasks.md
- Update test for publish_bundle(bump_version=) signature

Made-with: Cursor

* Add missing migration tasks to the open change to completely isolate modules into specfact-cli-modules repo.

* Add gap analysis and update changes

* Update follow-up changes to avoid ambiguities and overlaps

* docs: complete migration-02 section-18 parity and 17.8 gate evidence

* docs: mark migration-02 import-categorization commit checkpoint done

* Update change constraints and blockers for module migration

* docs: add migration-05 issue #334 and complete task 17.10.4

* Update change constraints and blockers for module migration

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
…317) (#341)

* Prepare module-migration-03 removal of old built-in modules

* feat(core): delete specfact-project module source from core (migration-03)

Made-with: Cursor

* feat(core): delete specfact-backlog module source from core (migration-03)

Made-with: Cursor

* feat(core): delete specfact-codebase module source from core (migration-03)

Made-with: Cursor

* feat(core): delete specfact-spec module source from core (migration-03)

Made-with: Cursor

* feat(core): delete specfact-govern module source from core (migration-03)

Made-with: Cursor

* chore(tests): skip tests for removed modules when source absent (migration-03)

Add pytest.importorskip() for backlog, plan, sync, enforce, generate,
patch_mode, import_cmd so tests are skipped when module source was
removed from core. Preserves tests for later move to specfact-cli-modules.
Update tasks.md and TDD_EVIDENCE.md for Task 10 completion.

Made-with: Cursor

* feat(bootstrap): remove flat shims and non-core module registrations (migration-03)

- Remove _register_category_groups_and_shims (unconditional category/shim registration).
- Trim CORE_MODULE_ORDER to 4 core: init, auth, module-registry, upgrade.
- Add @beartype to _mount_installed_category_groups.
- Category groups and flat shims only for installed bundles via _mount_installed_category_groups.

Made-with: Cursor

* docs(openspec): mark Task 11.4 done in tasks.md

Made-with: Cursor

* feat(cli): conditional category group mount from installed bundles (migration-03)

- Add _RootCLIGroup (extends ProgressiveDisclosureGroup) with resolve_command
  override: unknown commands in KNOWN_BUNDLE_GROUP_OR_SHIM_NAMES show
  actionable error (not installed + specfact init / specfact module install).
- Root app uses cls=_RootCLIGroup. Main help docstring adds init/module
  install hint for workflow bundles.

Made-with: Cursor

* docs(openspec): mark Task 12.4 done in tasks.md

Made-with: Cursor

* feat(init): enforce mandatory bundle selection and profile presets (migration-03)

* Add module removal core tests

* docs(openspec): record Task 14 module signing gate (migration-03)

* feat: complete module-migration-03 core slimming and
  follow-up alignment (#317)

* Fix format error

* fix: handle detached HEAD registry branch selection and
  stabilize migration-03 CI tests

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
#317) (#343)

* Prepare module-migration-03 removal of old built-in modules

* feat(core): delete specfact-project module source from core (migration-03)

Made-with: Cursor

* feat(core): delete specfact-backlog module source from core (migration-03)

Made-with: Cursor

* feat(core): delete specfact-codebase module source from core (migration-03)

Made-with: Cursor

* feat(core): delete specfact-spec module source from core (migration-03)

Made-with: Cursor

* feat(core): delete specfact-govern module source from core (migration-03)

Made-with: Cursor

* chore(tests): skip tests for removed modules when source absent (migration-03)

Add pytest.importorskip() for backlog, plan, sync, enforce, generate,
patch_mode, import_cmd so tests are skipped when module source was
removed from core. Preserves tests for later move to specfact-cli-modules.
Update tasks.md and TDD_EVIDENCE.md for Task 10 completion.

Made-with: Cursor

* feat(bootstrap): remove flat shims and non-core module registrations (migration-03)

- Remove _register_category_groups_and_shims (unconditional category/shim registration).
- Trim CORE_MODULE_ORDER to 4 core: init, auth, module-registry, upgrade.
- Add @beartype to _mount_installed_category_groups.
- Category groups and flat shims only for installed bundles via _mount_installed_category_groups.

Made-with: Cursor

* docs(openspec): mark Task 11.4 done in tasks.md

Made-with: Cursor

* feat(cli): conditional category group mount from installed bundles (migration-03)

- Add _RootCLIGroup (extends ProgressiveDisclosureGroup) with resolve_command
  override: unknown commands in KNOWN_BUNDLE_GROUP_OR_SHIM_NAMES show
  actionable error (not installed + specfact init / specfact module install).
- Root app uses cls=_RootCLIGroup. Main help docstring adds init/module
  install hint for workflow bundles.

Made-with: Cursor

* docs(openspec): mark Task 12.4 done in tasks.md

Made-with: Cursor

* feat(init): enforce mandatory bundle selection and profile presets (migration-03)

* Add module removal core tests

* docs(openspec): record Task 14 module signing gate (migration-03)

* feat: complete module-migration-03 core slimming and
  follow-up alignment (#317)

* Fix format error

* fix: handle detached HEAD registry branch selection and
  stabilize migration-03 CI tests

* Prepare module-migration-03 removal of old built-in modules

* Prepare module-migration-03 removal of old built-in modules

* chore(tests): skip tests for removed modules when source absent (migration-03)

Add pytest.importorskip() for backlog, plan, sync, enforce, generate,
patch_mode, import_cmd so tests are skipped when module source was
removed from core. Preserves tests for later move to specfact-cli-modules.
Update tasks.md and TDD_EVIDENCE.md for Task 10 completion.

Made-with: Cursor

* feat(bootstrap): remove flat shims and non-core module registrations (migration-03)

- Remove _register_category_groups_and_shims (unconditional category/shim registration).
- Trim CORE_MODULE_ORDER to 4 core: init, auth, module-registry, upgrade.
- Add @beartype to _mount_installed_category_groups.
- Category groups and flat shims only for installed bundles via _mount_installed_category_groups.

Made-with: Cursor

* docs(openspec): mark Task 11.4 done in tasks.md

Made-with: Cursor

* feat(cli): conditional category group mount from installed bundles (migration-03)

- Add _RootCLIGroup (extends ProgressiveDisclosureGroup) with resolve_command
  override: unknown commands in KNOWN_BUNDLE_GROUP_OR_SHIM_NAMES show
  actionable error (not installed + specfact init / specfact module install).
- Root app uses cls=_RootCLIGroup. Main help docstring adds init/module
  install hint for workflow bundles.

Made-with: Cursor

* docs(openspec): mark Task 12.4 done in tasks.md

Made-with: Cursor

* feat(init): enforce mandatory bundle selection and profile presets (migration-03)

* Add module removal core tests

* docs(openspec): record Task 14 module signing gate (migration-03)

* feat: complete module-migration-03 core slimming and
  follow-up alignment (#317)

* Fix format error

* fix: handle detached HEAD registry branch selection and
  stabilize migration-03 CI tests

* feat(core): remove auth module from core and route auth via backlog (migration-03)

* docs(openspec): update migration-03 PR status and tracking

* docs(openspec): finalize migration-03 checklist and defer non-blocking gates

* Fix remaining auth findings and dependency in core cli

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
* feat: remove flat command shims from grouped registry

* Finalize change module-migration-04 implementation

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
…R merge (#345)

* Implement blockers to prepare for module-migration-03 change.

* Update migration change

* docs(openspec): close migration-05 PR tracking and change order

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
* feat(migration-06): core decoupling cleanup - boundary tests and inventory

- Add test_core_does_not_import_from_bundle_packages boundary regression test
- Update spec with ownership boundary and migration acceptance criteria
- Add CORE_DECOUPLING_INVENTORY.md (keep/move/interface classification)
- Record TDD evidence in TDD_EVIDENCE.md
- Update docs/reference/architecture.md with core vs modules-repo boundary
- Update openspec/CHANGE_ORDER.md status

No move candidates identified; core already decoupled from bundle packages.
Boundary test prevents future core->bundle coupling.

Refs #338

Made-with: Cursor

* chore(migration-06): mark all tasks complete

Made-with: Cursor

* feat(migration-06): extend scope - migrate package-specific artifacts per #338

- Add MIGRATION_REMOVAL_PLAN.md with phased removal of MIGRATE-tier code
- Add test_core_modules_do_not_import_migrate_tier boundary test
- Remove templates.bridge_templates (dead code; only tests used it)
- Remove tests/unit/templates/test_bridge_templates.py
- Update CORE_DECOUPLING_INVENTORY.md with removal status
- Update spec with MIGRATE-tier enforcement and package-specific removal

Phase 1 complete. Further MIGRATE-tier removal documented in plan.
Refs #338

Made-with: Cursor

* test(migration-06): move legacy sync tests out of core

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
* test: finalize module-migration-07 core test ownership cleanup

* docs: mark module-migration-07 quality and PR tasks complete

* test: fix CI isolation failures for project and persona merge

* test: narrow migrated skips and restore core registry guardrails

* test: stabilize core CI by refining skips and bootstrap checks

* test: fix remaining PR failures via targeted core filtering

* fix: harden module package checks against import-mode class identity

* test: stabilize core slimming integration assertions

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
djm81 and others added 14 commits May 3, 2026 23:37
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
…551)

* chore(openspec): park 21 deferred change proposals

Move proposals that are awaiting external signal (paying enterprise customer,
third-party publisher, evidence corpus, etc.) from openspec/changes/ into
a new openspec/parking-lot/ directory, preserving full content and history.

This restores focus on the active core thesis (full-chain traceability for
agile DevOps + AI IDEs) without abandoning prior thinking. Each parked
proposal has an explicit un-park trigger documented in
openspec/parking-lot/README.md.

Parked groups:
- enterprise-01..04 (4): no paying enterprise customer yet
- finops-01..02 (2): no internal LLM workload to optimise yet
- knowledge-01..02 (2): insufficient evidence corpus for distillation
- marketplace-03..06 (4): no third-party publishers to onboard
- security-01..02 (2): no customer-driven security review demand
- review-resiliency-01-contracts (1): code-review module gap unproven
- profile-02..03 (2): profile-01 not yet shipped
- cli-val-01,02,05,06 (4): infrastructure ahead of demand;
  cli-val-03 and cli-val-04 remain active

Active changes drop from 45 to 24. No CI workflows or production code
referenced the parked directories; only comment-level references remain
in already-shipped marketplace-06 helper scripts. openspec list is clean.

Also adds a missing fenced-code language tag to a parked design.md
to satisfy the markdownlint pre-commit hook.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(openspec): rewrite CHANGE_ORDER.md to reflect parked roadmap

Reduce from 647 to 214 lines and reorganise around five active tracks
instead of ten plan-derived addenda. The previous file accumulated
historical narrative ("plan-derived addendum 2026-02-15", "addendum
2026-03-22", etc.) that belonged in git history, and listed many
changes that no longer exist as folders here (moved to modules repo
or already archived).

New structure:
- Status snapshot: 24 active / 21 parked / 104 archived with paths
- Five active tracks (full-chain, AI IDE, profile, CLI reliability, other)
- Modify queue: explicit list of proposals needing scope adjustment
  before implementation begins
- Five waves (1: adjust scope, 2: foundations, 3: chain assembly,
  4: evidence + AI surface, 5: proof + extensions) with auditable
  exit gates
- Ownership authority table (kept; still load-bearing)
- Pointers to parking-lot, archive, and the modules-repo companion plan

Stale content removed: old "Implemented" table (51 archived items
already in changes/archive/), four separate addendum sections, tables
for backlog-scrum/kanban/safe that just said "moved to modules", a
GitHub blocked-by relationships table that duplicated each track's
own Blocked-by column, and references to changes that don't exist as
active folders.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(openspec): fix Modify queue count "Five" -> "Six"

PR #551 review caught the prose/table mismatch: the Modify queue
intro said "Five active changes" but the table lists six
(integration-01, architecture-02, telemetry-01, ai-integration-02,
ai-integration-04, openspec-01). The table is the canonical list;
all six adjustments are still required before implementation.

Other count wording verified consistent:
- "five independent tracks" (line 28) refers to Tracks A-E - correct.
- Wave 1 references in the wave plan name the queue by reference,
  not by count.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(openspec): archive marketplace-06 (incorrectly parked, already shipped)

Re-validation of parked changes against git history found that
marketplace-06-ci-module-signing was substantially implemented in dev
(PRs #501, #503, #504, #505 + commit a1dda6d) before the 2026-05-05
parking triage, but its tasks.md still read 0/N done so it was placed
in parking-lot/ by mistake.

Move the change to openspec/changes/archive/2026-05-06-marketplace-06-ci-module-signing/,
mark all tasks [x] in bulk, and add an "Implementation history" banner
documenting the actual merging PRs and verified on-disk deliverables
(sign-modules-on-approval.yml, git-branch-module-signature-flag.sh,
branch-aware verify-module-signatures gating).

Update parking-lot/README.md (remove marketplace-06 row) and
CHANGE_ORDER.md status snapshot (parked 21 -> 20, archived 104 -> 105).

All 20 other core parked changes and all 9 modules-side parked changes
were re-validated and have no implementation traces; they remain
correctly parked.

* fix(openspec): sync specs from archived marketplace-06 via openspec archive

The previous commit (8443297) moved marketplace-06-ci-module-signing
into the archive directory manually, which skipped the
`openspec archive` step that syncs delta specs into main specs.

Re-ran the proper flow:
1. Move change back to openspec/changes/marketplace-06-ci-module-signing/
2. Run `openspec archive marketplace-06-ci-module-signing --yes`

That command applied the delta specs to:
- openspec/specs/ci-integration/spec.md (3 added)
- openspec/specs/ci-module-signing-on-approval/spec.md (3 added, new file)

Net effect on this PR is the proper inclusion of those spec updates;
the archive folder content from 8443297 is unchanged (banner +
checked tasks preserved).

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* Refine telemetry change to active opt-in

* Address telemetry opt-in review annotations

* Align telemetry payload field names

* Clarify telemetry semantic payload contract

* Align telemetry sanitizer transition spec

* Track modules telemetry docs rollout

* Tighten telemetry implementation tasks

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
* fix runtime module discovery reliability

* fix runtime discovery review findings

* fix installed module loader test fixture

* fix review feedback on runtime discovery state isolation

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 23da1564-916a-4175-8235-51739d999059

📥 Commits

Reviewing files that changed from the base of the PR and between ba94402 and fab4fa6.

📒 Files selected for processing (31)
  • .github/workflows/pr-orchestrator.yml
  • CHANGELOG.md
  • openspec/CHANGE_ORDER.md
  • openspec/changes/runtime-01-discovery-reliability/.openspec.yaml
  • openspec/changes/runtime-01-discovery-reliability/TDD_EVIDENCE.md
  • openspec/changes/runtime-01-discovery-reliability/proposal.md
  • openspec/changes/runtime-01-discovery-reliability/specs/environment-manager-detection/spec.md
  • openspec/changes/runtime-01-discovery-reliability/specs/installed-runtime-module-discovery/spec.md
  • openspec/changes/runtime-01-discovery-reliability/specs/module-installation/spec.md
  • openspec/changes/runtime-01-discovery-reliability/specs/module-owned-ide-prompts/spec.md
  • openspec/changes/runtime-01-discovery-reliability/tasks.md
  • pyproject.toml
  • scripts/runtime_discovery_smoke.py
  • setup.py
  • src/__init__.py
  • src/specfact_cli/__init__.py
  • src/specfact_cli/cli.py
  • src/specfact_cli/modules/init/module-package.yaml
  • src/specfact_cli/modules/init/src/commands.py
  • src/specfact_cli/modules/module_registry/module-package.yaml
  • src/specfact_cli/modules/module_registry/src/commands.py
  • src/specfact_cli/registry/module_availability.py
  • src/specfact_cli/registry/module_packages.py
  • src/specfact_cli/utils/env_manager.py
  • src/specfact_cli/utils/ide_setup.py
  • tests/e2e/test_init_command.py
  • tests/integration/scripts/test_runtime_discovery_smoke.py
  • tests/unit/specfact_cli/registry/test_module_availability.py
  • tests/unit/specfact_cli/registry/test_module_packages.py
  • tests/unit/utils/test_env_manager.py
  • tests/unit/utils/test_ide_setup.py

📝 Walkthrough

Walkthrough

This PR implements runtime module discovery reliability for SpecFact CLI. It adds sys.path prepending for installed module src roots, per-module load-failure tracking and diagnostics, environment-manager detection for rootless monorepos with PATH fallback, a new --env-manager CLI option for init ide, a comprehensive smoke test across multiple launchers, and corresponding test coverage spanning unit, integration, and e2e layers.

Changes

Runtime Discovery Reliability

Layer / File(s) Summary
Specification & Requirements
openspec/CHANGE_ORDER.md, openspec/changes/runtime-01-discovery-reliability/*
OpenSpec documents define problem statement (installed-module runtime discovery gaps), proposed solutions (sys.path prepending, load-failure diagnostics, monorepo env detection, --env-manager option), and acceptance criteria.
Module Load Failure Tracking
src/specfact_cli/registry/module_packages.py
New _ACTIVE_MODULE_SRC_DIRS and _MODULE_LOAD_FAILURES state tracking; helpers for path containment, site-package detection, SpecFact-managed package classification; sys.path prepending before command load; exception recording into load-failure cache; exported clear_module_load_failures() and get_module_load_failure_reason() APIs.
Availability Classification & Resolution
src/specfact_cli/registry/module_availability.py, src/specfact_cli/cli.py
_skip_reason() now queries load-failure cache; classify_module_availability() docstring updated to reflect incorporation of lazy-load diagnostics. Command resolver catches ValueError alongside UsageError for missing-bundle guidance.
Environment Manager Detection
src/specfact_cli/utils/env_manager.py
EnvManager enum extended with AUTO option. Detection priority: pyproject.toml markers → lock markers → monorepo-aware subdirectory scanning → PATH fallback (uv before pip). New helpers: _env_info_for_available_tool(), _env_info_from_lock_markers(), _iter_monorepo_candidate_dirs(), _env_info_from_monorepo_markers(), _env_info_from_path_fallback().
init ide Command Enhancement
src/specfact_cli/modules/init/src/commands.py, src/specfact_cli/utils/ide_setup.py
init_ide gains --env-manager option (defaults to AUTO); routes to auto-detection or explicit validation; exits early if override unavailable; passes resolved manager to write_ide_prompt_export_state(). IDE state persistence extended to include optional env_manager parameter.
Workspace Safety
src/specfact_cli/modules/module_registry/src/commands.py
_normalize_project_repo() treats system temp directory as workspace boundary, preventing false positive discovery.
Smoke Test Infrastructure
scripts/runtime_discovery_smoke.py, pyproject.toml
New smoke script validates runtime discovery across launchers (direct, pip-editable, uvx); builds local registry; creates rootless monorepo demo; installs modules; tests module list, init ide (default and with --env-manager uv), code command loading; asserts absence of incompatible-manager warnings. Hatch script entry added.
End-to-End Tests
tests/e2e/test_init_command.py
New tests verify environment manager warning suppression with explicit --env-manager uv override and rootless monorepo uv detection.
Integration Tests
tests/integration/scripts/test_runtime_discovery_smoke.py
New module validates smoke script execution, workspace preservation with --keep-workspace, per-launcher demo isolation, and sys.path correctness.
Unit Tests
tests/unit/specfact_cli/registry/test_module_packages.py, test_module_availability.py, tests/unit/utils/test_env_manager.py, test_ide_setup.py
Extensive coverage: lazy loader failure tracking, active module src recording, distribution-metadata detection, stale src-root cleanup; environment manager PATH fallback and monorepo scenarios; IDE state persistence with env_manager.
Release Metadata
pyproject.toml, setup.py, src/__init__.py, src/specfact_cli/__init__.py, src/specfact_cli/modules/init/module-package.yaml, src/specfact_cli/modules/module_registry/module-package.yaml
Version bumped to 0.46.19; init module 0.1.31 → 0.1.33; module_registry 0.1.23 → 0.1.24; integrity checksums updated.
CI & Documentation
.github/workflows/pr-orchestrator.yml, CHANGELOG.md
GitHub Actions workflow adds runtime discovery smoke test step. CHANGELOG documents v0.46.19 release notes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

  • nold-ai/specfact-cli#535: Both modify module availability/discovery stack (module_availability.py, module_packages.py) for improved missing-command diagnostics.
  • nold-ai/specfact-cli#541: Both modify CLI command-loading and module discovery/registry code (cli.py, registry modules) for installed module root handling.
  • nold-ai/specfact-cli#558: Overlapping code-level changes to runtime discovery, load-failure APIs, sys.path handling, environment-manager detection, --env-manager option, and package versioning.

Suggested labels

QA

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Comment @coderabbitai help to get the list of available commands and usage tips.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@djm81 djm81 merged commit 1a0e264 into main May 7, 2026
6 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in SpecFact CLI May 7, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 469af4600a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +240 to +243
for manager in (EnvManager.UV, EnvManager.PIP):
executable = "pip" if manager is EnvManager.PIP else manager.value
if shutil.which(executable) is not None:
return _env_info_for_available_tool(manager, f"Detected {executable} in PATH")
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 Keep markerless repos on direct fallback

Do not auto-select uv purely because it is on PATH for repositories with no environment markers. This new fallback changes detect_env_manager() from UNKNOWN to UV in markerless repos, which makes downstream flows execute uv-specific logic (for example validators/sidecar/dependency_installer.install_dependencies() now takes the UV branch and returns failure when no requirements.txt/pyproject.toml exists). In practice, any machine with global uv installed can now fail sidecar/repro setup for non-uv projects that previously worked with direct invocation.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working dependencies Dependency resolution and management

Projects

Status: Done

1 participant