Skip to content

fix: post-PR-217 review findings and lazy module registration#218

Merged
djm81 merged 92 commits intomainfrom
dev
Feb 10, 2026
Merged

fix: post-PR-217 review findings and lazy module registration#218
djm81 merged 92 commits intomainfrom
dev

Conversation

@djm81
Copy link
Copy Markdown
Collaborator

@djm81 djm81 commented Feb 10, 2026

Summary

  • fix CodeQL findings from PR 217 (unreachable return, unnecessary lambdas, unused module contract aliases)
  • remove unused _MODULE_IO_CONTRACT aliases in flagged module command files
  • restore lazy module registration by switching protocol compliance detection to static source inspection (no eager module imports at CLI startup)
  • bump version to 0.30.1 and add changelog entry

Validation

  • hatch run pytest -q tests/unit/test_core_module_isolation.py tests/unit/registry/test_module_bridge_registration.py tests/unit/specfact_cli/registry/test_module_packages.py
  • hatch run ruff check tests/unit/test_core_module_isolation.py tests/unit/registry/test_module_bridge_registration.py tests/unit/specfact_cli/registry/test_module_packages.py src/specfact_cli/registry/module_packages.py src/specfact_cli/modules/backlog/src/commands.py src/specfact_cli/modules/enforce/src/commands.py src/specfact_cli/modules/generate/src/commands.py src/specfact_cli/modules/migrate/src/commands.py src/specfact_cli/modules/plan/src/commands.py src/specfact_cli/modules/spec/src/commands.py src/specfact_cli/modules/sync/src/commands.py

Notes

  • This PR is intentionally dev -> main per release flow and includes only post-merge fixes for PR 217 plus the lazy-loading regression fix reported by Codex review.

djm81 and others added 30 commits January 27, 2026 01:27
…command (#142)

* feat: implement backlog field mapping and refinement improvements

- Add FieldMapper abstract base class with canonical field names
- Implement GitHubFieldMapper and AdoFieldMapper
- Add custom field mapping support with YAML templates
- Add field validation in refinement (story_points, business_value, priority)
- Add comprehensive unit and integration tests (42 tests)
- Add custom field mapping documentation
- Fix custom_field_mapping parameter connection
- Add early validation for custom mapping files

Implements OpenSpec change: improve-backlog-field-mapping-and-refinement

* perf: optimize startup performance with metadata tracking and update command

- Add metadata management module for tracking version and check timestamps
- Optimize startup checks to only run when needed:
  - Template checks: Only after version changes detected
  - Version checks: Limited to once per day (24h threshold)
- Add --skip-checks flag for CI/CD environments
- Add new 'specfact update' command for manual update checking and installation
- Add comprehensive unit and integration tests (35 tests, all passing)
- Update startup_checks to use metadata for conditional execution
- Ensure backward compatibility (first-time users still get all checks)

Performance Impact:
- Startup time: Reduced from several seconds to < 1-2 seconds
- Network requests: Reduced from every startup to once per day
- File system operations: Reduced from every startup to only after version changes

Fixes #140
Implements OpenSpec change: optimize-startup-performance

* feat: request offline_access scope for Azure DevOps refresh tokens

- Add offline_access scope to Azure DevOps OAuth requests
- Refresh tokens now last 90 days (vs 1 hour for access tokens)
- Automatic token refresh via persistent cache (no re-authentication needed)
- Update documentation to reflect 90-day refresh token lifetime

This addresses the issue where tokens were expiring too quickly.
Refresh tokens obtained via offline_access scope enable automatic
token renewal for 90 days without user interaction.

Fixes token lifetime limitation issue

* feat: improve CLI UX with banner control and upgrade command

- Change banner to hidden by default, shown on first run or with --banner flag
- Add simple version line (SpecFact CLI - vXYZ) for regular use
- Rename 'update' command to 'upgrade' to avoid confusion
- Update documentation for new banner behavior and upgrade command
- Update startup checks message to reference 'specfact upgrade'

* fix: suppress version line in test mode and fix field mapping issues

- Suppress version line output in test mode and for help/version commands to prevent test failures
- Fix ADO custom field mapping to honor --custom-field-mapping on writeback
- Fix GitHub issue body updates to prevent duplicate sections
- Ensure proper type handling for story points and business value calculations

* Fix failed tests

* chore: bump version to 0.26.7 and update changelog

- Fixed adapter token validation tests (ADO and GitHub)
- Resolved test timeout issues (commit history, AST parsing, Semgrep)
- Improved test file discovery to exclude virtual environments
- Added file size limits for AST parsing to prevent timeouts

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
* fix: add missing ADO field mappings and assignee display

- Add Microsoft.VSTS.Common.AcceptanceCriteria to default field mappings
- Update AdoFieldMapper to support multiple field name alternatives
- Fix assignee extraction to include displayName, uniqueName, and mail
- Add assignee display in preview output
- Add interactive template mapping command (specfact backlog map-fields)
- Update specfact init to copy backlog field mapping templates
- Extend documentation with step-by-step guides

Fixes #144

* test: add unit tests for ADO field mapping and assignee fixes

- Add tests for Microsoft.VSTS.Common.AcceptanceCriteria field extraction
- Add tests for multiple field name alternatives
- Add tests for assignee extraction with displayName, uniqueName, mail
- Add tests for assignee filtering with multiple identifiers
- Add tests for assignee display in preview output
- Add tests for interactive mapping command
- Add tests for template copying in init command
- Update existing tests to match new assignee extraction behavior

* docs: update init command docstring to mention template copying

* docs: update documentation for ADO field mapping and interactive mapping features

- Update authentication guide with ADO token resolution priority
- Update custom field mapping guide with interactive mapping details
- Update backlog refinement guide with progress indicators and required field display
- Update Azure DevOps adapter guide with field mapping improvements
- Update command reference with map-fields command documentation
- Update troubleshooting guide with ADO-specific issues
- Update README files with new features
- Update getting started guide with template initialization

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: address review findings for ADO field mapping

- Prefer System.* fields over Microsoft.VSTS.Common.* when writing updates
  (fixes issue where PATCH requests could fail for Scrum templates)
- Preserve existing work_item_type_mappings when saving field mappings
  (prevents silent erasure of custom work item type mappings)

Fixes review comments:
- P1: Prefer System.AcceptanceCriteria when writing updates
- P2: Preserve existing work_item_type_mappings on save

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: mitigate code scanning vulnerabilities

- Fix ReDoS vulnerability in github_mapper.py by replacing regex with line-by-line processing
- Fix incomplete URL sanitization in github.py, bridge_sync.py, and ado.py using proper URL parsing
- Add explicit permissions blocks to 7 GitHub Actions jobs following least-privilege model

Resolves all 13 code scanning findings:
- 1 ReDoS error
- 5 URL sanitization warnings
- 7 missing workflow permissions warnings

Fixes #147

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: accept GitHub SSH host aliases in repo detection

Accept ssh.github.com (port 443) in addition to github.com when
detecting GitHub repositories via SSH remotes. This ensures
repositories using git@ssh.github.com:owner/repo.git are properly
detected as GitHub repos.

Addresses review feedback on PR #148

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: prevent async cleanup issues in test mode

Remove manual Live display cleanup that could cause EOFError.
The _safe_progress_display function already handles test mode
by skipping progress display, so direct save path is sufficient.

Fixes test_unlock_section failure with EOFError/ValueError.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Extend URL pattern matching to support ssh://git@github.com/owner/repo.git
and git://github.com/owner/repo.git formats in addition to existing
https?:// and scp-style git@host:path URLs.

This fixes a regression where these valid GitHub URL formats were not
detected, causing detect() to return false for repos using these schemes.

Addresses review feedback on PR #149

Co-authored-by: Cursor <cursoragent@cursor.com>
- Update version from 0.26.8 to 0.26.9
- Add changelog entry for GitHub remote detection fix and code scanning fixes

Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Lowercase host_part before comparison to handle mixed-case hostnames
like git@GitHub.com:org/repo.git. This restores the case-insensitive
behavior from the previous config_content.lower() check and prevents
regression where valid GitHub repos with mixed-case hostnames would
not be detected.

Addresses review feedback on PR #150

Co-authored-by: Cursor <cursoragent@cursor.com>
- Sync version across pyproject.toml, setup.py, src/__init__.py, src/specfact_cli/__init__.py
- Add CHANGELOG entry for 0.26.10 (fixes incorrect version publish issue)

Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
…156)

* feat(backlog): implement --import-from-tmp for refine export/import round-trip

- Add _parse_refined_export_markdown() to parse export-format markdown (ID, Body, Acceptance Criteria, optional title/metrics)
- Import branch: read file, match by ID, update items; --write calls adapter.update_backlog_item()
- Remove 'Import functionality pending implementation' message
- Unit tests for parser (single item, AC/metrics, header-only, blocks without ID)
- Bump version to 0.26.11 and sync across pyproject.toml, setup.py, src/__init__.py, src/specfact_cli/__init__.py
- OpenSpec change: implement-backlog-refine-import-from-tmp (proposal, tasks, spec delta)

Fixes #155

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix type check issues

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
* feat: add debug logs under ~/.specfact/logs with operation metadata

- User-level log dir: get_specfact_home_logs_dir() (~/.specfact/logs, 0o755)
- debug_print() routes to console and rotating specfact-debug.log when --debug
- debug_log_operation() for structured metadata (ADO, GitHub, backlog, init)
- CLI init_debug_log_file() when --debug; help text updated

Closes #158
OpenSpec change: add-debug-logs-specfact-home

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add debug logging for selected commands at first

* release: 0.26.13 - debug log parity for upgrade, versions and changelog

- Log upgrade success (up to date) to ~/.specfact/logs/specfact-debug.log
- Bump version to 0.26.13; sync pyproject.toml, setup.py, src/__init__.py, specfact_cli/__init__.py
- CHANGELOG: 0.26.13 Fixed entry for upgrade debug parity

Co-authored-by: Cursor <cursoragent@cursor.com>

* Remove pr markdown

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
@djm81 djm81 linked an issue Feb 10, 2026 that may be closed by this pull request
@github-actions
Copy link
Copy Markdown
Contributor

SpecFact CLI Validation Report

All validations passed!
Duration: 17.77s
Checks: 4 total (2 passed) (2 skipped)

@djm81 djm81 moved this from Todo to Done in SpecFact CLI Feb 10, 2026
@djm81 djm81 added bug Something isn't working enhancement New feature or request module-system Module system and registry labels Feb 10, 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: 5075d0ce80

ℹ️ 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 thread src/specfact_cli/registry/module_packages.py Outdated
@djm81
Copy link
Copy Markdown
Collaborator Author

djm81 commented Feb 10, 2026

Added follow-up fix for the release blocker test failure.

  • fix: refresh project console per invocation in tests (31e6924)
  • Root cause: lazy module import could bind module-level Rich Console() to a CliRunner capture stream that is closed after invoke, causing ValueError: I/O operation on closed file on later invocations.
  • Fix: in src/specfact_cli/modules/project/src/commands.py, refresh console via get_configured_console() per command invocation and for bundle load/save progress helpers.

Validation:

  • hatch run pytest -q tests/unit/commands/test_project_cmd.py::TestProjectImport::test_import_dry_run_validation -vv
  • repeated run x8 of the same test
  • hatch run pytest -q tests/unit/commands/test_project_cmd.py -q
  • hatch run ruff check src/specfact_cli/modules/project/src/commands.py tests/unit/commands/test_project_cmd.py

@github-actions
Copy link
Copy Markdown
Contributor

SpecFact CLI Validation Report

All validations passed!
Duration: 17.93s
Checks: 4 total (2 passed) (2 skipped)

@djm81
Copy link
Copy Markdown
Collaborator Author

djm81 commented Feb 10, 2026

@cursoragent review this PR

@cursor
Copy link
Copy Markdown

cursor bot commented Feb 10, 2026

I’ve reviewed the startup docs (README.md, AGENTS.md, docs/README.md, CLAUDE.md) plus the testing/build guide. There isn’t an explicit plan referenced in README.md, but the current emphasis appears to be the module lifecycle system (lazy-loaded registry), contract-first validation, and keeping core/module boundaries strict while maintaining compatibility shims. The docs also stress contract-first testing and strict quality gates.

Please confirm you want me to proceed with the PR review based on the GitHub context you provided.

Applied rulesets: .cursorrules, session_startup_instructions.mdc, testing-and-build-guide.mdc, AGENTS.md, CLAUDE.md, spec-fact-cli-rules.mdc, clean-code-principles.mdc, automatic-openspec-workflow.mdc, estimation-bias-prevention.mdc.
LLM: OpenAI GPT-5.2-codex-high.

Open in Cursor Open in Web

@djm81
Copy link
Copy Markdown
Collaborator Author

djm81 commented Feb 10, 2026

Addressed the new Codex P2 finding about runtime-interface protocol detection.

Included in commit d7ca6af:

  • Extended static protocol scan in src/specfact_cli/registry/module_packages.py to inspect interface bindings (runtime_interface, commands_interface, commands).
  • Scanner now derives protocol operations from class-based interface objects declared in source (including runtime_interface = RuntimeInterface() and runtime_interface = interface_impl where interface_impl is an instance of a locally-defined class).
  • Kept lazy-registration behavior (no eager module imports).

Added regression coverage in tests/unit/specfact_cli/registry/test_module_packages.py:

  • test_protocol_source_scan_detects_runtime_interface_class_instance
  • test_protocol_source_scan_detects_runtime_interface_assigned_via_name

Validation:

  • hatch run pytest -q tests/unit/specfact_cli/registry/test_module_packages.py tests/unit/registry/test_module_bridge_registration.py tests/unit/test_core_module_isolation.py
  • hatch run ruff check src/specfact_cli/registry/module_packages.py tests/unit/specfact_cli/registry/test_module_packages.py

@github-actions
Copy link
Copy Markdown
Contributor

SpecFact CLI Validation Report

All validations passed!
Duration: 17.32s
Checks: 4 total (2 passed) (2 skipped)

@djm81
Copy link
Copy Markdown
Collaborator Author

djm81 commented Feb 10, 2026

Addressed the two additional P2 findings from CursorAgent.

Included in commit 0e5463f:

  1. Project console refresh is now systemic
  • Added group-level callbacks in src/specfact_cli/modules/project/src/commands.py:
    • @app.callback()
    • @version_app.callback()
  • Both callbacks call _refresh_console() so every project subcommand refreshes console streams before execution.
  • Existing explicit refresh calls in export/import and load/save helpers remain safe.
  1. Protocol static scan now inspects app entrypoint too
  • Replaced single-path resolver with _resolve_protocol_source_paths() in src/specfact_cli/registry/module_packages.py.
  • Static compliance scan now aggregates symbols across:
    • src/commands.py
    • src/<package>/commands.py
    • resolved app entrypoint (src/app.py / src/<package>.py / src/<package>/__init__.py)
  • This fixes under-reporting when runtime_interface is defined outside commands.py.

Regression tests added/updated

  • tests/unit/commands/test_project_cmd.py
    • test_list_locks_refreshes_console_when_module_console_is_closed
  • tests/unit/specfact_cli/registry/test_module_packages.py
    • test_protocol_source_scan_detects_runtime_interface_from_app_py_when_commands_exists

Validation

  • hatch run pytest -q tests/unit/commands/test_project_cmd.py::TestProjectLocks::test_list_locks_refreshes_console_when_module_console_is_closed tests/unit/specfact_cli/registry/test_module_packages.py::test_protocol_source_scan_detects_runtime_interface_from_app_py_when_commands_exists tests/unit/specfact_cli/registry/test_module_packages.py::test_protocol_source_scan_detects_runtime_interface_class_instance tests/unit/specfact_cli/registry/test_module_packages.py::test_protocol_source_scan_detects_runtime_interface_assigned_via_name -vv
  • hatch run pytest -q tests/unit/specfact_cli/registry/test_module_packages.py tests/unit/commands/test_project_cmd.py -q
  • hatch run ruff check src/specfact_cli/modules/project/src/commands.py src/specfact_cli/registry/module_packages.py tests/unit/commands/test_project_cmd.py tests/unit/specfact_cli/registry/test_module_packages.py

@github-actions
Copy link
Copy Markdown
Contributor

SpecFact CLI Validation Report

All validations passed!
Duration: 17.75s
Checks: 4 total (2 passed) (2 skipped)

@djm81
Copy link
Copy Markdown
Collaborator Author

djm81 commented Feb 10, 2026

Addressed the additional closed-stream failure reported in tests/integration/analyzers/test_analyze_command.py::TestAnalyzeCommand::test_code2spec_basic_repository.

Included in commit 57c729b:

  • Added import command group console refresh in src/specfact_cli/modules/import_cmd/src/commands.py:
    • _refresh_console() helper
    • @app.callback() (_import_callback) to refresh per invocation
  • This prevents stale module-level Rich console instances from retaining closed CliRunner capture streams across invocations.

Added regression coverage:

  • tests/integration/analyzers/test_analyze_command.py
    • test_code2spec_basic_repository_with_closed_import_console
    • Simulates a closed module-level console stream before runner.invoke(...); command now succeeds.

Validation:

  • hatch run pytest -q tests/integration/analyzers/test_analyze_command.py::TestAnalyzeCommand::test_code2spec_basic_repository tests/integration/analyzers/test_analyze_command.py::TestAnalyzeCommand::test_code2spec_basic_repository_with_closed_import_console -vv
  • hatch run pytest -q tests/integration/analyzers/test_analyze_command.py -q
  • hatch run ruff check src/specfact_cli/modules/import_cmd/src/commands.py tests/integration/analyzers/test_analyze_command.py

@github-actions
Copy link
Copy Markdown
Contributor

SpecFact CLI Validation Report

All validations passed!
Duration: 17.65s
Checks: 4 total (2 passed) (2 skipped)

@djm81 djm81 moved this from Done to In Progress in SpecFact CLI Feb 10, 2026
@github-actions
Copy link
Copy Markdown
Contributor

SpecFact CLI Validation Report

All validations passed!
Duration: 17.69s
Checks: 4 total (2 passed) (2 skipped)

@github-actions
Copy link
Copy Markdown
Contributor

SpecFact CLI Validation Report

All validations passed!
Duration: 18.15s
Checks: 4 total (2 passed) (2 skipped)

@djm81 djm81 merged commit 7b1b812 into main Feb 10, 2026
29 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in SpecFact CLI Feb 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request module-system Module system and registry

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Bridge Registry for Cross-Module Service Interoperability Core Contracts and Module Interface Formalization

1 participant