Skip to content

fix: safe VS Code settings merge and project artifact writes (#490)#496

Merged
djm81 merged 12 commits intodevfrom
bugfix/profile-04-safe-project-artifact-writes
Apr 12, 2026
Merged

fix: safe VS Code settings merge and project artifact writes (#490)#496
djm81 merged 12 commits intodevfrom
bugfix/profile-04-safe-project-artifact-writes

Conversation

@djm81
Copy link
Copy Markdown
Collaborator

@djm81 djm81 commented Apr 12, 2026

Description

This change implements the safe project artifact write policy for specfact init ide (and related paths) so .vscode/settings.json is merged instead of overwritten: SpecFact-managed chat/prompt recommendations are applied while unrelated user settings are preserved. Malformed JSON fails safely unless --force is used (with backup under .specfact/recovery/). A CI/static guard (scripts/verify_safe_project_writes.py, wired into hatch run lint) rejects direct unsafe writes to protected paths in init/setup code.

Semgrep started failing when setuptools 82+ dropped pkg_resources; this PR pins setuptools>=69.0.0,<82 in Hatch/dev deps so the code review and lint stack keep working.

OpenSpec: profile-04-safe-project-artifact-writes. Paired modules adoption remains tracked as project-runtime-01-safe-artifact-write-policy (see #490).

Fixes #487

Closes #490

Contract References

  • specfact_cli.utils.project_artifact_write: merge_vscode_settings_prompt_recommendations, backup_file_to_recovery, create_vscode_settings@require / @ensure with contract_predicates.repo_path_exists, repo_path_is_dir, file_path_is_file, settings_relative_nonblank, prompt_files_all_strings.
  • specfact_cli.utils.contract_predicates: settings_relative_nonblank, prompt_files_all_strings (new).
  • scripts/verify_safe_project_writes.py: main() with layout precondition and postcondition via icontract; @beartype on entrypoints.

Type of Change

Please check all that apply:

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🔒 Contract enforcement (adding/updating @icontract decorators)
  • 🧪 Test enhancement (scenario tests, property-based tests)
  • 🔧 Refactoring (code improvement without functionality change)

Contract-First Testing Evidence

Required for all changes affecting CLI commands or public APIs:

Contract Validation

  • Runtime contracts added/updated (@icontract decorators on public APIs)
  • Type checking enforced (@beartype decorators applied)
  • CrossHair exploration completed: hatch run contract-test-exploration
  • Contract violations reviewed and addressed (N/A for this scope / gates clean)

Test Execution

  • Contract validation: hatch run contract-test-contracts
  • Contract exploration: hatch run contract-test-exploration
  • Scenario tests: hatch run contract-test-scenarios
  • Full test suite: hatch run smart-test ✅ (and hatch run contract-test auto — cached pass)

Test Quality

  • CLI commands tested with typer test client (init ide paths covered via unit/integration tests)
  • Edge cases covered with Hypothesis property tests
  • Error handling tested with invalid inputs (malformed JSON, bad chat shape)
  • Rich console output verified manually or with snapshots

How Has This Been Tested?

Contract-First Approach: New predicates and safe-write helpers are covered by unit tests; verify_safe_project_writes is enforced in hatch run lint. specfact code review run executed clean on touched scripts.

Manual Testing

  • Tested CLI commands manually
  • Verified rich console output
  • Tested with different input scenarios
  • Checked error messages for clarity

Automated Testing

  • Contract validation passes
  • Property-based tests cover edge cases
  • Scenario tests cover user workflows
  • All existing tests still pass

Test Environment

  • Python version: 3.12 (Hatch default env)
  • OS: Linux (Ubuntu)

Checklist

  • My code follows the style guidelines (PEP 8, ruff format, isort)
  • I have performed a self-review of my code
  • I have added/updated contracts (@icontract, @beartype)
  • I have added/updated docstrings (Google style) (minimal; public helpers documented as in repo norms)
  • I have made corresponding changes to documentation
  • My changes generate no new warnings (basedpyright, ruff, pylint) (0 basedpyright errors; pre-existing test warnings)
  • All tests pass locally
  • I have added tests that prove my fix/feature works
  • Any dependent changes have been merged (paired specfact-cli-modules change tracked in [Change] Safe project artifact writes for init and IDE setup #490 — not a blocker for this PR)

Quality Gates Status

  • Type checking ✅ (hatch run type-check)
  • Linting ✅ (hatch run lint)
  • Contract validation ✅ (hatch run contract-test-contracts)
  • Contract exploration ✅ (hatch run contract-test-exploration)
  • Scenario tests ✅ (hatch run contract-test-scenarios)

Screenshots/Recordings (if applicable)

N/A (behavioral/CLI plumbing; see tests and TDD_EVIDENCE.md in the OpenSpec change folder).

djm81 added 2 commits April 12, 2026 21:55
- Add project_artifact_write.merge_vscode_settings_prompt_recommendations with fail-safe
  on invalid JSON / bad chat shape; --force backs up to .specfact/recovery/ then replaces.
- Route ide_setup create_vscode_settings through helper; thread force; catch errors for CLI exit.
- Lint gate: scripts/verify_safe_project_writes.py blocks json.load/dump in ide_setup.py.
- Tests, installation docs, 0.45.2 changelog and version pins.

OpenSpec: profile-04-safe-project-artifact-writes
Made-with: Cursor
- Refactor project_artifact_write merge path (KISS); icontract predicates
- Deduplicate ide_setup prompt helpers; import from project_artifact_write
- verify_safe_project_writes: ast.walk, contracts, beartype
- Pin setuptools<82 for Semgrep pkg_resources chain
- Update TDD_EVIDENCE and tasks checklist

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a safe-write core for project artifacts (notably .vscode/settings.json): new JSON5-backed merge/backup logic, error types, and explicit --force replace semantics; refactors IDE setup to use it; adds an AST-based CI/lint gate to prevent raw JSON IO; bumps package to v0.45.2 and updates docs/tests. (50 words)

Changes

Cohort / File(s) Summary
Version & Packaging
pyproject.toml, setup.py, src/__init__.py, src/specfact_cli/__init__.py, CHANGELOG.md
Bumped package to 0.45.2, added json5>=0.9.28, and constrained setuptools<82 in dev/Hatch envs.
Docs & Samples
README.md, docs/getting-started/installation.md, docs/_support/readme-first-contact/..., docs/_support/readme-first-contact/sample-output/..., docs/_support/readme-first-contact/sample-output/review-output.txt
Updated CLI version strings to 0.45.2; documented .vscode/settings.json merge behavior, failure modes, and --force/backup semantics; refreshed sample outputs.
Safe-write Core Module
src/specfact_cli/utils/project_artifact_write.py
New module: JSON5-backed read/merge/write for VS Code settings, repository-relative path safety, ordered dedupe merges, SpecFact-managed-path stripping, .specfact/recovery backups, error classes (ProjectArtifactWriteError, StructuredJsonDocumentError), and public APIs merge_vscode_settings_prompt_recommendations / backup_file_to_recovery.
IDE Setup Refactor
src/specfact_cli/utils/ide_setup.py
Delegates merging/repair to safe-write helper, adds force: bool param, handles StructuredJsonDocumentError with click-friendly exit, adjusts prompt-finalization to support empty explicit mappings, and removes local merge helpers.
Contracts & Validation
src/specfact_cli/utils/contract_predicates.py
Added icontract/beartype predicates settings_relative_nonblank and prompt_files_all_strings.
Lint Gate & CI
.github/workflows/pr-orchestrator.yml, pyproject.toml
Added scripts/verify_safe_project_writes.py to lint/CI checks and extended lint script to run the verifier; CI job step tightened with set -euo pipefail.
Regression Gate Script
scripts/verify_safe_project_writes.py
New AST-based verifier that scans ide_setup.py for direct JSON IO call sites (load, dump, loads, dumps, including aliases) and returns exit codes {0,1,2}.
Tests & OpenSpec Evidence
tests/unit/..., openspec/changes/profile-04-safe-project-artifact-writes/...
Added unit tests for safe-write behavior and verifier, extensive merge/backup/error-flow tests; added TDD evidence and updated tasks/checklist for profile-04.
Minor Test Import Update
tests/unit/utils/test_ide_setup.py
Adjusted test import to source _is_specfact_github_prompt_path from project_artifact_write.
Build/metadata script samples
docs/_support/readme-first-contact/capture-readme-output.sh, sample-output files
Bumped sample CLI version env usage to 0.45.2 in capture scripts and outputs.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI (init ide)
    participant IdeSetup as ide_setup.py
    participant SafeWrite as project_artifact_write.py
    participant FS as File System
    participant CI as CI / Lint Gate

    rect rgba(70, 130, 180, 0.5)
        note over CLI,IdeSetup: Prior behavior — direct overwrite
        CLI->>IdeSetup: create_vscode_settings(prompts)
        IdeSetup->>FS: write settings.json (overwrite)
        FS-->>CLI: existing settings lost
    end

    rect rgba(34, 139, 34, 0.5)
        note over CLI,SafeWrite: New behavior — merge, validate, backup
        CLI->>IdeSetup: create_vscode_settings(prompts, force=False)
        IdeSetup->>SafeWrite: merge_vscode_settings_prompt_recommendations(prompts,...)
        SafeWrite->>FS: read settings.json
        alt invalid JSON & force=False
            FS-->>SafeWrite: invalid JSON
            SafeWrite-->>IdeSetup: StructuredJsonDocumentError
            IdeSetup-->>CLI: abort with recovery guidance (exit 1)
        else valid JSON
            SafeWrite->>SafeWrite: merge chat.promptFilesRecommendations (ordered dedupe)
            SafeWrite->>FS: write merged settings.json (preserve other keys)
            FS-->>CLI: updated settings with SpecFact entries merged
        end
        alt force=True
            SafeWrite->>FS: backup settings.json → .specfact/recovery/*.bak
            SafeWrite->>FS: write replacement settings.json
            FS-->>CLI: recoverable backup created
        end
    end

    rect rgba(255, 165, 0, 0.5)
        note over CI,SafeWrite: CI/lint regression gate
        CI->>CI: run python scripts/verify_safe_project_writes.py
        CI-->>SafeWrite: ensures no raw json IO in ide_setup.py
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • #447 — Modifies IDE init/export logic and prompt recommendation merging; overlaps with safe-write and merge behavior changes.
  • #446 — Alters create_vscode_settings and prompts handling; intersects the refactor of prompt-source namespacing and merge semantics.
  • #478 — Touches VS Code settings and prompt-recommendation flow; related to merging/stripping SpecFact prompt entries and tests.

Suggested labels

QA, documentation

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: safe VS Code settings merge and project artifact writes (#490)' follows Conventional Commits style with 'fix:' prefix and clearly summarizes the main change.
Description check ✅ Passed The PR description comprehensively covers required sections: issue fixes, contract references, type of change checkboxes, testing evidence, quality gates, and detailed checklist completion.
Linked Issues check ✅ Passed Code changes fully implement linked issue requirements: #487 (merge instead of overwrite) and #490 (safe-write policy with backups, contracts, CI guards). All acceptance criteria are met.
Out of Scope Changes check ✅ Passed All changes are in-scope: safe-write helpers, contract enforcement, CI guard script, setuptools pin, documentation updates, and comprehensive tests directly address the linked issues.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/profile-04-safe-project-artifact-writes

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

@djm81 djm81 self-assigned this Apr 12, 2026
@djm81 djm81 added bug Something isn't working enhancement New feature or request architecture Architecture and design changes dependencies Dependency resolution and management labels Apr 12, 2026
@djm81 djm81 moved this from Todo to In Progress in SpecFact CLI Apr 12, 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: ed16399914

ℹ️ 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 pyproject.toml
Match hatch run lint by invoking scripts/verify_safe_project_writes.py
after ruff/basedpyright/pylint. Use set -euo pipefail so the first lint
failure is not masked by later commands.

Made-with: Cursor
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/getting-started/installation.md`:
- Around line 78-79: The paragraph beginning "For VS Code / Copilot, the CLI
**merges** prompt recommendations..." exceeds the 120-character markdown
line-length guideline; wrap it into multiple lines so no line exceeds 120
characters while preserving all original wording and symbols
(`.vscode/settings.json`, `chat` block, `specfact init ide --force`,
`.specfact/recovery/`) and keep the meaning that the command stops if JSON is
invalid and `--force` replaces the file after a timestamped backup.

In `@openspec/changes/profile-04-safe-project-artifact-writes/tasks.md`:
- Around line 23-28: Add a new checklist item to the verification tasks to run
strict OpenSpec validation: explicitly run "openspec validate
profile-04-safe-project-artifact-writes --strict" and fix any validation errors
until it passes before sign-off; update the tasks list (near the existing
numbered items 4.1–4.6) to include this step and record the successful
validation and timestamp in TDD_EVIDENCE.md (or PR notes) as part of completion
evidence.

In `@scripts/verify_safe_project_writes.py`:
- Around line 22-35: The current _collect_json_io_offenders only flags attribute
calls like json.load/dump and misses direct calls from "from json import loads"
or aliased imports; extend it to first scan the AST for ImportFrom nodes with
module == "json" and collect the imported names and their aliases (e.g., loads,
dumps, load, dump, or alias names), then when walking Call nodes also check if
node.func is an ast.Name whose id is in that collected set and append those
calls (using the same offenders tuple format) so direct imports and aliases are
detected in addition to json.X attribute calls.

In `@src/specfact_cli/utils/contract_predicates.py`:
- Around line 55-60: The validator settings_relative_nonblank currently only
checks for non-blank strings and must be tightened to forbid absolute paths and
parent-traversal segments: update settings_relative_nonblank to (1) strip and
ensure non-empty, (2) construct a pathlib.Path(settings_relative) and ensure
p.is_absolute() is False, and (3) ensure no part equals ".." (e.g., all(part !=
".." for part in p.parts)) so relative traversal is disallowed; return the
combined boolean. Use the function name settings_relative_nonblank and
pathlib.Path in the implementation.

In `@src/specfact_cli/utils/ide_setup.py`:
- Around line 515-523: Extract the duplicated StructuredJsonDocumentError
handling into a small helper (e.g., handle_structured_json_error) and call it
from both _copy_template_files_to_ide and copy_prompts_by_source_to_ide; the
helper should accept the exception instance and the console and perform the two
console.print calls shown in the current blocks and then raise
click.exceptions.Exit(1) from the passed exception. Replace the two try/except
blocks that catch StructuredJsonDocumentError around create_vscode_settings with
a single except that calls this helper (refer to StructuredJsonDocumentError,
create_vscode_settings, _copy_template_files_to_ide, and
copy_prompts_by_source_to_ide to locate the spots).

In `@src/specfact_cli/utils/project_artifact_write.py`:
- Around line 39-45: ProjectWriteMode is declared but never used; either clarify
intent or remove it: if you intend it as a public policy surface, add a short
docstring/TODO to the ProjectWriteMode enum explaining it’s reserved for future
write-dispatch semantics (CREATE_ONLY, MERGE_STRUCTURED, EXPLICIT_REPLACE) so
reviewers know it’s intentional; otherwise delete the ProjectWriteMode
declaration and remove any unused imports/exports referencing it to satisfy
YAGNI. Ensure you update any module-level __all__ or docs if present to reflect
the change.
- Around line 174-178: The backup filename currently uses
datetime.now(UTC).strftime("%Y%m%dT%H%M%SZ") which is only second-precision and
can collide; update the stamp generation in this backup routine (the code that
sets stamp and constructs dest) to include microseconds (e.g. use
"%Y%m%dT%H%M%S.%fZ" or append datetime.now(UTC).strftime("%f")) or implement a
collision-avoidance loop that checks dest.exists() and appends a numeric suffix
until a unique path is found before calling shutil.copy2; ensure you update the
stamp/dest construction code (the variables stamp, dest and the shutil.copy2
call) so no silent overwrite can occur.

In `@tests/unit/modules/init/test_init_ide_prompt_selection.py`:
- Around line 155-174: The test
test_init_ide_malformed_vscode_settings_exits_nonzero currently only checks exit
code and stdout but doesn't assert the CLI preserved the malformed
.vscode/settings.json; after invoking app (the runner.invoke call) read the
settings file (vscode_dir / "settings.json") and assert its contents remain the
original malformed string (e.g. "{not-json") to ensure non-destructive behavior
is tested; place this assertion after the existing exit_code/stdout checks so it
runs even when the command failed.

In `@tests/unit/utils/test_project_artifact_write.py`:
- Around line 102-115: Add a complementary unit test that verifies
create_vscode_settings coerces a non-object "chat" when force=True and creates a
backup: create a .vscode/settings.json containing {"chat":"invalid"}, create a
prompt file as in the existing test, call create_vscode_settings(tmp_path,
".vscode/settings.json", prompts_by_source={PROMPT_SOURCE_CORE: [prompt]},
force=True), then assert a backup file exists under .specfact/recovery (e.g.,
settings.json.*.bak) and that the updated settings.json now has data["chat"] as
a dict; use the test name
test_create_vscode_settings_chat_not_object_force_coerces_with_backup to mirror
the existing test pattern.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: dd742cff-d512-4f1b-924d-f68582e04fec

📥 Commits

Reviewing files that changed from the base of the PR and between 73b8f48 and ed16399.

📒 Files selected for processing (21)
  • CHANGELOG.md
  • README.md
  • docs/_support/readme-first-contact/capture-readme-output.sh
  • docs/_support/readme-first-contact/sample-output/capture-metadata.txt
  • docs/_support/readme-first-contact/sample-output/review-output.txt
  • docs/getting-started/installation.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • pyproject.toml
  • scripts/verify_safe_project_writes.py
  • setup.py
  • src/__init__.py
  • src/specfact_cli/__init__.py
  • src/specfact_cli/utils/contract_predicates.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_ide_setup.py
  • tests/unit/utils/test_project_artifact_write.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Linting (ruff, pylint)
  • GitHub Check: Contract-First CI
  • GitHub Check: Tests (Python 3.12)
  • GitHub Check: Compatibility (Python 3.11)
🧰 Additional context used
📓 Path-based instructions (19)
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

**/*.py: Maintain minimum 80% test coverage, with 100% coverage for critical paths in Python code
Use clear naming and self-documenting code, preferring clear names over comments
Ensure each function/class has a single clear purpose (Single Responsibility Principle)
Extract common patterns to avoid code duplication (DRY principle)
Apply SOLID object-oriented design principles in Python code
Use type hints everywhere in Python code and enable basedpyright strict mode
Use Pydantic models for data validation and serialization in Python
Use async/await for I/O operations in Python code
Use context managers for resource management in Python
Use dataclasses for simple data containers in Python
Enforce maximum line length of 120 characters in Python code
Use 4 spaces for indentation in Python code (no tabs)
Use 2 blank lines between classes and 1 blank line between methods in Python
Organize imports in order: Standard library → Third party → Local in Python files
Use snake_case for variables and functions in Python
Use PascalCase for class names in Python
Use UPPER_SNAKE_CASE for constants in Python
Use leading underscore (_) for private methods in Python classes
Use snake_case for Python file names
Enable basedpyright strict mode with strict type checking configuration in Python
Use Google-style docstrings for functions and classes in Python
Include comprehensive exception handling with specific exception types in Python code
Use logging with structured context (extra parameters) instead of print statements
Use retry logic with tenacity decorators (@retry) for operations that might fail
Use Pydantic BaseSettings for environment-based configuration in Python
Validate user input using Pydantic validators in Python models
Use @lru_cache and Redis-based caching for expensive calculations in Python
Run code formatting with Black (120 character line length) and isort in Python
Run type checking with basedpyright on all Python files
Run linting with ruff and pylint on all Pyth...

Files:

  • src/__init__.py
  • src/specfact_cli/__init__.py
  • tests/unit/utils/test_contract_predicates.py
  • setup.py
  • tests/unit/utils/test_ide_setup.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • src/specfact_cli/utils/contract_predicates.py
  • scripts/verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
{src/__init__.py,pyproject.toml,setup.py}

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

{src/__init__.py,pyproject.toml,setup.py}: Update src/init.py first as primary source of truth for package version, then pyproject.toml and setup.py
Maintain version synchronization across src/init.py, pyproject.toml, and setup.py

Files:

  • src/__init__.py
  • setup.py
  • pyproject.toml
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

src/**/*.py: All code changes must be followed by running the full test suite using the smart test system.
All Python files in src/ and tools/ directories must have corresponding test files in tests/ directory. If you modify src/common/logger_setup.py, you MUST have tests/unit/common/test_logger_setup.py. NO EXCEPTIONS - even small changes require tests.
All new Python runtime code files must have corresponding test files created BEFORE committing the code. NO EXCEPTIONS - no code without tests.
Test Coverage Validation: Run hatch run smart-test-unit for modified files, hatch run smart-test-folder for modified directories, and hatch run smart-test-full before committing. ALL TESTS MUST PASS.
All components must support TEST_MODE=true environment variable with test-specific behavior defined as: if os.environ.get('TEST_MODE') == 'true': # test-specific behavior
Use src/common/logger_setup.py for all logging via: from common.logger_setup import get_logger; logger = get_logger(name)
Use src/common/redis_client.py with fallback for Redis operations via: from common.redis_client import get_redis_client; redis_client = get_redis_client()
Type checking must pass with no errors using: mypy .
Test coverage must meet or exceed 80% total coverage. New code must have corresponding tests. Modified code must maintain or improve coverage. Critical paths must have 100% coverage.
Use Pydantic v2 validation for all context and data schemas.

Add/update contracts on new or modified public APIs, stateful classes and adapters using icontract decorators and beartype runtime type checks

src/**/*.py: Meaningful Naming — identifiers reveal intent; avoid abbreviations. Identifiers in src/ must use snake_case (modules/functions), PascalCase (classes), UPPER_SNAKE_CASE (constants). Avoid single-letter names outside short loop variables.
KISS — keep functions and modules small and single-purpose. Maximum function length: 120 lines (Phase A error threshold). Maximum cyclomati...

Files:

  • src/__init__.py
  • src/specfact_cli/__init__.py
  • src/specfact_cli/utils/contract_predicates.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
@(src|tests)/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Linting must pass with no errors using: pylint src tests

Files:

  • src/__init__.py
  • src/specfact_cli/__init__.py
  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_ide_setup.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • src/specfact_cli/utils/contract_predicates.py
  • tests/unit/utils/test_project_artifact_write.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
{pyproject.toml,setup.py,src/__init__.py}

📄 CodeRabbit inference engine (.cursor/rules/testing-and-build-guide.mdc)

Manually update version numbers in pyproject.toml, setup.py, and src/init.py when making a formal version change

Files:

  • src/__init__.py
  • setup.py
  • pyproject.toml
**/*.{py,pyi}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{py,pyi}: After any code changes, follow these steps in order: (1) Apply linting and formatting to ensure code quality: hatch run format, (2) Type checking: hatch run type-check (basedpyright), (3) Contract-first approach: Run hatch run contract-test for contract validation, (4) Run full test suite: hatch test --cover -v, (5) Verify all tests pass and contracts are satisfied, (6) Fix any issues and repeat steps until all tests pass
All public APIs must have @icontract decorators and @beartype type checking
Use Pydantic models for all data structures with data validation
Only write high-value comments if at all. Avoid talking to the user through comments

Files:

  • src/__init__.py
  • src/specfact_cli/__init__.py
  • tests/unit/utils/test_contract_predicates.py
  • setup.py
  • tests/unit/utils/test_ide_setup.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • src/specfact_cli/utils/contract_predicates.py
  • scripts/verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
src/specfact_cli/**/*.py

⚙️ CodeRabbit configuration file

src/specfact_cli/**/*.py: Focus on modular CLI architecture: lazy module loading, registry/bootstrap patterns, and
dependency direction. Flag breaking changes to public APIs, Pydantic models, and resource
bundling. Verify @icontract + @beartype on public surfaces; prefer centralized logging
(get_bridge_logger) over print().

Files:

  • src/specfact_cli/__init__.py
  • src/specfact_cli/utils/contract_predicates.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
**/test_*.py

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

**/test_*.py: Write tests first in test-driven development (TDD) using the Red-Green-Refactor cycle
Ensure each test is independent and repeatable with no shared state between tests
Organize Python imports in tests using unittest.mock for Mock and patch
Use setup_method() for test initialization and Arrange-Act-Assert pattern in test files
Use @pytest.mark.asyncio decorator for async test functions in Python
Organize test files in structure: tests/unit/, tests/integration/, tests/e2e/ by module

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_ide_setup.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py
tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Tests must be meaningful and test actual functionality, cover both success and failure cases, be independent and repeatable, and have clear, descriptive names. NO EXCEPTIONS - no placeholder or empty tests.

tests/**/*.py: Trim low-value unit tests when a contract covers the same assertion (type/shape/raises on negative checks)
Delete tests that only assert input validation, datatype/shape enforcement, or raises on negative conditions now guarded by contracts and runtime typing
Convert repeated edge-case permutations into one Hypothesis property with contracts acting as oracles

Secret redaction via LoggerSetup.redact_secrets must be covered by unit tests

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_ide_setup.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py

⚙️ CodeRabbit configuration file

tests/**/*.py: Contract-first testing: meaningful scenarios, not redundant assertions already covered by
contracts. Flag flakiness, environment coupling, and missing coverage for changed behavior.

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_ide_setup.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py
**/*.{md,mdc}

📄 CodeRabbit inference engine (.cursor/rules/markdown-rules.mdc)

**/*.{md,mdc}: Do not use more than one consecutive blank line anywhere in the document (MD012: No Multiple Consecutive Blank Lines)
Fenced code blocks should be surrounded by blank lines (MD031: Fenced Code Blocks)
Lists should be surrounded by blank lines (MD032: Lists)
Files must end with a single empty line (MD047: Files Must End With Single Newline)
Lines should not have trailing spaces (MD009: No Trailing Spaces)
Use asterisks (**) for strong emphasis, not underscores (__) (MD050: Strong Style)
Fenced code blocks must have a language specified (MD040: Fenced Code Language)
Headers should increment by one level at a time (MD001: Header Increment)
Headers should be surrounded by blank lines (MD022: Headers Should Be Surrounded By Blank Lines)
Only one top-level header (H1) is allowed per document (MD025: Single H1 Header)
Use consistent list markers, preferring dashes (-) for unordered lists (MD004: List Style)
Nested unordered list items should be indented consistently, typically by 2 spaces (MD007: Unordered List Indentation)
Use exactly one space after the list marker (e.g., -, *, +, 1.) (MD030: Spaces After List Markers)
Use incrementing numbers for ordered lists (MD029: Ordered List Item Prefix)
Enclose bare URLs in angle brackets or format them as links (MD034: Bare URLs)
Don't use spaces immediately inside code spans (MD038: Spaces Inside Code Spans)
Use consistent indentation (usually 2 or 4 spaces) throughout markdown files
Keep line length under 120 characters in markdown files
Use reference-style links for better readability in markdown files
Use a trailing slash for directory paths in markdown files
Ensure proper escaping of special characters in markdown files

Files:

  • README.md
  • docs/getting-started/installation.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • CHANGELOG.md
@(README.md|AGENTS.md)

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Check README.md and AGENTS.md for current project status and development guidelines. Review .cursor/rules/ for detailed development standards and testing procedures.

Files:

  • README.md
**/*.md

📄 CodeRabbit inference engine (.cursorrules)

Avoid markdown linting errors (refer to markdown-rules)

Files:

  • README.md
  • docs/getting-started/installation.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • CHANGELOG.md
docs/**/*.md

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Update architecture documentation in docs/ for architecture changes, state machine documentation for FSM modifications, interface documentation for API changes, and configuration guides for configuration changes. DO NOT create internal docs in specfact-cli repo folder that should not be visible to end users; use the respective internal repository instead.

Files:

  • docs/getting-started/installation.md

⚙️ CodeRabbit configuration file

docs/**/*.md: User-facing accuracy: CLI examples match current behavior; preserve Jekyll front matter;
call out when README/docs index need sync.

Files:

  • docs/getting-started/installation.md
openspec/changes/**/*.md

📄 CodeRabbit inference engine (.cursorrules)

For /opsx:archive (Archive change): Include module signing and cleanup in final tasks. Agents MUST run openspec archive <change-id> from repo root (no manual mv under openspec/changes/archive/)

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
openspec/**/*.md

⚙️ CodeRabbit configuration file

openspec/**/*.md: Treat as specification source of truth: proposal/tasks/spec deltas vs. code behavior,
CHANGE_ORDER consistency, and scenario coverage. Surface drift between OpenSpec and
implementation.

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
openspec/**/{proposal.md,tasks.md,design.md,spec.md}

📄 CodeRabbit inference engine (.cursor/rules/automatic-openspec-workflow.mdc)

openspec/**/{proposal.md,tasks.md,design.md,spec.md}: Apply openspec/config.yaml project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase
After implementation, validate the change with openspec validate <change-id> --strict; fix validation errors in proposal, specs, design, or tasks and re-validate until passing before considering the change complete

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
scripts/**/*.py

⚙️ CodeRabbit configuration file

scripts/**/*.py: Deterministic tooling: subprocess safety, Hatch integration, and parity with documented
quality gates (format, type-check, module signing).

Files:

  • scripts/verify_safe_project_writes.py
pyproject.toml

📄 CodeRabbit inference engine (.cursorrules)

When updating the version in pyproject.toml, ensure it's newer than the latest PyPI version. The CI/CD pipeline will automatically publish to PyPI only if the new version is greater than the published version

Files:

  • pyproject.toml
CHANGELOG.md

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

Include new version entries at the top of CHANGELOG.md when updating versions

Update CHANGELOG.md with all code changes as part of version control requirements.

Update CHANGELOG.md to document all significant changes under Added, Fixed, Changed, or Removed sections when making a version change

Files:

  • CHANGELOG.md
🧠 Learnings (46)
📓 Common learnings
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : Apply `openspec/config.yaml` project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: When creating implementation plans, task lists, or OpenSpec tasks.md, ALWAYS explicitly verify and include: (1) Worktree creation from `origin/dev` (not `git checkout -b`), (2) `hatch env create` in the worktree, (3) Pre-flight checks (`hatch run smart-test-status`, `hatch run contract-test-status`), (4) Worktree cleanup steps post-merge, (5) Self-check: 'Have I followed AGENTS.md Git Worktree Policy section?'
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-10T22:41:26.519Z
Learning: Enforce the clean-code review gate through `hatch run specfact code review run --json --out .specfact/code-review.json`
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to {src/__init__.py,pyproject.toml,setup.py} : Update src/__init__.py first as primary source of truth for package version, then pyproject.toml and setup.py

Applied to files:

  • src/__init__.py
  • pyproject.toml
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to {pyproject.toml,setup.py,src/__init__.py} : Manually update version numbers in pyproject.toml, setup.py, and src/__init__.py when making a formal version change

Applied to files:

  • src/__init__.py
  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to @(pyproject.toml|setup.py|src/__init__.py|src/specfact_cli/__init__.py) : Maintain synchronized versions across pyproject.toml, setup.py, src/__init__.py, and src/specfact_cli/__init__.py.

Applied to files:

  • src/__init__.py
  • src/specfact_cli/__init__.py
  • setup.py
  • pyproject.toml
  • CHANGELOG.md
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to {src/__init__.py,pyproject.toml,setup.py} : Maintain version synchronization across src/__init__.py, pyproject.toml, and setup.py

Applied to files:

  • src/__init__.py
  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to docs/**/*.md : Update architecture documentation in docs/ for architecture changes, state machine documentation for FSM modifications, interface documentation for API changes, and configuration guides for configuration changes. DO NOT create internal docs in specfact-cli repo folder that should not be visible to end users; use the respective internal repository instead.

Applied to files:

  • docs/_support/readme-first-contact/sample-output/review-output.txt
  • docs/_support/readme-first-contact/sample-output/capture-metadata.txt
  • README.md
  • docs/getting-started/installation.md
📚 Learning: 2026-04-10T22:42:21.849Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-10T22:42:21.849Z
Learning: Fix SpecFact code review findings, including warnings, unless a rare explicit exception is documented

Applied to files:

  • docs/_support/readme-first-contact/sample-output/review-output.txt
  • docs/_support/readme-first-contact/sample-output/capture-metadata.txt
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Trim low-value unit tests when a contract covers the same assertion (type/shape/raises on negative checks)

Applied to files:

  • tests/unit/utils/test_contract_predicates.py
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Delete tests that only assert input validation, datatype/shape enforcement, or raises on negative conditions now guarded by contracts and runtime typing

Applied to files:

  • tests/unit/utils/test_contract_predicates.py
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Convert repeated edge-case permutations into one Hypothesis property with contracts acting as oracles

Applied to files:

  • tests/unit/utils/test_contract_predicates.py
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: All development work MUST use git worktrees per AGENTS.md Git Worktree Policy. Never create branches with `git checkout -b` in the primary checkout. Create worktree from origin/dev: `git worktree add ../specfact-cli-worktrees/<type>/<slug> -b <branch-name> origin/dev` where allowed types are: `feature/`, `bugfix/`, `hotfix/`, `chore/`. Forbidden in worktrees: `dev`, `main`. After creating worktree: `cd ../specfact-cli-worktrees/<type>/<slug>`. Bootstrap Hatch in worktree: `hatch env create`. Run pre-flight checks: `hatch run smart-test-status` and `hatch run contract-test-status`. Do all implementation work from the worktree, never from primary checkout. After PR merge: cleanup with `git worktree remove`, `git branch -d`, `git worktree prune`

Applied to files:

  • docs/_support/readme-first-contact/capture-readme-output.sh
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:42:04.362Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/session_startup_instructions.mdc:0-0
Timestamp: 2026-04-10T22:42:04.362Z
Learning: After merges shipping OpenSpec- or GitHub-related work with a sibling `specfact-cli-internal` checkout present, run wiki scripts from that sibling repo's working directory (e.g., `cd ../specfact-cli-internal && python3 scripts/wiki_openspec_gh_status.py`), not from `specfact-cli` or other directories

Applied to files:

  • docs/_support/readme-first-contact/capture-readme-output.sh
  • docs/_support/readme-first-contact/sample-output/capture-metadata.txt
  • README.md
📚 Learning: 2026-04-10T22:42:04.362Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/session_startup_instructions.mdc:0-0
Timestamp: 2026-04-10T22:42:04.362Z
Learning: Detect repository root, branch, and worktree state before implementation

Applied to files:

  • docs/_support/readme-first-contact/capture-readme-output.sh
📚 Learning: 2026-04-10T22:42:21.849Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-10T22:42:21.849Z
Learning: Detect repository root, active branch, and worktree state during bootstrap

Applied to files:

  • docs/_support/readme-first-contact/capture-readme-output.sh
📚 Learning: 2026-04-10T22:41:26.519Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-10T22:41:26.519Z
Learning: Enforce the clean-code review gate through `hatch run specfact code review run --json --out .specfact/code-review.json`

Applied to files:

  • docs/_support/readme-first-contact/sample-output/capture-metadata.txt
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • scripts/verify_safe_project_writes.py
  • CHANGELOG.md
📚 Learning: 2026-04-10T22:42:04.362Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/session_startup_instructions.mdc:0-0
Timestamp: 2026-04-10T22:42:04.362Z
Learning: For OpenSpec changes when a sibling `specfact-cli-internal/` checkout exists, read internal wiki guidance in `docs/agent-rules/40-openspec-and-tdd.md` and consult `wiki/hot.md`, `wiki/graph.md`, and relevant `wiki/concepts/*.md` files

Applied to files:

  • docs/_support/readme-first-contact/sample-output/capture-metadata.txt
  • README.md
  • docs/getting-started/installation.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • CHANGELOG.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: If `openspec` command is not found or if specfact-cli workspace or openspec/ directory is not accessible, do not modify application code unless the user explicitly confirms to proceed without OpenSpec

Applied to files:

  • docs/_support/readme-first-contact/sample-output/capture-metadata.txt
  • docs/getting-started/installation.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : Apply `openspec/config.yaml` project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase

Applied to files:

  • README.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • tests/unit/utils/test_project_artifact_write.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to src/**/*.py : All code changes must be followed by running the full test suite using the smart test system.

Applied to files:

  • tests/unit/scripts/test_verify_safe_project_writes.py
  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to src/**/*.py : Test Coverage Validation: Run hatch run smart-test-unit for modified files, hatch run smart-test-folder for modified directories, and hatch run smart-test-full before committing. ALL TESTS MUST PASS.

Applied to files:

  • tests/unit/scripts/test_verify_safe_project_writes.py
  • pyproject.toml
📚 Learning: 2026-04-10T22:42:21.849Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-10T22:42:21.849Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: For `/opsx:ff` (Fast-Forward Change Creation): OPSX provides change scaffolding and artifact templates. AGENTS.md requires explicitly adding: Worktree creation task as Step 1 in tasks.md (not just 'create branch'), TDD_EVIDENCE.md tracking task in section 2 (Tests), Documentation research task per `openspec/config.yaml`, Module signing quality gate if applicable, Worktree cleanup steps in final section

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:31:55.908Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/estimation-bias-prevention.mdc:0-0
Timestamp: 2026-03-25T21:31:55.908Z
Learning: Use TDD with quality gates (contract-driven, test-driven implementation, quality gate validation, documentation) as the standard development pattern

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : After implementation, validate the change with `openspec validate <change-id> --strict`; fix validation errors in proposal, specs, design, or tasks and re-validate until passing before considering the change complete

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Before implementing code changes, run `openspec validate <change-id> --strict` to validate the OpenSpec change and optionally run `/wf-validate-change <change-id>` for breaking-change and dependency analysis; do not proceed to implementation until validation passes or user explicitly overrides

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: When creating implementation plans, task lists, or OpenSpec tasks.md, ALWAYS explicitly verify and include: (1) Worktree creation from `origin/dev` (not `git checkout -b`), (2) `hatch env create` in the worktree, (3) Pre-flight checks (`hatch run smart-test-status`, `hatch run contract-test-status`), (4) Worktree cleanup steps post-merge, (5) Self-check: 'Have I followed AGENTS.md Git Worktree Policy section?'

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: For `/opsx:apply` (Implementation): OPSX provides task iteration and progress tracking. AGENTS.md requires verification before each task: Confirm you are IN a worktree (not primary checkout) before modifying code, Record failing test evidence in `TDD_EVIDENCE.md` BEFORE implementing, Record passing test evidence AFTER implementation, Run quality gates from worktree (format, type-check, contract-test), GPG-signed commits (`git commit -S`), PR to `dev` branch (never direct push)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to **/*.{py,pyi} : After any code changes, follow these steps in order: (1) Apply linting and formatting to ensure code quality: `hatch run format`, (2) Type checking: `hatch run type-check` (basedpyright), (3) Contract-first approach: Run `hatch run contract-test` for contract validation, (4) Run full test suite: `hatch test --cover -v`, (5) Verify all tests pass and contracts are satisfied, (6) Fix any issues and repeat steps until all tests pass

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • pyproject.toml
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to openspec/changes/**/*.md : For `/opsx:archive` (Archive change): Include module signing and cleanup in final tasks. Agents MUST run `openspec archive <change-id>` from repo root (no manual `mv` under `openspec/changes/archive/`)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Before executing ANY workflow command (`/opsx:ff`, `/opsx:apply`, `/opsx:continue`, etc.), perform the Pre-Execution Checklist: (1) Git Worktree - create if task creates branches/modifies code, (2) TDD Evidence - create `TDD_EVIDENCE.md` if behavior changes, (3) Documentation - include documentation research if changes affect user-facing behavior, (4) Module Signing - include signature verification if changes modify bundled modules, (5) Confirmation - state clearly that pre-execution checklist is complete and AGENTS.md compliance is confirmed

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-31T22:38:25.299Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/clean-code-principles.mdc:0-0
Timestamp: 2026-03-31T22:38:25.299Z
Learning: Applies to src/**/*.py : Use `icontract` (`require`/`ensure`) and `beartype` on all public APIs in `src/`

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to src/**/*.py : Add/update contracts on new or modified public APIs, stateful classes and adapters using `icontract` decorators and `beartype` runtime type checks

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to **/*.{py,pyi} : All public APIs must have `icontract` decorators and `beartype` type checking

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-04-10T22:41:26.519Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-10T22:41:26.519Z
Learning: Applies to **/*.py : Public APIs require icontract and beartype decorators

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to {src,tools}/**/*.{js,ts,jsx,tsx,py},**/*.test.{js,ts,jsx,tsx,py},**/*.spec.{js,ts,jsx,tsx,py} : Do not add, modify, or delete any application code in src/, tools/, tests, or significant docs until an OpenSpec change (new or delta) is created and validated, unless the user explicitly opts out with 'skip openspec', 'direct implementation', 'simple fix', or 'just fix it'

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Always finish each output by listing: (1) Which rulesets have been applied (e.g., `.cursorrules`, `AGENTS.md`, specific `.cursor/rules/*.mdc`), (2) Confirmation of Git Worktree Policy compliance (if applicable), (3) Which AI (LLM) provider and model version you are using

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: When implementation is complete and merged, run `openspec archive <change-id>` from the repository root to merge delta specs into openspec/specs/ and move the change under openspec/changes/archive/; do not manually move folders or use --skip-specs or --no-validate without explicit user confirmation

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to pyproject.toml : When updating the version in `pyproject.toml`, ensure it's newer than the latest PyPI version. The CI/CD pipeline will automatically publish to PyPI only if the new version is greater than the published version

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to **/*.py : Use Python 3.12 as the target Python version

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to **/*.py : Run linting with ruff and pylint on all Python files

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Use `hatch test` command for running tests instead of direct pytest usage to ensure proper Python matrix, dependency resolution, environment variables, and coverage reports

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to **/*.py : Run type checking with basedpyright on all Python files

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to @(src|tests)/**/*.py : Linting must pass with no errors using: pylint src tests

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Before making a pull request, locally run format, lint, contract tests, and full test suite: `hatch run format`, `hatch run lint`, `hatch run contract-test`, `hatch test --cover -v`

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to src/**/*.py : Type checking must pass with no errors using: mypy .

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to CHANGELOG.md : Update CHANGELOG.md to document all significant changes under Added, Fixed, Changed, or Removed sections when making a version change

Applied to files:

  • CHANGELOG.md
🪛 GitHub Check: Type Checking (basedpyright)
src/specfact_cli/utils/project_artifact_write.py

[warning] 186-186:
Type of "is_file" is unknown (reportUnknownMemberType)


[warning] 186-186:
Type of "exists" is unknown (reportUnknownMemberType)


[warning] 169-169:
Type of "is_file" is unknown (reportUnknownMemberType)


[warning] 145-145:
Type of "get" is partially unknown
  Type of "get" is "Overload[(key: Unknown, default: None = None, /) -> (Unknown | None), (key: Unknown, default: Unknown, /) -> Unknown, (key: Unknown, default: _T@get, /) -> (Unknown | _T@get)]" (reportUnknownMemberType)

🔇 Additional comments (22)
openspec/changes/profile-04-safe-project-artifact-writes/tasks.md (1)

16-20: Safe-write rollout tasks and quality gates are well-scoped and traceable.

The implementation/verification breakdown is clear and maps cleanly to the safe artifact-write policy and CI guard outcomes.

Also applies to: 23-27

src/__init__.py (1)

6-6: Version bump in package root is correct.

__version__ update is appropriate for the patch release flow.

docs/_support/readme-first-contact/sample-output/review-output.txt (1)

12-12: Sample output version stamp is correctly updated.

This keeps captured evidence aligned with the release version.

README.md (1)

30-30: README release references are consistent.

Both the sample banner and hook revision now correctly reflect v0.45.2.

Also applies to: 87-87

src/specfact_cli/__init__.py (1)

48-48: Exported package version update looks good.

specfact_cli.__version__ now matches the patch release target.

setup.py (1)

10-10: Distribution metadata version bump is correct.

setup.py is aligned with the patch version increment.

docs/_support/readme-first-contact/sample-output/capture-metadata.txt (1)

3-3: Capture metadata version updates are consistent and correct.

The pinned uvx --from "specfact-cli==0.45.2" commands align with the release artifacts.

Also applies to: 12-13

docs/_support/readme-first-contact/capture-readme-output.sh (1)

8-8: Default capture CLI version update is correct.

The capture script now targets the intended 0.45.2 release by default.

tests/unit/utils/test_ide_setup.py (1)

24-24: Import move is correct and keeps coverage aligned with the refactor.

This update keeps the existing path-filter tests pointed at the new owning module.

tests/unit/scripts/test_verify_safe_project_writes.py (1)

10-19: Good regression gate test for the safe-write verifier.

This provides a straightforward CI guard that the safety script remains executable and passing in-repo.

pyproject.toml (2)

210-210: Nice lint-gate integration for safe project writes.

Adding scripts/verify_safe_project_writes.py to hatch run lint is a strong regression barrier for VS Code settings safety.


7-7: Version synchronization is correct across all package sources.

The version bump to 0.45.2 is properly synchronized: pyproject.toml, src/init.py, src/specfact_cli/init.py, and setup.py all match.

tests/unit/utils/test_contract_predicates.py (1)

36-43: ⚠️ Potential issue | 🟡 Minor

Add rejection-path cases for the new safety predicates.

Line 36 and Line 41 currently cover only happy/basic paths. Please add explicit rejection scenarios (for example absolute/parent-traversal path inputs for settings_relative_nonblank, and at least one non-string element case for prompt_files_all_strings) so the contract intent is regression-safe.

As per coding guidelines: tests/**/*.py: Contract-first testing should cover meaningful scenarios, not just redundant/basic assertions.

⛔ Skipped due to learnings
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Trim low-value unit tests when a contract covers the same assertion (type/shape/raises on negative checks)
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Convert repeated edge-case permutations into one Hypothesis property with contracts acting as oracles
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Delete tests that only assert input validation, datatype/shape enforcement, or raises on negative conditions now guarded by contracts and runtime typing
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to tests/**/*.py : Tests must be meaningful and test actual functionality, cover both success and failure cases, be independent and repeatable, and have clear, descriptive names. NO EXCEPTIONS - no placeholder or empty tests.
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*e2e*.py : Keep scenario/E2E tests for behavioral coverage, performance and resilience validation
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to src/**/*.py : Test coverage must meet or exceed 80% total coverage. New code must have corresponding tests. Modified code must maintain or improve coverage. Critical paths must have 100% coverage.
CHANGELOG.md (1)

13-25: Looks good: release entry is clear, scoped, and correctly positioned.

This 0.45.2 changelog block is top-placed, readable, and captures the safe-write policy, lint gate, and Semgrep/setuptools compatibility fix in a way that supports release traceability.

openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md (1)

1-55: Well-structured TDD evidence document aligning with OpenSpec workflow.

The evidence captures the failing-first → passing-after TDD cycle correctly, includes proper worktree path conventions, and documents the code review gate command matching the repository's quality gate pattern. The module signature verification step wisely notes that module-package.yaml remains unchanged since error UX is handled in ide_setup.

scripts/verify_safe_project_writes.py (1)

38-44: Contract precondition _repo_layout_ok() is minimal—consider strengthening.

The precondition only checks ROOT.is_dir(). For a regression gate, you might also want to verify that the src/specfact_cli directory structure exists to fail early with a clear contract violation rather than returning exit code 2.

That said, the current design separates "repo layout" (contract) from "target file existence" (runtime check with distinct exit code), which is a reasonable architectural choice for CI diagnostics.

tests/unit/utils/test_project_artifact_write.py (2)

59-79: Solid preservation test covering both top-level and nested chat keys.

This test correctly validates the core requirement from issue #487: unrelated user settings survive the merge. The test exercises both python.defaultInterpreterPath (top-level) and chat.otherSetting (nested within the managed key), confirming the merge implementation respects the trust boundary.

The assertion on line 79 verifies the prompt path transformation (.github/prompts/specfact.01-import.prompt.md), which aligns with the flat export layout.


82-99: Force-replace test validates backup/recovery contract.

The test correctly verifies that force=True creates a recovery directory and timestamped backup before replacing malformed JSON. The glob pattern settings.json.*.bak matches the backup_file_to_recovery implementation.

One architectural note: the test doesn't verify backup file contents, but since test_backup_file_to_recovery_writes_under_specfact (lines 32-38) already validates content preservation, this is appropriate separation of concerns.

src/specfact_cli/utils/ide_setup.py (1)

880-932: Well-designed contract-first public API with clear parameter semantics.

The create_vscode_settings function demonstrates good architectural principles:

  1. Contract decorators (@beartype, @require, @ensure) enforce input/output invariants at the API boundary
  2. Clear parameter semantics: force maps directly to explicit_replace_unparseable, making the intent transparent
  3. Delegation to shared helper: JSON I/O is routed through merge_vscode_settings_prompt_recommendations, satisfying the regression gate
  4. Docstring update (lines 899-900) documents the new force behavior for downstream consumers

The strip_specfact_github_from_existing=prompts_by_source is not None logic elegantly handles the selective export case where stale SpecFact recommendations should be pruned.

src/specfact_cli/utils/project_artifact_write.py (3)

165-178: Contract-protected backup function with clear recovery semantics.

The backup_file_to_recovery function demonstrates excellent contract-first design:

  1. Preconditions validate repo exists, is a directory, and source file exists
  2. Postcondition guarantees the returned path is a file (backup succeeded)
  3. Safe filename sanitization via regex prevents path traversal or special character issues
  4. shutil.copy2 preserves metadata, which is useful for forensic recovery

The .specfact/recovery/ location keeps backups organized within the project's tooling directory rather than polluting the workspace root.


181-227: Architecturally sound merge entry point with layered validation.

The merge_vscode_settings_prompt_recommendations function implements a clean layered architecture:

  1. Path resolution (lines 202-203): Normalizes and ensures parent directory
  2. Create-if-missing (lines 205-207): Fast path for new repos
  3. Load + validate (lines 209-216): First validation layer via _load_root_dict_from_settings_text
  4. Merge + validate (lines 217-225): Second validation layer via _merge_chat_and_recommendations
  5. Atomic write (line 226): Final state persisted

The contract predicates (settings_relative_nonblank, prompt_files_all_strings) from contract_predicates.py enforce API boundaries at runtime, while the postcondition guarantees callers always receive an existing file path.

This design satisfies the OpenSpec profile requirement for safe artifact writes with declared ownership semantics.


90-119: Validation layer handles JSON parse errors with actionable guidance.

The error message at lines 102-105 includes:

  • The specific file path
  • JSON error details (message, line, column)
  • Clear remediation: "Fix the file or re-run with --force"

This aligns with the PR objective of making malformed JSON cause a "safe failure" rather than silent data loss. The backup-before-replace pattern (lines 106-108) ensures recoverability when --force is used.

Comment thread docs/getting-started/installation.md Outdated
Comment thread openspec/changes/profile-04-safe-project-artifact-writes/tasks.md Outdated
Comment thread scripts/verify_safe_project_writes.py
Comment thread src/specfact_cli/utils/contract_predicates.py
Comment thread src/specfact_cli/utils/ide_setup.py Outdated
Comment thread src/specfact_cli/utils/project_artifact_write.py
Comment thread src/specfact_cli/utils/project_artifact_write.py Outdated
Comment thread tests/unit/modules/init/test_init_ide_prompt_selection.py
Comment thread tests/unit/utils/test_project_artifact_write.py
…ests)

- Wrap installation.md VS Code merge paragraph to <=120 chars per line
- tasks 4.7 + TDD_EVIDENCE: openspec validate --strict sign-off
- verify_safe_project_writes: detect from-json import and aliases
- settings_relative_nonblank: reject absolute paths and .. segments
- ide_setup: _handle_structured_json_document_error for duplicate handlers
- ProjectWriteMode docstring (reserved policy surface); backup stamp + collision loop
- Tests: malformed settings preserved on init ide exit; force+chat coercion; AST guard tests

Made-with: Cursor
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/specfact_cli/utils/ide_setup.py (1)

909-924: ⚠️ Potential issue | 🟠 Major

Don't repopulate recommendations on an empty selective export.

When prompts_by_source is an empty dict, this branch falls back to the full discovered catalog instead of preserving the empty selection. That means a selective init ide --prompts ... run that exports zero prompts will re-add every SpecFact recommendation rather than clearing stale managed entries. The selective path should pass through the exact exported set, even when it is empty.

♻️ Minimal fix
-    if prompts_by_source is not None:
-        prompt_files = _finalize_vscode_prompt_recommendation_paths(
-            repo_path, _vscode_prompt_recommendation_paths_from_sources(prompts_by_source)
-        )
+    if prompts_by_source is not None:
+        prompt_files = _vscode_prompt_recommendation_paths_from_sources(prompts_by_source)
     else:
         prompt_files = _finalize_vscode_prompt_recommendation_paths(
             repo_path, _vscode_prompt_paths_from_full_catalog(repo_path)
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/specfact_cli/utils/ide_setup.py` around lines 909 - 924, The current
branch treats a non-None prompts_by_source incorrectly when it is an empty dict
and ends up repopulating recommendations from the full catalog; change the logic
so an explicit empty export is preserved by passing the exact exported set (e.g.
an empty list) into _finalize_vscode_prompt_recommendation_paths instead of
falling back to _vscode_prompt_paths_from_full_catalog. Concretely, update the
if branch around prompts_by_source to detect empty mappings and call
_finalize_vscode_prompt_recommendation_paths(repo_path,
_vscode_prompt_recommendation_paths_from_sources(prompts_by_source) or [] ) (or
otherwise pass [] when prompts_by_source is empty) so
merge_vscode_settings_prompt_recommendations receives the true exported set
(honoring strip_specfact_github_from_existing and
explicit_replace_unparseable/force).
♻️ Duplicate comments (1)
scripts/verify_safe_project_writes.py (1)

24-54: ⚠️ Potential issue | 🟠 Major

import json as <alias> still bypasses offender detection.

Line 47-53 only flags attribute calls when the base name is exactly json.
import json as js + js.loads(...) will evade this gate.

Suggested fix
 _JSON_IO_NAMES = frozenset({"load", "dump", "loads", "dumps"})
 
+def _json_module_aliases(tree: ast.AST) -> set[str]:
+    aliases: set[str] = {"json"}
+    for node in ast.walk(tree):
+        if isinstance(node, ast.Import):
+            for alias in node.names:
+                if alias.name == "json":
+                    aliases.add(alias.asname or "json")
+    return aliases
+
 def _collect_json_io_offenders(tree: ast.AST) -> list[tuple[int, str]]:
     import_aliases = _json_import_aliases(tree)
+    module_aliases = _json_module_aliases(tree)
     offenders: list[tuple[int, str]] = []
     for node in ast.walk(tree):
         if not isinstance(node, ast.Call):
             continue
         func = node.func
@@
         if (
             isinstance(func, ast.Attribute)
             and isinstance(func.value, ast.Name)
-            and func.value.id == "json"
+            and func.value.id in module_aliases
             and func.attr in _JSON_IO_NAMES
         ):
             offenders.append((node.lineno, f"json.{func.attr}"))

As per coding guidelines: the unsafe-write rejection gate must reliably reject direct unsafe JSON writes on protected paths.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/verify_safe_project_writes.py` around lines 24 - 54,
_json_import_aliases only records names from "from json import ..." but misses
module aliases from "import json as js", so _collect_json_io_offenders doesn't
catch calls like js.loads(...). Update _json_import_aliases to also scan
ast.Import nodes and map module aliases (e.g., map "js" -> "json"), then in
_collect_json_io_offenders check attribute bases against that map (e.g., if
isinstance(func.value, ast.Name) and import_aliases.get(func.value.id) == "json"
and func.attr in _JSON_IO_NAMES) so both "json.loads" and "js.loads" are
flagged; keep existing mapping for from-imports so Name-based calls still work.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@openspec/changes/profile-04-safe-project-artifact-writes/tasks.md`:
- Around line 3-29: Several checklist lines in tasks.md exceed the 120-character
markdown limit (e.g., the "Create
`bugfix/profile-04-safe-project-artifact-writes`..." checklist line and long
items such as the CI/static guard/verification lines including "3.3 Implement
the CI/static guard..." and the long run-quality-gates line); wrap those long
markdown checklist lines to under 120 characters at logical breakpoints (between
clauses or before parentheticals) without splitting code spans or changing the
checklist semantics, preserving backticks around tokens like
`bugfix/profile-04-safe-project-artifact-writes`,
`scripts/verify_safe_project_writes.py`, and `hatch run ...` commands, then run
your markdown linter/formatter to confirm no lines exceed 120 chars and commit
the updated tasks.md.

In `@openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md`:
- Around line 18-59: Wrap any Markdown lines longer than 120 characters in
TDD_EVIDENCE.md: break the long command and narrative lines such as the
multi-command bash block starting with "hatch run pytest
tests/unit/utils/test_project_artifact_write.py \", the long "hatch run specfact
code review run --json --out .specfact/code-review.json \\" line, and the long
paragraph beginning "- **Pass (2026-04-12)**: after `hatch run specfact module
install nold-ai/specfact-codebase`..." into multiple shorter lines (soft-wrap
within paragraphs or use continued indented code lines for command blocks) so
every line is <=120 chars, preserving markdown structure and code block
formatting.

In `@src/specfact_cli/utils/project_artifact_write.py`:
- Around line 211-235: Resolve repo_root = repo_path.resolve() and then after
computing settings_path = (repo_path / settings_relative).resolve(), validate
containment by ensuring settings_path is under repo_root (use
pathlib.Path.relative_to(repo_root) and catch ValueError or equivalent) before
performing any filesystem mutations (parent.mkdir, read_text, backup, or
write_text). If the check fails, abort early (raise/return) instead of creating
directories or touching files outside the repo; keep existing calls to
_write_new_vscode_settings_file, _load_root_dict_from_settings_text, and
_merge_chat_and_recommendations but only invoke them after the containment check
passes.
- Around line 95-124: The settings handling currently uses json.loads/json.dumps
in _load_root_dict_from_settings_text (and its write path) which will reject or
strip JSONC comments/trailing-commas used by VS Code; switch to a JSONC-aware
parser/serializer (e.g., comment-preserving loader) for both parsing and
round-trip dumping to preserve user comments and formatting. Also harden the
path validation around settings_relative_nonblank by, after resolving the
candidate path (settings_path = (repo_path / settings_relative).resolve()),
asserting settings_path.is_relative_to(repo_path.resolve()) (or equivalent
containment check) so symlinks cannot escape the repo boundary before any
write/backup operations. Ensure both fixes reference the json.loads/json.dumps
sites and the settings_relative_nonblank/resolve usage so the parser change and
the containment check are applied where settings are read, backed up, and
written.

In `@tests/unit/scripts/test_verify_safe_project_writes.py`:
- Around line 30-46: Add a new unit test to
tests/unit/scripts/test_verify_safe_project_writes.py that mirrors
test_collect_json_io_flags_aliased_json_import but covers the "import json as
js" form: load the module via _load_verify_module(), parse a snippet like
'import json as js\nx = None\njs.dump(x, open("f","w"))', call
mod._collect_json_io_offenders(tree) and assert that one of the offender names
equals "json.dump"; this ensures the _collect_json_io_offenders logic recognizes
attribute calls through module aliasing (reference _collect_json_io_offenders
and _load_verify_module to locate the implementation).

In `@tests/unit/utils/test_contract_predicates.py`:
- Around line 43-45: Add a negative test case to
tests/unit/utils/test_contract_predicates.py to assert
cp.prompt_files_all_strings returns False for mixed-type input; specifically, in
the test_prompt_files_all_strings function add an assertion using a list
containing at least one non-string (e.g., ["a", 1] or ["a", None]) and assert
cp.prompt_files_all_strings(<mixed_list>) is False to catch regressions in type
filtering for the prompt_files_all_strings function.

---

Outside diff comments:
In `@src/specfact_cli/utils/ide_setup.py`:
- Around line 909-924: The current branch treats a non-None prompts_by_source
incorrectly when it is an empty dict and ends up repopulating recommendations
from the full catalog; change the logic so an explicit empty export is preserved
by passing the exact exported set (e.g. an empty list) into
_finalize_vscode_prompt_recommendation_paths instead of falling back to
_vscode_prompt_paths_from_full_catalog. Concretely, update the if branch around
prompts_by_source to detect empty mappings and call
_finalize_vscode_prompt_recommendation_paths(repo_path,
_vscode_prompt_recommendation_paths_from_sources(prompts_by_source) or [] ) (or
otherwise pass [] when prompts_by_source is empty) so
merge_vscode_settings_prompt_recommendations receives the true exported set
(honoring strip_specfact_github_from_existing and
explicit_replace_unparseable/force).

---

Duplicate comments:
In `@scripts/verify_safe_project_writes.py`:
- Around line 24-54: _json_import_aliases only records names from "from json
import ..." but misses module aliases from "import json as js", so
_collect_json_io_offenders doesn't catch calls like js.loads(...). Update
_json_import_aliases to also scan ast.Import nodes and map module aliases (e.g.,
map "js" -> "json"), then in _collect_json_io_offenders check attribute bases
against that map (e.g., if isinstance(func.value, ast.Name) and
import_aliases.get(func.value.id) == "json" and func.attr in _JSON_IO_NAMES) so
both "json.loads" and "js.loads" are flagged; keep existing mapping for
from-imports so Name-based calls still work.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 79f4fce9-05bd-4732-9790-5cb67f99fc8f

📥 Commits

Reviewing files that changed from the base of the PR and between 3a76aac and 75cf864.

📒 Files selected for processing (11)
  • docs/getting-started/installation.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • scripts/verify_safe_project_writes.py
  • src/specfact_cli/utils/contract_predicates.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_project_artifact_write.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Tests (Python 3.12)
🧰 Additional context used
📓 Path-based instructions (14)
**/*.{md,mdc}

📄 CodeRabbit inference engine (.cursor/rules/markdown-rules.mdc)

**/*.{md,mdc}: Do not use more than one consecutive blank line anywhere in the document (MD012: No Multiple Consecutive Blank Lines)
Fenced code blocks should be surrounded by blank lines (MD031: Fenced Code Blocks)
Lists should be surrounded by blank lines (MD032: Lists)
Files must end with a single empty line (MD047: Files Must End With Single Newline)
Lines should not have trailing spaces (MD009: No Trailing Spaces)
Use asterisks (**) for strong emphasis, not underscores (__) (MD050: Strong Style)
Fenced code blocks must have a language specified (MD040: Fenced Code Language)
Headers should increment by one level at a time (MD001: Header Increment)
Headers should be surrounded by blank lines (MD022: Headers Should Be Surrounded By Blank Lines)
Only one top-level header (H1) is allowed per document (MD025: Single H1 Header)
Use consistent list markers, preferring dashes (-) for unordered lists (MD004: List Style)
Nested unordered list items should be indented consistently, typically by 2 spaces (MD007: Unordered List Indentation)
Use exactly one space after the list marker (e.g., -, *, +, 1.) (MD030: Spaces After List Markers)
Use incrementing numbers for ordered lists (MD029: Ordered List Item Prefix)
Enclose bare URLs in angle brackets or format them as links (MD034: Bare URLs)
Don't use spaces immediately inside code spans (MD038: Spaces Inside Code Spans)
Use consistent indentation (usually 2 or 4 spaces) throughout markdown files
Keep line length under 120 characters in markdown files
Use reference-style links for better readability in markdown files
Use a trailing slash for directory paths in markdown files
Ensure proper escaping of special characters in markdown files

Files:

  • docs/getting-started/installation.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
docs/**/*.md

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Update architecture documentation in docs/ for architecture changes, state machine documentation for FSM modifications, interface documentation for API changes, and configuration guides for configuration changes. DO NOT create internal docs in specfact-cli repo folder that should not be visible to end users; use the respective internal repository instead.

Files:

  • docs/getting-started/installation.md

⚙️ CodeRabbit configuration file

docs/**/*.md: User-facing accuracy: CLI examples match current behavior; preserve Jekyll front matter;
call out when README/docs index need sync.

Files:

  • docs/getting-started/installation.md
**/*.md

📄 CodeRabbit inference engine (.cursorrules)

Avoid markdown linting errors (refer to markdown-rules)

Files:

  • docs/getting-started/installation.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
**/test_*.py

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

**/test_*.py: Write tests first in test-driven development (TDD) using the Red-Green-Refactor cycle
Ensure each test is independent and repeatable with no shared state between tests
Organize Python imports in tests using unittest.mock for Mock and patch
Use setup_method() for test initialization and Arrange-Act-Assert pattern in test files
Use @pytest.mark.asyncio decorator for async test functions in Python
Organize test files in structure: tests/unit/, tests/integration/, tests/e2e/ by module

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

**/*.py: Maintain minimum 80% test coverage, with 100% coverage for critical paths in Python code
Use clear naming and self-documenting code, preferring clear names over comments
Ensure each function/class has a single clear purpose (Single Responsibility Principle)
Extract common patterns to avoid code duplication (DRY principle)
Apply SOLID object-oriented design principles in Python code
Use type hints everywhere in Python code and enable basedpyright strict mode
Use Pydantic models for data validation and serialization in Python
Use async/await for I/O operations in Python code
Use context managers for resource management in Python
Use dataclasses for simple data containers in Python
Enforce maximum line length of 120 characters in Python code
Use 4 spaces for indentation in Python code (no tabs)
Use 2 blank lines between classes and 1 blank line between methods in Python
Organize imports in order: Standard library → Third party → Local in Python files
Use snake_case for variables and functions in Python
Use PascalCase for class names in Python
Use UPPER_SNAKE_CASE for constants in Python
Use leading underscore (_) for private methods in Python classes
Use snake_case for Python file names
Enable basedpyright strict mode with strict type checking configuration in Python
Use Google-style docstrings for functions and classes in Python
Include comprehensive exception handling with specific exception types in Python code
Use logging with structured context (extra parameters) instead of print statements
Use retry logic with tenacity decorators (@retry) for operations that might fail
Use Pydantic BaseSettings for environment-based configuration in Python
Validate user input using Pydantic validators in Python models
Use @lru_cache and Redis-based caching for expensive calculations in Python
Run code formatting with Black (120 character line length) and isort in Python
Run type checking with basedpyright on all Python files
Run linting with ruff and pylint on all Pyth...

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • src/specfact_cli/utils/contract_predicates.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • scripts/verify_safe_project_writes.py
  • src/specfact_cli/utils/ide_setup.py
  • tests/unit/utils/test_project_artifact_write.py
  • src/specfact_cli/utils/project_artifact_write.py
tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Tests must be meaningful and test actual functionality, cover both success and failure cases, be independent and repeatable, and have clear, descriptive names. NO EXCEPTIONS - no placeholder or empty tests.

tests/**/*.py: Trim low-value unit tests when a contract covers the same assertion (type/shape/raises on negative checks)
Delete tests that only assert input validation, datatype/shape enforcement, or raises on negative conditions now guarded by contracts and runtime typing
Convert repeated edge-case permutations into one Hypothesis property with contracts acting as oracles

Secret redaction via LoggerSetup.redact_secrets must be covered by unit tests

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py

⚙️ CodeRabbit configuration file

tests/**/*.py: Contract-first testing: meaningful scenarios, not redundant assertions already covered by
contracts. Flag flakiness, environment coupling, and missing coverage for changed behavior.

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py
@(src|tests)/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Linting must pass with no errors using: pylint src tests

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • src/specfact_cli/utils/contract_predicates.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • src/specfact_cli/utils/ide_setup.py
  • tests/unit/utils/test_project_artifact_write.py
  • src/specfact_cli/utils/project_artifact_write.py
**/*.{py,pyi}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{py,pyi}: After any code changes, follow these steps in order: (1) Apply linting and formatting to ensure code quality: hatch run format, (2) Type checking: hatch run type-check (basedpyright), (3) Contract-first approach: Run hatch run contract-test for contract validation, (4) Run full test suite: hatch test --cover -v, (5) Verify all tests pass and contracts are satisfied, (6) Fix any issues and repeat steps until all tests pass
All public APIs must have @icontract decorators and @beartype type checking
Use Pydantic models for all data structures with data validation
Only write high-value comments if at all. Avoid talking to the user through comments

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/modules/init/test_init_ide_prompt_selection.py
  • src/specfact_cli/utils/contract_predicates.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • scripts/verify_safe_project_writes.py
  • src/specfact_cli/utils/ide_setup.py
  • tests/unit/utils/test_project_artifact_write.py
  • src/specfact_cli/utils/project_artifact_write.py
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

src/**/*.py: All code changes must be followed by running the full test suite using the smart test system.
All Python files in src/ and tools/ directories must have corresponding test files in tests/ directory. If you modify src/common/logger_setup.py, you MUST have tests/unit/common/test_logger_setup.py. NO EXCEPTIONS - even small changes require tests.
All new Python runtime code files must have corresponding test files created BEFORE committing the code. NO EXCEPTIONS - no code without tests.
Test Coverage Validation: Run hatch run smart-test-unit for modified files, hatch run smart-test-folder for modified directories, and hatch run smart-test-full before committing. ALL TESTS MUST PASS.
All components must support TEST_MODE=true environment variable with test-specific behavior defined as: if os.environ.get('TEST_MODE') == 'true': # test-specific behavior
Use src/common/logger_setup.py for all logging via: from common.logger_setup import get_logger; logger = get_logger(name)
Use src/common/redis_client.py with fallback for Redis operations via: from common.redis_client import get_redis_client; redis_client = get_redis_client()
Type checking must pass with no errors using: mypy .
Test coverage must meet or exceed 80% total coverage. New code must have corresponding tests. Modified code must maintain or improve coverage. Critical paths must have 100% coverage.
Use Pydantic v2 validation for all context and data schemas.

Add/update contracts on new or modified public APIs, stateful classes and adapters using icontract decorators and beartype runtime type checks

src/**/*.py: Meaningful Naming — identifiers reveal intent; avoid abbreviations. Identifiers in src/ must use snake_case (modules/functions), PascalCase (classes), UPPER_SNAKE_CASE (constants). Avoid single-letter names outside short loop variables.
KISS — keep functions and modules small and single-purpose. Maximum function length: 120 lines (Phase A error threshold). Maximum cyclomati...

Files:

  • src/specfact_cli/utils/contract_predicates.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
src/specfact_cli/**/*.py

⚙️ CodeRabbit configuration file

src/specfact_cli/**/*.py: Focus on modular CLI architecture: lazy module loading, registry/bootstrap patterns, and
dependency direction. Flag breaking changes to public APIs, Pydantic models, and resource
bundling. Verify @icontract + @beartype on public surfaces; prefer centralized logging
(get_bridge_logger) over print().

Files:

  • src/specfact_cli/utils/contract_predicates.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
openspec/changes/**/*.md

📄 CodeRabbit inference engine (.cursorrules)

For /opsx:archive (Archive change): Include module signing and cleanup in final tasks. Agents MUST run openspec archive <change-id> from repo root (no manual mv under openspec/changes/archive/)

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
openspec/**/*.md

⚙️ CodeRabbit configuration file

openspec/**/*.md: Treat as specification source of truth: proposal/tasks/spec deltas vs. code behavior,
CHANGE_ORDER consistency, and scenario coverage. Surface drift between OpenSpec and
implementation.

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
scripts/**/*.py

⚙️ CodeRabbit configuration file

scripts/**/*.py: Deterministic tooling: subprocess safety, Hatch integration, and parity with documented
quality gates (format, type-check, module signing).

Files:

  • scripts/verify_safe_project_writes.py
openspec/**/{proposal.md,tasks.md,design.md,spec.md}

📄 CodeRabbit inference engine (.cursor/rules/automatic-openspec-workflow.mdc)

openspec/**/{proposal.md,tasks.md,design.md,spec.md}: Apply openspec/config.yaml project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase
After implementation, validate the change with openspec validate <change-id> --strict; fix validation errors in proposal, specs, design, or tasks and re-validate until passing before considering the change complete

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
🧠 Learnings (28)
📓 Common learnings
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : Apply `openspec/config.yaml` project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to docs/**/*.md : Update architecture documentation in docs/ for architecture changes, state machine documentation for FSM modifications, interface documentation for API changes, and configuration guides for configuration changes. DO NOT create internal docs in specfact-cli repo folder that should not be visible to end users; use the respective internal repository instead.

Applied to files:

  • docs/getting-started/installation.md
📚 Learning: 2026-04-10T22:42:04.362Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/session_startup_instructions.mdc:0-0
Timestamp: 2026-04-10T22:42:04.362Z
Learning: For OpenSpec changes when a sibling `specfact-cli-internal/` checkout exists, read internal wiki guidance in `docs/agent-rules/40-openspec-and-tdd.md` and consult `wiki/hot.md`, `wiki/graph.md`, and relevant `wiki/concepts/*.md` files

Applied to files:

  • docs/getting-started/installation.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-03-25T21:32:08.987Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/markdown-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:08.987Z
Learning: Applies to **/*.{md,mdc} : Keep line length under 120 characters in markdown files

Applied to files:

  • docs/getting-started/installation.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: If `openspec` command is not found or if specfact-cli workspace or openspec/ directory is not accessible, do not modify application code unless the user explicitly confirms to proceed without OpenSpec

Applied to files:

  • docs/getting-started/installation.md
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Trim low-value unit tests when a contract covers the same assertion (type/shape/raises on negative checks)

Applied to files:

  • tests/unit/utils/test_contract_predicates.py
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Delete tests that only assert input validation, datatype/shape enforcement, or raises on negative conditions now guarded by contracts and runtime typing

Applied to files:

  • tests/unit/utils/test_contract_predicates.py
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Convert repeated edge-case permutations into one Hypothesis property with contracts acting as oracles

Applied to files:

  • tests/unit/utils/test_contract_predicates.py
📚 Learning: 2026-03-31T22:38:25.299Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/clean-code-principles.mdc:0-0
Timestamp: 2026-03-31T22:38:25.299Z
Learning: Applies to src/**/*.py : Use `icontract` (`require`/`ensure`) and `beartype` on all public APIs in `src/`

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to src/**/*.py : Add/update contracts on new or modified public APIs, stateful classes and adapters using `icontract` decorators and `beartype` runtime type checks

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to **/*.{py,pyi} : All public APIs must have `icontract` decorators and `beartype` type checking

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-04-10T22:42:21.849Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-10T22:42:21.849Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: For `/opsx:ff` (Fast-Forward Change Creation): OPSX provides change scaffolding and artifact templates. AGENTS.md requires explicitly adding: Worktree creation task as Step 1 in tasks.md (not just 'create branch'), TDD_EVIDENCE.md tracking task in section 2 (Tests), Documentation research task per `openspec/config.yaml`, Module signing quality gate if applicable, Worktree cleanup steps in final section

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : After implementation, validate the change with `openspec validate <change-id> --strict`; fix validation errors in proposal, specs, design, or tasks and re-validate until passing before considering the change complete

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to openspec/changes/**/*.md : For `/opsx:archive` (Archive change): Include module signing and cleanup in final tasks. Agents MUST run `openspec archive <change-id>` from repo root (no manual `mv` under `openspec/changes/archive/`)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:31:55.908Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/estimation-bias-prevention.mdc:0-0
Timestamp: 2026-03-25T21:31:55.908Z
Learning: Use TDD with quality gates (contract-driven, test-driven implementation, quality gate validation, documentation) as the standard development pattern

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Before implementing code changes, run `openspec validate <change-id> --strict` to validate the OpenSpec change and optionally run `/wf-validate-change <change-id>` for breaking-change and dependency analysis; do not proceed to implementation until validation passes or user explicitly overrides

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: For `/opsx:apply` (Implementation): OPSX provides task iteration and progress tracking. AGENTS.md requires verification before each task: Confirm you are IN a worktree (not primary checkout) before modifying code, Record failing test evidence in `TDD_EVIDENCE.md` BEFORE implementing, Record passing test evidence AFTER implementation, Run quality gates from worktree (format, type-check, contract-test), GPG-signed commits (`git commit -S`), PR to `dev` branch (never direct push)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : Apply `openspec/config.yaml` project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • src/specfact_cli/utils/ide_setup.py
  • tests/unit/utils/test_project_artifact_write.py
  • src/specfact_cli/utils/project_artifact_write.py
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to {src,tools}/**/*.{js,ts,jsx,tsx,py},**/*.test.{js,ts,jsx,tsx,py},**/*.spec.{js,ts,jsx,tsx,py} : Do not add, modify, or delete any application code in src/, tools/, tests, or significant docs until an OpenSpec change (new or delta) is created and validated, unless the user explicitly opts out with 'skip openspec', 'direct implementation', 'simple fix', or 'just fix it'

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: When creating implementation plans, task lists, or OpenSpec tasks.md, ALWAYS explicitly verify and include: (1) Worktree creation from `origin/dev` (not `git checkout -b`), (2) `hatch env create` in the worktree, (3) Pre-flight checks (`hatch run smart-test-status`, `hatch run contract-test-status`), (4) Worktree cleanup steps post-merge, (5) Self-check: 'Have I followed AGENTS.md Git Worktree Policy section?'

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:26.519Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-10T22:41:26.519Z
Learning: Enforce the clean-code review gate through `hatch run specfact code review run --json --out .specfact/code-review.json`

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: All development work MUST use git worktrees per AGENTS.md Git Worktree Policy. Never create branches with `git checkout -b` in the primary checkout. Create worktree from origin/dev: `git worktree add ../specfact-cli-worktrees/<type>/<slug> -b <branch-name> origin/dev` where allowed types are: `feature/`, `bugfix/`, `hotfix/`, `chore/`. Forbidden in worktrees: `dev`, `main`. After creating worktree: `cd ../specfact-cli-worktrees/<type>/<slug>`. Bootstrap Hatch in worktree: `hatch env create`. Run pre-flight checks: `hatch run smart-test-status` and `hatch run contract-test-status`. Do all implementation work from the worktree, never from primary checkout. After PR merge: cleanup with `git worktree remove`, `git branch -d`, `git worktree prune`

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Before executing ANY workflow command (`/opsx:ff`, `/opsx:apply`, `/opsx:continue`, etc.), perform the Pre-Execution Checklist: (1) Git Worktree - create if task creates branches/modifies code, (2) TDD Evidence - create `TDD_EVIDENCE.md` if behavior changes, (3) Documentation - include documentation research if changes affect user-facing behavior, (4) Module Signing - include signature verification if changes modify bundled modules, (5) Confirmation - state clearly that pre-execution checklist is complete and AGENTS.md compliance is confirmed

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:42:21.849Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-10T22:42:21.849Z
Learning: Run the required verification and quality gates for the touched scope before finalization

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Always finish each output by listing: (1) Which rulesets have been applied (e.g., `.cursorrules`, `AGENTS.md`, specific `.cursor/rules/*.mdc`), (2) Confirmation of Git Worktree Policy compliance (if applicable), (3) Which AI (LLM) provider and model version you are using

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to **/*.{py,pyi} : After any code changes, follow these steps in order: (1) Apply linting and formatting to ensure code quality: `hatch run format`, (2) Type checking: `hatch run type-check` (basedpyright), (3) Contract-first approach: Run `hatch run contract-test` for contract validation, (4) Run full test suite: `hatch test --cover -v`, (5) Verify all tests pass and contracts are satisfied, (6) Fix any issues and repeat steps until all tests pass

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: When implementation is complete and merged, run `openspec archive <change-id>` from the repository root to merge delta specs into openspec/specs/ and move the change under openspec/changes/archive/; do not manually move folders or use --skip-specs or --no-validate without explicit user confirmation

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
🪛 GitHub Check: Linting (ruff, pylint, safe-write guard)
src/specfact_cli/utils/project_artifact_write.py

[warning] 195-195:
Type of "is_file" is unknown (reportUnknownMemberType)


[warning] 195-195:
Type of "exists" is unknown (reportUnknownMemberType)


[warning] 174-174:
Type of "is_file" is unknown (reportUnknownMemberType)


[warning] 150-150:
Type of "get" is partially unknown
  Type of "get" is "Overload[(key: Unknown, default: None = None, /) -> (Unknown | None), (key: Unknown, default: Unknown, /) -> Unknown, (key: Unknown, default: _T@get, /) -> (Unknown | _T@get)]" (reportUnknownMemberType)

🪛 GitHub Check: Type Checking (basedpyright)
src/specfact_cli/utils/project_artifact_write.py

[warning] 195-195:
Type of "is_file" is unknown (reportUnknownMemberType)


[warning] 195-195:
Type of "exists" is unknown (reportUnknownMemberType)


[warning] 174-174:
Type of "is_file" is unknown (reportUnknownMemberType)


[warning] 150-150:
Type of "get" is partially unknown
  Type of "get" is "Overload[(key: Unknown, default: None = None, /) -> (Unknown | None), (key: Unknown, default: Unknown, /) -> Unknown, (key: Unknown, default: _T@get, /) -> (Unknown | _T@get)]" (reportUnknownMemberType)

🔇 Additional comments (3)
docs/getting-started/installation.md (1)

78-81: Safety contract wording is accurate and release-ready.

Lines 78-81 correctly describe merge behavior, fail-safe handling for malformed JSON/chat, and --force replacement only after backup under .specfact/recovery/.

As per coding guidelines: “Document the user-facing safety contract for specfact init ide on VS Code…stop without rewriting…--force…after a timestamped backup under .specfact/recovery/.”

tests/unit/modules/init/test_init_ide_prompt_selection.py (1)

155-176: Excellent regression coverage for non-destructive failure path.

Line 175 now verifies malformed .vscode/settings.json remains untouched when merge fails, which is the core safety contract.

src/specfact_cli/utils/contract_predicates.py (1)

55-73: Path and prompt predicates are tightened correctly.

Line 55-66 now blocks absolute/traversal paths, and Line 68-73 enforces string-only prompt entries with runtime contracts in place.

Based on learnings: public APIs in src/** should use @icontract and @beartype.

Comment thread openspec/changes/profile-04-safe-project-artifact-writes/tasks.md Outdated
Comment thread openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md Outdated
Comment thread src/specfact_cli/utils/project_artifact_write.py
Comment thread src/specfact_cli/utils/project_artifact_write.py Outdated
Comment thread tests/unit/scripts/test_verify_safe_project_writes.py
Comment thread tests/unit/utils/test_contract_predicates.py
- merge_vscode_settings: resolve containment before mkdir/write; JSON5 load/dump
  (JSONC comments; trailing_commas=False for strict JSON output)
- ide_setup: empty prompts_by_source skips catalog fallback (_finalize allow_empty_fallback)
- verify_safe_project_writes: detect import json as js attribute calls
- contract_predicates: prompt_files_all_strings accepts list[Any] for mixed-type checks
- Tests: symlink escape, JSONC merge, empty export strip, import-json-as-js guard
- tasks.md / TDD_EVIDENCE: wrap lines to <=120 chars; CHANGELOG + json5 dep + setup.py sync

Made-with: Cursor
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md (1)

36-38: 🧹 Nitpick | 🔵 Trivial

Minor: Some lines still exceed 120 characters.

Several narrative lines remain over the markdown width limit (e.g., lines 36-38, 42-43, 52-53, 58-59). Consider soft-wrapping to keep lint clean.

As per coding guidelines: "Keep line length under 120 characters in markdown files."

Also applies to: 42-43, 52-53, 58-59

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md`
around lines 36 - 38, The markdown has several narrative lines exceeding the
120-character limit (notably the "**Module signatures**" bullet containing the
long command `hatch run ./scripts/verify-modules-signature.py
--require-signature`); soft-wrap those long sentences so no line exceeds 120
chars, breaking phrases at natural word boundaries and keeping inline
code/commands intact on their own or wrapped across lines if needed; update the
affected paragraphs (the module signatures bullet and the other long narrative
lines) to multiple shorter lines so the markdown linter passes while preserving
exact commands and meaning.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@openspec/changes/profile-04-safe-project-artifact-writes/tasks.md`:
- Around line 3-4: Update the worktree bootstrap checklist in tasks.md to add
explicit pre-flight status checks: after the step that bootstraps Hatch in the
worktree (the `hatch env create` bootstrap step referenced in the checklist),
insert two commands to run pre-flight checks — `hatch run smart-test-status` and
`hatch run contract-test-status` — so the execution plan enforces these status
checks immediately following the Hatch environment creation.
- Around line 43-45: The quality-gate checklist in tasks.md is missing the
required full coverage test command; update the checklist near the "Run quality
gates" items (the list including `hatch run format`, `hatch run type-check`,
`hatch run lint`, `hatch run yaml-lint`, `hatch run contract-test`, and `hatch
run smart-test`) to include `hatch test --cover -v` as one of the steps so the
documented verification sequence matches the coding guideline requiring the full
test suite with coverage.

In `@src/specfact_cli/utils/project_artifact_write.py`:
- Line 196: The postcondition lambda used with the ensure decorator currently
lacks an explicit type for its parameter (lambda result: result.exists() and
result.is_file()), which triggers pyright's reportUnknownMemberType; fix by
narrowing the type or suppressing the warning—for example change the lambda to
perform an isinstance check like: lambda result: isinstance(result,
pathlib.Path) and result.exists() and result.is_file(), or add a pyright
suppression comment (e.g. # pyright: ignore[reportUnknownMemberType]) on the
decorator line; ensure you import pathlib if using isinstance and keep the
ensure decorator and the is_file/exists checks intact.

---

Duplicate comments:
In `@openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md`:
- Around line 36-38: The markdown has several narrative lines exceeding the
120-character limit (notably the "**Module signatures**" bullet containing the
long command `hatch run ./scripts/verify-modules-signature.py
--require-signature`); soft-wrap those long sentences so no line exceeds 120
chars, breaking phrases at natural word boundaries and keeping inline
code/commands intact on their own or wrapped across lines if needed; update the
affected paragraphs (the module signatures bullet and the other long narrative
lines) to multiple shorter lines so the markdown linter passes while preserving
exact commands and meaning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 505eef03-162b-4c94-8eb6-a7cf844856e9

📥 Commits

Reviewing files that changed from the base of the PR and between 75cf864 and 13d12d6.

📒 Files selected for processing (12)
  • CHANGELOG.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • pyproject.toml
  • scripts/verify_safe_project_writes.py
  • setup.py
  • src/specfact_cli/utils/contract_predicates.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_project_artifact_write.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Type Checking (basedpyright)
  • GitHub Check: Tests (Python 3.12)
  • GitHub Check: Compatibility (Python 3.11)
  • GitHub Check: Linting (ruff, pylint, safe-write guard)
  • GitHub Check: Contract-First CI
🧰 Additional context used
📓 Path-based instructions (17)
**/test_*.py

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

**/test_*.py: Write tests first in test-driven development (TDD) using the Red-Green-Refactor cycle
Ensure each test is independent and repeatable with no shared state between tests
Organize Python imports in tests using unittest.mock for Mock and patch
Use setup_method() for test initialization and Arrange-Act-Assert pattern in test files
Use @pytest.mark.asyncio decorator for async test functions in Python
Organize test files in structure: tests/unit/, tests/integration/, tests/e2e/ by module

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_project_artifact_write.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

**/*.py: Maintain minimum 80% test coverage, with 100% coverage for critical paths in Python code
Use clear naming and self-documenting code, preferring clear names over comments
Ensure each function/class has a single clear purpose (Single Responsibility Principle)
Extract common patterns to avoid code duplication (DRY principle)
Apply SOLID object-oriented design principles in Python code
Use type hints everywhere in Python code and enable basedpyright strict mode
Use Pydantic models for data validation and serialization in Python
Use async/await for I/O operations in Python code
Use context managers for resource management in Python
Use dataclasses for simple data containers in Python
Enforce maximum line length of 120 characters in Python code
Use 4 spaces for indentation in Python code (no tabs)
Use 2 blank lines between classes and 1 blank line between methods in Python
Organize imports in order: Standard library → Third party → Local in Python files
Use snake_case for variables and functions in Python
Use PascalCase for class names in Python
Use UPPER_SNAKE_CASE for constants in Python
Use leading underscore (_) for private methods in Python classes
Use snake_case for Python file names
Enable basedpyright strict mode with strict type checking configuration in Python
Use Google-style docstrings for functions and classes in Python
Include comprehensive exception handling with specific exception types in Python code
Use logging with structured context (extra parameters) instead of print statements
Use retry logic with tenacity decorators (@retry) for operations that might fail
Use Pydantic BaseSettings for environment-based configuration in Python
Validate user input using Pydantic validators in Python models
Use @lru_cache and Redis-based caching for expensive calculations in Python
Run code formatting with Black (120 character line length) and isort in Python
Run type checking with basedpyright on all Python files
Run linting with ruff and pylint on all Pyth...

Files:

  • tests/unit/utils/test_contract_predicates.py
  • setup.py
  • src/specfact_cli/utils/contract_predicates.py
  • scripts/verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Tests must be meaningful and test actual functionality, cover both success and failure cases, be independent and repeatable, and have clear, descriptive names. NO EXCEPTIONS - no placeholder or empty tests.

tests/**/*.py: Trim low-value unit tests when a contract covers the same assertion (type/shape/raises on negative checks)
Delete tests that only assert input validation, datatype/shape enforcement, or raises on negative conditions now guarded by contracts and runtime typing
Convert repeated edge-case permutations into one Hypothesis property with contracts acting as oracles

Secret redaction via LoggerSetup.redact_secrets must be covered by unit tests

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_project_artifact_write.py
  • tests/unit/scripts/test_verify_safe_project_writes.py

⚙️ CodeRabbit configuration file

tests/**/*.py: Contract-first testing: meaningful scenarios, not redundant assertions already covered by
contracts. Flag flakiness, environment coupling, and missing coverage for changed behavior.

Files:

  • tests/unit/utils/test_contract_predicates.py
  • tests/unit/utils/test_project_artifact_write.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
@(src|tests)/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Linting must pass with no errors using: pylint src tests

Files:

  • tests/unit/utils/test_contract_predicates.py
  • src/specfact_cli/utils/contract_predicates.py
  • tests/unit/utils/test_project_artifact_write.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
**/*.{py,pyi}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{py,pyi}: After any code changes, follow these steps in order: (1) Apply linting and formatting to ensure code quality: hatch run format, (2) Type checking: hatch run type-check (basedpyright), (3) Contract-first approach: Run hatch run contract-test for contract validation, (4) Run full test suite: hatch test --cover -v, (5) Verify all tests pass and contracts are satisfied, (6) Fix any issues and repeat steps until all tests pass
All public APIs must have @icontract decorators and @beartype type checking
Use Pydantic models for all data structures with data validation
Only write high-value comments if at all. Avoid talking to the user through comments

Files:

  • tests/unit/utils/test_contract_predicates.py
  • setup.py
  • src/specfact_cli/utils/contract_predicates.py
  • scripts/verify_safe_project_writes.py
  • tests/unit/utils/test_project_artifact_write.py
  • tests/unit/scripts/test_verify_safe_project_writes.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
{src/__init__.py,pyproject.toml,setup.py}

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

{src/__init__.py,pyproject.toml,setup.py}: Update src/init.py first as primary source of truth for package version, then pyproject.toml and setup.py
Maintain version synchronization across src/init.py, pyproject.toml, and setup.py

Files:

  • setup.py
  • pyproject.toml
{pyproject.toml,setup.py,src/__init__.py}

📄 CodeRabbit inference engine (.cursor/rules/testing-and-build-guide.mdc)

Manually update version numbers in pyproject.toml, setup.py, and src/init.py when making a formal version change

Files:

  • setup.py
  • pyproject.toml
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

src/**/*.py: All code changes must be followed by running the full test suite using the smart test system.
All Python files in src/ and tools/ directories must have corresponding test files in tests/ directory. If you modify src/common/logger_setup.py, you MUST have tests/unit/common/test_logger_setup.py. NO EXCEPTIONS - even small changes require tests.
All new Python runtime code files must have corresponding test files created BEFORE committing the code. NO EXCEPTIONS - no code without tests.
Test Coverage Validation: Run hatch run smart-test-unit for modified files, hatch run smart-test-folder for modified directories, and hatch run smart-test-full before committing. ALL TESTS MUST PASS.
All components must support TEST_MODE=true environment variable with test-specific behavior defined as: if os.environ.get('TEST_MODE') == 'true': # test-specific behavior
Use src/common/logger_setup.py for all logging via: from common.logger_setup import get_logger; logger = get_logger(name)
Use src/common/redis_client.py with fallback for Redis operations via: from common.redis_client import get_redis_client; redis_client = get_redis_client()
Type checking must pass with no errors using: mypy .
Test coverage must meet or exceed 80% total coverage. New code must have corresponding tests. Modified code must maintain or improve coverage. Critical paths must have 100% coverage.
Use Pydantic v2 validation for all context and data schemas.

Add/update contracts on new or modified public APIs, stateful classes and adapters using icontract decorators and beartype runtime type checks

src/**/*.py: Meaningful Naming — identifiers reveal intent; avoid abbreviations. Identifiers in src/ must use snake_case (modules/functions), PascalCase (classes), UPPER_SNAKE_CASE (constants). Avoid single-letter names outside short loop variables.
KISS — keep functions and modules small and single-purpose. Maximum function length: 120 lines (Phase A error threshold). Maximum cyclomati...

Files:

  • src/specfact_cli/utils/contract_predicates.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
src/specfact_cli/**/*.py

⚙️ CodeRabbit configuration file

src/specfact_cli/**/*.py: Focus on modular CLI architecture: lazy module loading, registry/bootstrap patterns, and
dependency direction. Flag breaking changes to public APIs, Pydantic models, and resource
bundling. Verify @icontract + @beartype on public surfaces; prefer centralized logging
(get_bridge_logger) over print().

Files:

  • src/specfact_cli/utils/contract_predicates.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
scripts/**/*.py

⚙️ CodeRabbit configuration file

scripts/**/*.py: Deterministic tooling: subprocess safety, Hatch integration, and parity with documented
quality gates (format, type-check, module signing).

Files:

  • scripts/verify_safe_project_writes.py
**/*.{md,mdc}

📄 CodeRabbit inference engine (.cursor/rules/markdown-rules.mdc)

**/*.{md,mdc}: Do not use more than one consecutive blank line anywhere in the document (MD012: No Multiple Consecutive Blank Lines)
Fenced code blocks should be surrounded by blank lines (MD031: Fenced Code Blocks)
Lists should be surrounded by blank lines (MD032: Lists)
Files must end with a single empty line (MD047: Files Must End With Single Newline)
Lines should not have trailing spaces (MD009: No Trailing Spaces)
Use asterisks (**) for strong emphasis, not underscores (__) (MD050: Strong Style)
Fenced code blocks must have a language specified (MD040: Fenced Code Language)
Headers should increment by one level at a time (MD001: Header Increment)
Headers should be surrounded by blank lines (MD022: Headers Should Be Surrounded By Blank Lines)
Only one top-level header (H1) is allowed per document (MD025: Single H1 Header)
Use consistent list markers, preferring dashes (-) for unordered lists (MD004: List Style)
Nested unordered list items should be indented consistently, typically by 2 spaces (MD007: Unordered List Indentation)
Use exactly one space after the list marker (e.g., -, *, +, 1.) (MD030: Spaces After List Markers)
Use incrementing numbers for ordered lists (MD029: Ordered List Item Prefix)
Enclose bare URLs in angle brackets or format them as links (MD034: Bare URLs)
Don't use spaces immediately inside code spans (MD038: Spaces Inside Code Spans)
Use consistent indentation (usually 2 or 4 spaces) throughout markdown files
Keep line length under 120 characters in markdown files
Use reference-style links for better readability in markdown files
Use a trailing slash for directory paths in markdown files
Ensure proper escaping of special characters in markdown files

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • CHANGELOG.md
**/*.md

📄 CodeRabbit inference engine (.cursorrules)

Avoid markdown linting errors (refer to markdown-rules)

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • CHANGELOG.md
openspec/changes/**/*.md

📄 CodeRabbit inference engine (.cursorrules)

For /opsx:archive (Archive change): Include module signing and cleanup in final tasks. Agents MUST run openspec archive <change-id> from repo root (no manual mv under openspec/changes/archive/)

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
openspec/**/*.md

⚙️ CodeRabbit configuration file

openspec/**/*.md: Treat as specification source of truth: proposal/tasks/spec deltas vs. code behavior,
CHANGE_ORDER consistency, and scenario coverage. Surface drift between OpenSpec and
implementation.

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
openspec/**/{proposal.md,tasks.md,design.md,spec.md}

📄 CodeRabbit inference engine (.cursor/rules/automatic-openspec-workflow.mdc)

openspec/**/{proposal.md,tasks.md,design.md,spec.md}: Apply openspec/config.yaml project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase
After implementation, validate the change with openspec validate <change-id> --strict; fix validation errors in proposal, specs, design, or tasks and re-validate until passing before considering the change complete

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
pyproject.toml

📄 CodeRabbit inference engine (.cursorrules)

When updating the version in pyproject.toml, ensure it's newer than the latest PyPI version. The CI/CD pipeline will automatically publish to PyPI only if the new version is greater than the published version

Files:

  • pyproject.toml
CHANGELOG.md

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

Include new version entries at the top of CHANGELOG.md when updating versions

Update CHANGELOG.md with all code changes as part of version control requirements.

Update CHANGELOG.md to document all significant changes under Added, Fixed, Changed, or Removed sections when making a version change

Files:

  • CHANGELOG.md
🧠 Learnings (48)
📓 Common learnings
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : Apply `openspec/config.yaml` project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Trim low-value unit tests when a contract covers the same assertion (type/shape/raises on negative checks)

Applied to files:

  • tests/unit/utils/test_contract_predicates.py
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Delete tests that only assert input validation, datatype/shape enforcement, or raises on negative conditions now guarded by contracts and runtime typing

Applied to files:

  • tests/unit/utils/test_contract_predicates.py
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to tests/**/*.py : Convert repeated edge-case permutations into one Hypothesis property with contracts acting as oracles

Applied to files:

  • tests/unit/utils/test_contract_predicates.py
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to @(pyproject.toml|setup.py|src/__init__.py|src/specfact_cli/__init__.py) : Maintain synchronized versions across pyproject.toml, setup.py, src/__init__.py, and src/specfact_cli/__init__.py.

Applied to files:

  • setup.py
  • pyproject.toml
  • CHANGELOG.md
📚 Learning: 2026-03-31T22:38:25.299Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/clean-code-principles.mdc:0-0
Timestamp: 2026-03-31T22:38:25.299Z
Learning: Applies to src/**/*.py : Use `icontract` (`require`/`ensure`) and `beartype` on all public APIs in `src/`

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to src/**/*.py : Add/update contracts on new or modified public APIs, stateful classes and adapters using `icontract` decorators and `beartype` runtime type checks

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to **/*.{py,pyi} : All public APIs must have `icontract` decorators and `beartype` type checking

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-04-10T22:41:26.519Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-10T22:41:26.519Z
Learning: Applies to **/*.py : Public APIs require icontract and beartype decorators

Applied to files:

  • src/specfact_cli/utils/contract_predicates.py
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: For `/opsx:ff` (Fast-Forward Change Creation): OPSX provides change scaffolding and artifact templates. AGENTS.md requires explicitly adding: Worktree creation task as Step 1 in tasks.md (not just 'create branch'), TDD_EVIDENCE.md tracking task in section 2 (Tests), Documentation research task per `openspec/config.yaml`, Module signing quality gate if applicable, Worktree cleanup steps in final section

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:42:21.849Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-10T22:42:21.849Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:42:04.362Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/session_startup_instructions.mdc:0-0
Timestamp: 2026-04-10T22:42:04.362Z
Learning: For OpenSpec changes when a sibling `specfact-cli-internal/` checkout exists, read internal wiki guidance in `docs/agent-rules/40-openspec-and-tdd.md` and consult `wiki/hot.md`, `wiki/graph.md`, and relevant `wiki/concepts/*.md` files

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to openspec/changes/**/*.md : For `/opsx:archive` (Archive change): Include module signing and cleanup in final tasks. Agents MUST run `openspec archive <change-id>` from repo root (no manual `mv` under `openspec/changes/archive/`)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : After implementation, validate the change with `openspec validate <change-id> --strict`; fix validation errors in proposal, specs, design, or tasks and re-validate until passing before considering the change complete

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Before implementing code changes, run `openspec validate <change-id> --strict` to validate the OpenSpec change and optionally run `/wf-validate-change <change-id>` for breaking-change and dependency analysis; do not proceed to implementation until validation passes or user explicitly overrides

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: When creating implementation plans, task lists, or OpenSpec tasks.md, ALWAYS explicitly verify and include: (1) Worktree creation from `origin/dev` (not `git checkout -b`), (2) `hatch env create` in the worktree, (3) Pre-flight checks (`hatch run smart-test-status`, `hatch run contract-test-status`), (4) Worktree cleanup steps post-merge, (5) Self-check: 'Have I followed AGENTS.md Git Worktree Policy section?'

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:31:55.908Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/estimation-bias-prevention.mdc:0-0
Timestamp: 2026-03-25T21:31:55.908Z
Learning: Use TDD with quality gates (contract-driven, test-driven implementation, quality gate validation, documentation) as the standard development pattern

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: When implementation is complete and merged, run `openspec archive <change-id>` from the repository root to merge delta specs into openspec/specs/ and move the change under openspec/changes/archive/; do not manually move folders or use --skip-specs or --no-validate without explicit user confirmation

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : Apply `openspec/config.yaml` project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • tests/unit/utils/test_project_artifact_write.py
  • src/specfact_cli/utils/ide_setup.py
  • src/specfact_cli/utils/project_artifact_write.py
📚 Learning: 2026-03-25T21:32:08.987Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/markdown-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:08.987Z
Learning: Applies to **/*.{md,mdc} : Keep line length under 120 characters in markdown files

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to **/*.py : Enforce maximum line length of 120 characters in Python code

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:33:22.650Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/yaml-and-workflows.md:0-0
Timestamp: 2026-03-25T21:33:22.650Z
Learning: Applies to .yamllint : Ensure .yamllint configuration enforces line-length of 140 characters, ignores workflows, and enforces trailing spaces and final newline

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:26.519Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-10T22:41:26.519Z
Learning: Enforce the clean-code review gate through `hatch run specfact code review run --json --out .specfact/code-review.json`

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • pyproject.toml
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: For `/opsx:apply` (Implementation): OPSX provides task iteration and progress tracking. AGENTS.md requires verification before each task: Confirm you are IN a worktree (not primary checkout) before modifying code, Record failing test evidence in `TDD_EVIDENCE.md` BEFORE implementing, Record passing test evidence AFTER implementation, Run quality gates from worktree (format, type-check, contract-test), GPG-signed commits (`git commit -S`), PR to `dev` branch (never direct push)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: All development work MUST use git worktrees per AGENTS.md Git Worktree Policy. Never create branches with `git checkout -b` in the primary checkout. Create worktree from origin/dev: `git worktree add ../specfact-cli-worktrees/<type>/<slug> -b <branch-name> origin/dev` where allowed types are: `feature/`, `bugfix/`, `hotfix/`, `chore/`. Forbidden in worktrees: `dev`, `main`. After creating worktree: `cd ../specfact-cli-worktrees/<type>/<slug>`. Bootstrap Hatch in worktree: `hatch env create`. Run pre-flight checks: `hatch run smart-test-status` and `hatch run contract-test-status`. Do all implementation work from the worktree, never from primary checkout. After PR merge: cleanup with `git worktree remove`, `git branch -d`, `git worktree prune`

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Before executing ANY workflow command (`/opsx:ff`, `/opsx:apply`, `/opsx:continue`, etc.), perform the Pre-Execution Checklist: (1) Git Worktree - create if task creates branches/modifies code, (2) TDD Evidence - create `TDD_EVIDENCE.md` if behavior changes, (3) Documentation - include documentation research if changes affect user-facing behavior, (4) Module Signing - include signature verification if changes modify bundled modules, (5) Confirmation - state clearly that pre-execution checklist is complete and AGENTS.md compliance is confirmed

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to {src,tools}/**/*.{js,ts,jsx,tsx,py},**/*.test.{js,ts,jsx,tsx,py},**/*.spec.{js,ts,jsx,tsx,py} : Do not add, modify, or delete any application code in src/, tools/, tests, or significant docs until an OpenSpec change (new or delta) is created and validated, unless the user explicitly opts out with 'skip openspec', 'direct implementation', 'simple fix', or 'just fix it'

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:42:21.849Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-10T22:42:21.849Z
Learning: Run the required verification and quality gates for the touched scope before finalization

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Always finish each output by listing: (1) Which rulesets have been applied (e.g., `.cursorrules`, `AGENTS.md`, specific `.cursor/rules/*.mdc`), (2) Confirmation of Git Worktree Policy compliance (if applicable), (3) Which AI (LLM) provider and model version you are using

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:32:08.987Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/markdown-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:08.987Z
Learning: Applies to **/*.{md,mdc} : Lines should not have trailing spaces (MD009: No Trailing Spaces)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-31T22:38:25.299Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/clean-code-principles.mdc:0-0
Timestamp: 2026-03-31T22:38:25.299Z
Learning: Applies to src/**/*.py : KISS — keep functions and modules small and single-purpose. Maximum function length: 120 lines (Phase A error threshold). Maximum cyclomatic complexity: 12 (radon `cc` threshold).

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:32:08.987Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/markdown-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:08.987Z
Learning: Applies to **/*.{md,mdc} : Lists should be surrounded by blank lines (MD032: Lists)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to **/*.md : Avoid markdown linting errors (refer to markdown-rules)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to **/*.{py,pyi} : After any code changes, follow these steps in order: (1) Apply linting and formatting to ensure code quality: `hatch run format`, (2) Type checking: `hatch run type-check` (basedpyright), (3) Contract-first approach: Run `hatch run contract-test` for contract validation, (4) Run full test suite: `hatch test --cover -v`, (5) Verify all tests pass and contracts are satisfied, (6) Fix any issues and repeat steps until all tests pass

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • pyproject.toml
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to .github/workflows/*.{yml,yaml} : Validate GitHub workflow files using `hatch run lint-workflows` before committing

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:33:22.650Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/yaml-and-workflows.md:0-0
Timestamp: 2026-03-25T21:33:22.650Z
Learning: Run `hatch run yaml-check-all` in CI and before pull requests to validate all YAML and workflow files

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to **/*.yaml : YAML files must pass linting using: hatch run yaml-lint with relaxed policy.

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Applies to **/*.{yml,yaml} : Validate YAML configuration files locally using `hatch run yaml-lint` before committing

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:33:22.650Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/yaml-and-workflows.md:0-0
Timestamp: 2026-03-25T21:33:22.650Z
Learning: Applies to .github/workflows/*.{yml,yaml} : Format GitHub Actions workflows using `hatch run workflows-fmt` and lint them with `hatch run workflows-lint` after editing

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to **/*.py : Use Python 3.12 as the target Python version

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to **/*.py : Run linting with ruff and pylint on all Python files

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Use `hatch test` command for running tests instead of direct pytest usage to ensure proper Python matrix, dependency resolution, environment variables, and coverage reports

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to @(src|tests)/**/*.py : Linting must pass with no errors using: pylint src tests

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to **/*.py : Run type checking with basedpyright on all Python files

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to src/**/*.py : Test Coverage Validation: Run hatch run smart-test-unit for modified files, hatch run smart-test-folder for modified directories, and hatch run smart-test-full before committing. ALL TESTS MUST PASS.

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Before making a pull request, locally run format, lint, contract tests, and full test suite: `hatch run format`, `hatch run lint`, `hatch run contract-test`, `hatch test --cover -v`

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to src/**/*.py : Type checking must pass with no errors using: mypy .

Applied to files:

  • pyproject.toml
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to src/**/*.py : All code changes must be followed by running the full test suite using the smart test system.

Applied to files:

  • pyproject.toml
🪛 GitHub Check: Type Checking (basedpyright)
src/specfact_cli/utils/project_artifact_write.py

[warning] 196-196:
Type of "is_file" is unknown (reportUnknownMemberType)


[warning] 196-196:
Type of "exists" is unknown (reportUnknownMemberType)


[warning] 175-175:
Type of "is_file" is unknown (reportUnknownMemberType)


[warning] 151-151:
Type of "get" is partially unknown
  Type of "get" is "Overload[(key: Unknown, default: None = None, /) -> (Unknown | None), (key: Unknown, default: Unknown, /) -> Unknown, (key: Unknown, default: _T@get, /) -> (Unknown | _T@get)]" (reportUnknownMemberType)

🔇 Additional comments (26)
setup.py (1)

10-10: Version/dependency packaging updates look consistent and release-safe.

The 0.45.2 bump and json5>=0.9.28 addition align with the safe settings merge runtime path.

Also applies to: 34-34

tests/unit/utils/test_contract_predicates.py (1)

36-40: Predicate regression coverage is solid and focused.

These assertions capture both valid/invalid path constraints and mixed-type prompt file inputs without redundant noise.

Also applies to: 43-47

openspec/changes/profile-04-safe-project-artifact-writes/tasks.md (1)

53-55: Strict OpenSpec validation gate is correctly captured.

Good addition of the explicit openspec validate profile-04-safe-project-artifact-writes --strict sign-off step with evidence expectations.

src/specfact_cli/utils/contract_predicates.py (1)

56-67: New predicates are correctly constrained for safe-write contracts.

Both additions are single-purpose, typed, and decorated with @icontract/@beartype, and they directly reinforce repository-bound path and prompt-file input safety.

Also applies to: 69-73

scripts/verify_safe_project_writes.py (2)

24-58: AST detection logic is appropriately targeted for the regression boundary.

Catching both json.<fn> and from json import <fn> usage patterns strengthens the lint gate against bypasses.


61-78: Main gate behavior is CI-friendly and operationally clear.

Exit-code contract (0/1/2) and stderr diagnostics are clean for deterministic lint orchestration.

CHANGELOG.md (1)

13-30: Release notes are well-structured and policy-compliant.

This entry is clear, scoped to the safe artifact-write initiative, and correctly placed at the top with a proper Fixed breakdown.

pyproject.toml (1)

7-7: LGTM! Well-coordinated dependency and tooling updates.

The changes establish a solid foundation for the safe-write policy:

  1. Version bump (0.45.2) — ensure src/__init__.py and src/specfact_cli/__init__.py stay synchronized per project conventions.
  2. json5 dependency — appropriate choice for JSONC-compatible parsing; VS Code's settings.json commonly includes comments and trailing commas.
  3. setuptools pin (<82) — pragmatic fix for the Semgrep/pkg_resources compatibility chain.
  4. lint gate extensionverify_safe_project_writes.py now runs as part of hatch run lint, enforcing the safe-write contract at CI time.

Based on learnings: "Maintain synchronized versions across pyproject.toml, setup.py, src/init.py, and src/specfact_cli/init.py."

Also applies to: 87-88, 109-109, 177-178, 212-212

openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md (1)

1-64: Well-documented TDD evidence trail.

The artifact correctly captures the failing-first/passing-after cycle, quality gates (format, type-check, lint, contract-test, smart-test), module signature verification, code review gate, and OpenSpec strict validation — aligning with the project's contract-first development workflow and OpenSpec traceability requirements.

tests/unit/scripts/test_verify_safe_project_writes.py (3)

37-41: Good: Module-alias test case added.

This test (test_collect_json_io_flags_import_json_as_module_alias) covers the import json as js form, addressing the previously flagged gap in alias detection coverage. The test validates that attribute-style calls through module aliases are properly detected by _collect_json_io_offenders.


12-19: LGTM with minor note on path brittleness.

The parents[3] calculation works for the current test location (tests/unit/scripts/). If the test file moves, this will break silently. Consider extracting a shared test utility or adding a guard assertion on the script path existence.


44-53: Solid end-to-end verification.

The subprocess execution test ensures the gate script passes against the actual repository state — a good regression lock that the ide_setup.py module routes settings I/O through the sanctioned project_artifact_write helper.

tests/unit/utils/test_project_artifact_write.py (5)

21-46: Excellent symlink escape test.

This test validates the path containment check by creating a symlink that escapes tmp_path. The try/finally cleanup pattern and platform-aware skip logic (symlink_to availability, OSError on unsupported platforms) make this robust across environments. The assertion on "outside the repository" matches the error message in merge_vscode_settings_prompt_recommendations.


49-71: JSONC handling validated.

This test confirms that VS Code settings with // comments are correctly parsed via JSON5 and that unrelated keys (python.defaultInterpreterPath) survive the merge while chat.promptFilesRecommendations is updated.


124-139: Malformed JSON fail-safe behavior confirmed.

Validates the contract: without force=True, malformed JSON raises StructuredJsonDocumentError and the original file content is preserved unchanged. This is the core "fail-safe" guarantee from the PR objectives.


165-182: Force-replace with backup validated.

Confirms that force=True creates a timestamped backup under .specfact/recovery/ before replacing unparseable settings with safe defaults containing the expected prompt recommendations.


201-219: Good: Force coercion test for non-object chat added.

This test addresses the past review suggestion — it validates that when chat is a string (invalid type) and force=True, the file is backed up and chat is coerced to a proper dict with the expected promptFilesRecommendations.

src/specfact_cli/utils/ide_setup.py (3)

476-482: Good DRY extraction.

The _handle_structured_json_document_error helper consolidates the duplicate error handling pattern from both _copy_template_files_to_ide and copy_prompts_by_source_to_ide, addressing the past review feedback. The NoReturn return type annotation correctly signals this function never returns normally.


812-829: allow_empty_fallback enables explicit empty exports.

This parameter allows create_vscode_settings to distinguish between "no prompts discovered" (fallback to defaults) and "explicitly empty prompts_by_source" (strip existing SpecFact entries, add nothing new). This aligns with the selective --prompts export behavior described in the PR objectives.


889-944: Clean delegation to merge_vscode_settings_prompt_recommendations.

The refactored create_vscode_settings now delegates all JSON parsing, merging, and error recovery to the centralized helper in project_artifact_write.py. Key points:

  • force maps to explicit_replace_unparseable (explicit consent for destructive replace)
  • strip_specfact_github_from_existing is True when prompts_by_source is set (selective export mode)
  • The StructuredJsonDocumentError propagates to callers, who handle it via _handle_structured_json_document_error

This architectural boundary ensures all IDE settings I/O flows through the policy-constrained helper, which the verify_safe_project_writes.py gate now enforces.

src/specfact_cli/utils/project_artifact_write.py (6)

31-36: Well-defined error hierarchy.

ProjectArtifactWriteError as the base and StructuredJsonDocumentError as a specialization provides a clean exception taxonomy. Callers can catch the specific error for JSON merge failures while still having a broader category for general artifact write failures.


39-50: ProjectWriteMode enum documented for future use.

The docstring now explicitly notes this is "reserved for future write-dispatch routing" — addressing the past review feedback about YAGNI concerns. Keeping the enum aligned with the OpenSpec narrative without immediate call-site wiring is a reasonable architectural placeholder.


171-188: Robust backup with collision handling.

The backup function now:

  1. Uses microsecond-precision timestamps (%Y%m%dT%H%M%S.%fZ)
  2. Includes a collision-avoidance loop that appends numeric suffixes

This addresses the past review concern about rapid successive backups within the same second.


215-222: Symlink escape prevention implemented.

The containment check (settings_path.relative_to(repo_root)) after resolution ensures symlinks cannot escape the repository boundary. This addresses the security concern from the past review about writing outside the trust boundary.


191-249: Solid contract-first public API.

merge_vscode_settings_prompt_recommendations demonstrates the project's contract-first philosophy:

  • Preconditions: @require for repo existence, directory type, non-blank relative path, string list
  • Postconditions: @ensure guarantees the returned path exists and is a file
  • Runtime type checking: @beartype decorator
  • JSON5 parsing: Handles JSONC (comments, trailing commas) common in VS Code configs
  • Fail-safe behavior: Raises StructuredJsonDocumentError unless explicit_replace_unparseable=True
  • Recovery path: Timestamped backups under .specfact/recovery/

The docstring correctly notes that serialized output is canonical JSON (comments are not preserved from input) — this is acceptable given the merge semantics.


52-59: Path normalization in _is_specfact_github_prompt_path is intentional and correct.

The function is designed to accept paths with leading dots (as stored in VS Code settings: .github/prompts/specfact.01-import.prompt.md) and normalize them for comparison. The lstrip("./") converts .github/prompts/ to github/prompts/ before validation—this is confirmed by comprehensive test coverage including both Unix and Windows path formats in test_is_specfact_github_prompt_path_only_specfact_named_prompts. The pattern is consistent with how the function integrates with _strip_specfact_github_prompt_recommendations for selective export filtering.

Comment thread openspec/changes/profile-04-safe-project-artifact-writes/tasks.md Outdated
Comment thread openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
Comment thread src/specfact_cli/utils/project_artifact_write.py Outdated
…sure

- tasks 1.1: hatch env create then smart-test-status and contract-test-status
- tasks 4.3: add hatch test --cover -v to quality gates
- TDD_EVIDENCE: shorter module-signatures and report lines (<=120 cols)
- project_artifact_write: isinstance(result, Path) in @Ensure postconditions

Made-with: Cursor
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md`:
- Around line 27-34: The verification evidence block is missing the claimed
full-suite coverage gate output; run and record the coverage command `hatch test
--cover -v` (or remove/uncheck the corresponding checklist entry in tasks.md)
and include its console output in the passing evidence section so the documented
gate matches the checklist; update the evidence block to show the `hatch test
--cover -v` invocation and its success summary to restore consistency between
the passing evidence and the checklist in tasks.md.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: be459b2d-dea0-4c71-9121-545ff29b9026

📥 Commits

Reviewing files that changed from the base of the PR and between 13d12d6 and 002bacd.

📒 Files selected for processing (3)
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • src/specfact_cli/utils/project_artifact_write.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Linting (ruff, pylint, safe-write guard)
  • GitHub Check: Tests (Python 3.12)
  • GitHub Check: Compatibility (Python 3.11)
  • GitHub Check: Contract-First CI
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{md,mdc}

📄 CodeRabbit inference engine (.cursor/rules/markdown-rules.mdc)

**/*.{md,mdc}: Do not use more than one consecutive blank line anywhere in the document (MD012: No Multiple Consecutive Blank Lines)
Fenced code blocks should be surrounded by blank lines (MD031: Fenced Code Blocks)
Lists should be surrounded by blank lines (MD032: Lists)
Files must end with a single empty line (MD047: Files Must End With Single Newline)
Lines should not have trailing spaces (MD009: No Trailing Spaces)
Use asterisks (**) for strong emphasis, not underscores (__) (MD050: Strong Style)
Fenced code blocks must have a language specified (MD040: Fenced Code Language)
Headers should increment by one level at a time (MD001: Header Increment)
Headers should be surrounded by blank lines (MD022: Headers Should Be Surrounded By Blank Lines)
Only one top-level header (H1) is allowed per document (MD025: Single H1 Header)
Use consistent list markers, preferring dashes (-) for unordered lists (MD004: List Style)
Nested unordered list items should be indented consistently, typically by 2 spaces (MD007: Unordered List Indentation)
Use exactly one space after the list marker (e.g., -, *, +, 1.) (MD030: Spaces After List Markers)
Use incrementing numbers for ordered lists (MD029: Ordered List Item Prefix)
Enclose bare URLs in angle brackets or format them as links (MD034: Bare URLs)
Don't use spaces immediately inside code spans (MD038: Spaces Inside Code Spans)
Use consistent indentation (usually 2 or 4 spaces) throughout markdown files
Keep line length under 120 characters in markdown files
Use reference-style links for better readability in markdown files
Use a trailing slash for directory paths in markdown files
Ensure proper escaping of special characters in markdown files

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
**/*.md

📄 CodeRabbit inference engine (.cursorrules)

Avoid markdown linting errors (refer to markdown-rules)

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
openspec/changes/**/*.md

📄 CodeRabbit inference engine (.cursorrules)

For /opsx:archive (Archive change): Include module signing and cleanup in final tasks. Agents MUST run openspec archive <change-id> from repo root (no manual mv under openspec/changes/archive/)

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
openspec/**/{proposal.md,tasks.md,design.md,spec.md}

📄 CodeRabbit inference engine (.cursor/rules/automatic-openspec-workflow.mdc)

openspec/**/{proposal.md,tasks.md,design.md,spec.md}: Apply openspec/config.yaml project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase
After implementation, validate the change with openspec validate <change-id> --strict; fix validation errors in proposal, specs, design, or tasks and re-validate until passing before considering the change complete

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
openspec/**/*.md

⚙️ CodeRabbit configuration file

openspec/**/*.md: Treat as specification source of truth: proposal/tasks/spec deltas vs. code behavior,
CHANGE_ORDER consistency, and scenario coverage. Surface drift between OpenSpec and
implementation.

Files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/python-github-rules.mdc)

**/*.py: Maintain minimum 80% test coverage, with 100% coverage for critical paths in Python code
Use clear naming and self-documenting code, preferring clear names over comments
Ensure each function/class has a single clear purpose (Single Responsibility Principle)
Extract common patterns to avoid code duplication (DRY principle)
Apply SOLID object-oriented design principles in Python code
Use type hints everywhere in Python code and enable basedpyright strict mode
Use Pydantic models for data validation and serialization in Python
Use async/await for I/O operations in Python code
Use context managers for resource management in Python
Use dataclasses for simple data containers in Python
Enforce maximum line length of 120 characters in Python code
Use 4 spaces for indentation in Python code (no tabs)
Use 2 blank lines between classes and 1 blank line between methods in Python
Organize imports in order: Standard library → Third party → Local in Python files
Use snake_case for variables and functions in Python
Use PascalCase for class names in Python
Use UPPER_SNAKE_CASE for constants in Python
Use leading underscore (_) for private methods in Python classes
Use snake_case for Python file names
Enable basedpyright strict mode with strict type checking configuration in Python
Use Google-style docstrings for functions and classes in Python
Include comprehensive exception handling with specific exception types in Python code
Use logging with structured context (extra parameters) instead of print statements
Use retry logic with tenacity decorators (@retry) for operations that might fail
Use Pydantic BaseSettings for environment-based configuration in Python
Validate user input using Pydantic validators in Python models
Use @lru_cache and Redis-based caching for expensive calculations in Python
Run code formatting with Black (120 character line length) and isort in Python
Run type checking with basedpyright on all Python files
Run linting with ruff and pylint on all Pyth...

Files:

  • src/specfact_cli/utils/project_artifact_write.py
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

src/**/*.py: All code changes must be followed by running the full test suite using the smart test system.
All Python files in src/ and tools/ directories must have corresponding test files in tests/ directory. If you modify src/common/logger_setup.py, you MUST have tests/unit/common/test_logger_setup.py. NO EXCEPTIONS - even small changes require tests.
All new Python runtime code files must have corresponding test files created BEFORE committing the code. NO EXCEPTIONS - no code without tests.
Test Coverage Validation: Run hatch run smart-test-unit for modified files, hatch run smart-test-folder for modified directories, and hatch run smart-test-full before committing. ALL TESTS MUST PASS.
All components must support TEST_MODE=true environment variable with test-specific behavior defined as: if os.environ.get('TEST_MODE') == 'true': # test-specific behavior
Use src/common/logger_setup.py for all logging via: from common.logger_setup import get_logger; logger = get_logger(name)
Use src/common/redis_client.py with fallback for Redis operations via: from common.redis_client import get_redis_client; redis_client = get_redis_client()
Type checking must pass with no errors using: mypy .
Test coverage must meet or exceed 80% total coverage. New code must have corresponding tests. Modified code must maintain or improve coverage. Critical paths must have 100% coverage.
Use Pydantic v2 validation for all context and data schemas.

Add/update contracts on new or modified public APIs, stateful classes and adapters using icontract decorators and beartype runtime type checks

src/**/*.py: Meaningful Naming — identifiers reveal intent; avoid abbreviations. Identifiers in src/ must use snake_case (modules/functions), PascalCase (classes), UPPER_SNAKE_CASE (constants). Avoid single-letter names outside short loop variables.
KISS — keep functions and modules small and single-purpose. Maximum function length: 120 lines (Phase A error threshold). Maximum cyclomati...

Files:

  • src/specfact_cli/utils/project_artifact_write.py
@(src|tests)/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/spec-fact-cli-rules.mdc)

Linting must pass with no errors using: pylint src tests

Files:

  • src/specfact_cli/utils/project_artifact_write.py
**/*.{py,pyi}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{py,pyi}: After any code changes, follow these steps in order: (1) Apply linting and formatting to ensure code quality: hatch run format, (2) Type checking: hatch run type-check (basedpyright), (3) Contract-first approach: Run hatch run contract-test for contract validation, (4) Run full test suite: hatch test --cover -v, (5) Verify all tests pass and contracts are satisfied, (6) Fix any issues and repeat steps until all tests pass
All public APIs must have @icontract decorators and @beartype type checking
Use Pydantic models for all data structures with data validation
Only write high-value comments if at all. Avoid talking to the user through comments

Files:

  • src/specfact_cli/utils/project_artifact_write.py
src/specfact_cli/**/*.py

⚙️ CodeRabbit configuration file

src/specfact_cli/**/*.py: Focus on modular CLI architecture: lazy module loading, registry/bootstrap patterns, and
dependency direction. Flag breaking changes to public APIs, Pydantic models, and resource
bundling. Verify @icontract + @beartype on public surfaces; prefer centralized logging
(get_bridge_logger) over print().

Files:

  • src/specfact_cli/utils/project_artifact_write.py
🧠 Learnings (33)
📓 Common learnings
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : Apply `openspec/config.yaml` project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : After implementation, validate the change with `openspec validate <change-id> --strict`; fix validation errors in proposal, specs, design, or tasks and re-validate until passing before considering the change complete

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: When creating implementation plans, task lists, or OpenSpec tasks.md, ALWAYS explicitly verify and include: (1) Worktree creation from `origin/dev` (not `git checkout -b`), (2) `hatch env create` in the worktree, (3) Pre-flight checks (`hatch run smart-test-status`, `hatch run contract-test-status`), (4) Worktree cleanup steps post-merge, (5) Self-check: 'Have I followed AGENTS.md Git Worktree Policy section?'

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: For `/opsx:ff` (Fast-Forward Change Creation): OPSX provides change scaffolding and artifact templates. AGENTS.md requires explicitly adding: Worktree creation task as Step 1 in tasks.md (not just 'create branch'), TDD_EVIDENCE.md tracking task in section 2 (Tests), Documentation research task per `openspec/config.yaml`, Module signing quality gate if applicable, Worktree cleanup steps in final section

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to openspec/changes/**/*.md : For `/opsx:archive` (Archive change): Include module signing and cleanup in final tasks. Agents MUST run `openspec archive <change-id>` from repo root (no manual `mv` under `openspec/changes/archive/`)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Before implementing code changes, run `openspec validate <change-id> --strict` to validate the OpenSpec change and optionally run `/wf-validate-change <change-id>` for breaking-change and dependency analysis; do not proceed to implementation until validation passes or user explicitly overrides

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Before executing ANY workflow command (`/opsx:ff`, `/opsx:apply`, `/opsx:continue`, etc.), perform the Pre-Execution Checklist: (1) Git Worktree - create if task creates branches/modifies code, (2) TDD Evidence - create `TDD_EVIDENCE.md` if behavior changes, (3) Documentation - include documentation research if changes affect user-facing behavior, (4) Module Signing - include signature verification if changes modify bundled modules, (5) Confirmation - state clearly that pre-execution checklist is complete and AGENTS.md compliance is confirmed

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to openspec/**/{proposal.md,tasks.md,design.md,spec.md} : Apply `openspec/config.yaml` project context and per-artifact rules (for proposal, specs, design, tasks) when creating or updating any OpenSpec change artifact in the specfact-cli codebase

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • src/specfact_cli/utils/project_artifact_write.py
📚 Learning: 2026-04-10T22:42:04.362Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/session_startup_instructions.mdc:0-0
Timestamp: 2026-04-10T22:42:04.362Z
Learning: For OpenSpec changes when a sibling `specfact-cli-internal/` checkout exists, read internal wiki guidance in `docs/agent-rules/40-openspec-and-tdd.md` and consult `wiki/hot.md`, `wiki/graph.md`, and relevant `wiki/concepts/*.md` files

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: Applies to {src,tools}/**/*.{js,ts,jsx,tsx,py},**/*.test.{js,ts,jsx,tsx,py},**/*.spec.{js,ts,jsx,tsx,py} : Do not add, modify, or delete any application code in src/, tools/, tests, or significant docs until an OpenSpec change (new or delta) is created and validated, unless the user explicitly opts out with 'skip openspec', 'direct implementation', 'simple fix', or 'just fix it'

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: For `/opsx:apply` (Implementation): OPSX provides task iteration and progress tracking. AGENTS.md requires verification before each task: Confirm you are IN a worktree (not primary checkout) before modifying code, Record failing test evidence in `TDD_EVIDENCE.md` BEFORE implementing, Record passing test evidence AFTER implementation, Run quality gates from worktree (format, type-check, contract-test), GPG-signed commits (`git commit -S`), PR to `dev` branch (never direct push)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:42:21.849Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-10T22:42:21.849Z
Learning: Run the required verification and quality gates for the touched scope before finalization

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Always finish each output by listing: (1) Which rulesets have been applied (e.g., `.cursorrules`, `AGENTS.md`, specific `.cursor/rules/*.mdc`), (2) Confirmation of Git Worktree Policy compliance (if applicable), (3) Which AI (LLM) provider and model version you are using

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:32:08.987Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/markdown-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:08.987Z
Learning: Applies to **/*.{md,mdc} : Keep line length under 120 characters in markdown files

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-03-25T21:33:22.650Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/yaml-and-workflows.md:0-0
Timestamp: 2026-03-25T21:33:22.650Z
Learning: Applies to .yamllint : Ensure .yamllint configuration enforces line-length of 140 characters, ignores workflows, and enforces trailing spaces and final newline

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-03-25T21:32:08.987Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/markdown-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:08.987Z
Learning: Applies to **/*.{md,mdc} : Lines should not have trailing spaces (MD009: No Trailing Spaces)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-31T22:38:25.299Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/clean-code-principles.mdc:0-0
Timestamp: 2026-03-31T22:38:25.299Z
Learning: Applies to src/**/*.py : KISS — keep functions and modules small and single-purpose. Maximum function length: 120 lines (Phase A error threshold). Maximum cyclomatic complexity: 12 (radon `cc` threshold).

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:32:29.182Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/python-github-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:29.182Z
Learning: Applies to **/*.py : Enforce maximum line length of 120 characters in Python code

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-03-25T21:32:08.987Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/markdown-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:08.987Z
Learning: Applies to **/*.{md,mdc} : Lists should be surrounded by blank lines (MD032: Lists)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to **/*.md : Avoid markdown linting errors (refer to markdown-rules)

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: All development work MUST use git worktrees per AGENTS.md Git Worktree Policy. Never create branches with `git checkout -b` in the primary checkout. Create worktree from origin/dev: `git worktree add ../specfact-cli-worktrees/<type>/<slug> -b <branch-name> origin/dev` where allowed types are: `feature/`, `bugfix/`, `hotfix/`, `chore/`. Forbidden in worktrees: `dev`, `main`. After creating worktree: `cd ../specfact-cli-worktrees/<type>/<slug>`. Bootstrap Hatch in worktree: `hatch env create`. Run pre-flight checks: `hatch run smart-test-status` and `hatch run contract-test-status`. Do all implementation work from the worktree, never from primary checkout. After PR merge: cleanup with `git worktree remove`, `git branch -d`, `git worktree prune`

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-04-10T22:41:19.077Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-10T22:41:19.077Z
Learning: Applies to **/*.{py,pyi} : After any code changes, follow these steps in order: (1) Apply linting and formatting to ensure code quality: `hatch run format`, (2) Type checking: `hatch run type-check` (basedpyright), (3) Contract-first approach: Run `hatch run contract-test` for contract validation, (4) Run full test suite: `hatch test --cover -v`, (5) Verify all tests pass and contracts are satisfied, (6) Fix any issues and repeat steps until all tests pass

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Before making a pull request, locally run format, lint, contract tests, and full test suite: `hatch run format`, `hatch run lint`, `hatch run contract-test`, `hatch test --cover -v`

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: After implementation, run quality gates (hatch run format, hatch run type-check, hatch run contract-test, hatch test or hatch run smart-test) to ensure all tests pass and contracts are satisfied

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:33:22.650Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/yaml-and-workflows.md:0-0
Timestamp: 2026-03-25T21:33:22.650Z
Learning: Run `hatch run yaml-check-all` in CI and before pull requests to validate all YAML and workflow files

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Run contract-first validation locally before committing: `hatch run contract-test-contracts`, `hatch run contract-test-exploration`, and `hatch run contract-test-scenarios`

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to src/**/*.py : Test Coverage Validation: Run hatch run smart-test-unit for modified files, hatch run smart-test-folder for modified directories, and hatch run smart-test-full before committing. ALL TESTS MUST PASS.

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:26.519Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-10T22:41:26.519Z
Learning: Enforce the clean-code review gate through `hatch run specfact code review run --json --out .specfact/code-review.json`

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-03-25T21:33:15.296Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/testing-and-build-guide.mdc:0-0
Timestamp: 2026-03-25T21:33:15.296Z
Learning: Use `hatch test` command for running tests instead of direct pytest usage to ensure proper Python matrix, dependency resolution, environment variables, and coverage reports

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-03-25T21:32:57.944Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/spec-fact-cli-rules.mdc:0-0
Timestamp: 2026-03-25T21:32:57.944Z
Learning: Applies to src/**/*.py : All code changes must be followed by running the full test suite using the smart test system.

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:41:54.419Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/automatic-openspec-workflow.mdc:0-0
Timestamp: 2026-04-10T22:41:54.419Z
Learning: When implementation is complete and merged, run `openspec archive <change-id>` from the repository root to merge delta specs into openspec/specs/ and move the change under openspec/changes/archive/; do not manually move folders or use --skip-specs or --no-validate without explicit user confirmation

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/tasks.md
📚 Learning: 2026-04-10T22:42:21.849Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-10T22:42:21.849Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
📚 Learning: 2026-03-25T21:31:55.908Z
Learnt from: CR
Repo: nold-ai/specfact-cli PR: 0
File: .cursor/rules/estimation-bias-prevention.mdc:0-0
Timestamp: 2026-03-25T21:31:55.908Z
Learning: Use TDD with quality gates (contract-driven, test-driven implementation, quality gate validation, documentation) as the standard development pattern

Applied to files:

  • openspec/changes/profile-04-safe-project-artifact-writes/TDD_EVIDENCE.md
🪛 GitHub Check: Type Checking (basedpyright)
src/specfact_cli/utils/project_artifact_write.py

[warning] 151-151:
Type of "get" is partially unknown
  Type of "get" is "Overload[(key: Unknown, default: None = None, /) -> (Unknown | None), (key: Unknown, default: Unknown, /) -> Unknown, (key: Unknown, default: _T@get, /) -> (Unknown | _T@get)]" (reportUnknownMemberType)

🔇 Additional comments (2)
openspec/changes/profile-04-safe-project-artifact-writes/tasks.md (2)

54-56: Strict OpenSpec validation gate is explicitly captured and looks correct.

This closes the prior sign-off gap and improves traceability of completion evidence.


44-45: No actionable issue: hatch run yaml-lint is correctly defined in pyproject.toml (line 227) and aligns with documented standards. The checklist task is reproducible as written.

			> Likely an incorrect or invalid review comment.

djm81 added 6 commits April 12, 2026 22:48
- verify_safe_project_writes: flatten json binding helpers; stderr writes
  instead of print; inline Import/ImportFrom loops to drop duplicate-shape DRY
- project_artifact_write: _VscodeChatMergeContext dataclass (KISS param count);
  typed chat_body cast before .get for pyright

Made-with: Cursor
Align passing evidence with tasks.md 4.3 full-suite coverage gate.

Made-with: Cursor
…ers)

Refactors high-parameter call sites into dataclasses/context objects and splits hot spots (export devops pipeline, smart_test_coverage incremental run, suggest_frontmatter, crosshair summary loop).

API: BridgeSync.export_change_proposals_to_devops(adapter_type, ExportChangeProposalsOptions | None); LoggerSetup.create_logger(name, LoggerCreateOptions | None); run_crosshair(path, CrosshairRunOptions | None).

Full specfact code review --scope full still reports error-severity kiss/radon findings (remaining nesting/LOC and param counts in ADO, analyzers, generators, source_scanner, module_installer, bundle-mapper, etc.). Gate PASS requires follow-up.

Made-with: Cursor
…ate_cache tests

- Insert check_doc_frontmatter into sys.modules before exec_module so
  dataclasses can resolve string annotations (fixes Docs Review / agent
  rules governance fixture).
- Call SmartCoverageManager._update_cache with _SmartCacheUpdate after
  signature refactor (fixes basedpyright reportCallIssue).

Made-with: Cursor
…ister verify_bundle script

- Monkeypatch/patch fakes now accept (module_id, options=None) matching
  install_module(module_id, InstallModuleOptions(...)).
- Read install_root, trust_non_official, non_interactive, reinstall from
  InstallModuleOptions in CLI command tests.
- Dynamic load of verify-bundle-published registers sys.modules before
  exec_module (same dataclass annotation issue as check_doc_frontmatter).

Made-with: Cursor
@djm81 djm81 merged commit 951f3ae into dev Apr 12, 2026
18 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in SpecFact CLI Apr 12, 2026
@djm81 djm81 mentioned this pull request Apr 12, 2026
41 tasks
djm81 added a commit that referenced this pull request Apr 13, 2026
* Archive delta validation change and update specs

* Update patch version

* Potential fix for pull request finding 'Empty except'

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>

* apply review fixes

* Add cli validation changes

* feat: launch central module marketplace lifecycle (#287)

* feat: launch module marketplace lifecycle and trust-first UX

Deliver the central module marketplace workflow with source-aware discovery, lifecycle management, and trust/publisher visibility so users can safely manage official vs local modules. This also aligns docs and OpenSpec artifacts with the shipped behavior, including command introspection and clearer install/uninstall guidance.

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

* fix: respect explicit discovery roots in module tests

Disable implicit legacy/workspace roots when explicit roots are passed to module discovery so isolated test roots are honored and deterministic.

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

* fix: enforce safe module extraction and upgrade reinstall

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: resolve bundle-mapper review defects with TDD evidence (#290)

* feat: add bundle-mapper module with confidence-based spec-to-bundle mapping

- BundleMapping model and BundleMapper engine (explicit label, historical, content similarity)
- Mapping history persistence and MappingRule (save_user_confirmed_mapping, load_bundle_mapping_config)
- Interactive UI (ask_bundle_mapping) with Rich confidence visualization
- Unit tests and TDD_EVIDENCE for bundle-mapper-01 (OpenSpec #121)

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

* fix(bundle-mapper): address PR review findings (P1/P2)

- P1 interactive: no default accept for low-confidence; use default only when conf >= 0.5
- P1 history: ignore empty key fields in item_keys_similar (only count non-empty matches)
- P2 engine: add historical weight only when hist_bundle == primary_bundle_id
- Add test_item_keys_similar_empty_fields_not_counted to lock empty-key behavior

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

* fix: address bundle-mapper review defects with tdd evidence

* test: make specmatic integration tests plugin-agnostic

---------

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

* feat:Add architecture review docs and findings to mitigate

* feat(backlog): add backlog add for interactive issue creation (#289)

* feat: add interactive backlog issue creation flow

* feat(backlog): add interactive issue creation and mapping setup

* fix: align backlog protocol test fakes and module manifest versions

* Fix type error

* fix(backlog): persist ado sprint and normalize github create id

* fix(backlog-core): address review findings for add/config/github

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* chore(openspec): archive completed changes and align architecture docs (#292)

* chore(openspec): archive completed changes and align architecture docs

* docs(architecture): refresh discrepancies report after arch-08 remediation

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs(change): Archive architecture discrepancy remediation change

* fix(codeql): preserve module contract marker and document fallback excepts

* fix(backlog): restore installed-runtime discovery parity and add backlog prompt (#294)

* fix(backlog): restore installed runtime discovery and add backlog prompt

* Archive bugfix change

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(version): sync manifests to 0.36.1 and archive backlog-core-04 (#297)

* fix(backlog): restore installed runtime discovery and add backlog prompt

* Archive bugfix change

* fix(version): sync built-in module manifests to 0.36.1

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden module lifecycle bootstrap and signing workflows (#299)

* fix: harden module lifecycle bootstrap and signing workflows

* fix: stabilize module signature hashing across environments

* fix: stabilize bundle module signature verification in CI

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* test: simplify monkeypatch callables in module_security tests

* Fix duplicate with statement

* chore(release): bump to v0.37.1 and harden signature gates

* test: fix init command regression assertions

* fix: release v0.37.2 with runtime crypto deps

* fix: address signature-backend warning and module version drift

* fix: use hatch build in PyPI publish workflow script (#304)

* fix: resolve startup module freshness home path dynamically (#306)

* fix: harden module signing workflow and reduce startup log noise

* test: align module migration compatibility with decoupled module versions

* fix: fail fast on invalid base ref in changed-only module signing

* fix: stabilize module precedence and backlog github mapping flow

* fix(module-registry): persist disables and correct bundled availability

* Re-sign module registry and fix / ignore local temp artifacts

* bump module registry version to 0.1.3

* fix(registry): restore protocol reporting logs in debug mode

* fix(backlog): harden refine writeback, prompts, and any-filter semantics (#311)

* fix(backlog): harden refine writeback, prompts, and daily any filters

* fix(github): default story type fallback to feature

* Fix format

* Fix codex review findings

* bump and sign changed modules

* chore(hooks): enforce module signature verification in pre-commit

* chore(hooks): add markdownlint to pre-commit checks

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(hooks,ado): correct format gate and enforce iteration on direct
  id lookup

* Apply review findings and fix tests

* Pin virtualenv < 21 to avoid incaopatibility failure

* fix: finalize backlog-core-06 ado comment API versioning (#314)

* fix(backlog): harden refine writeback, prompts, and daily any filters

* fix(github): default story type fallback to feature

* Fix format

* Fix codex review findings

* bump and sign changed modules

* chore(hooks): enforce module signature verification in pre-commit

* chore(hooks): add markdownlint to pre-commit checks

* fix: finalize backlog-core-06 ado comment api versioning and ci hatch pins

* fix: address review findings for formatter safety and ado metric patch guards

* docs(openspec): update CHANGE_ORDER status tracking

* fix(ado): apply iteration filter for direct issue_id lookup

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat: Advanced marketplace features (marketplace-02) - dependency resolution, aliases, custom registries, publishing (#318)

* feat: advanced marketplace features (marketplace-02) - dependency resolution, aliases, custom registries, namespace enforcement, publishing

- dependency_resolver: resolve_dependencies(), --skip-deps, --force on install
- alias_manager: alias create/list/remove (no top-level alias commands)
- custom_registries: add-registry, list-registries, remove-registry; fetch_all_indexes; search Registry column
- module_installer: namespace/name enforcement, collision detection
- scripts/publish-module.py + .github/workflows/publish-modules.yml (optional signing)
- docs: publishing-modules, custom-registries, dependency-resolution; updated installing-modules, module-marketplace, commands
- version 0.38.0, CHANGELOG

Made-with: Cursor

* docs(openspec): defer 6.2.4 and 6.2.5 (index update/PR, workflow test) to later

Made-with: Cursor

* Add follow-up change proposals for marketplace

* Fix codex review findings

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: complete marketplace publish registry PR flow and bump (#320)

0.38.1

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: update init ide hint and repair publish workflow
  condition

* feat(backlog): normalize daily summarize Markdown output (#323)

* 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>

* Update version

* Add github skills

* Add new marketplace changes

* feat(cli): category groups and flat shims using real module Typer (#331)

* 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>

* Update docs regarding module migration change

* feat: module-migration-02 bundle extraction (#332)

* 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>

* Implement blockers to prepare for module-migration-03 change. (#336)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat: module-migration-03 core slimming closeout and registry fixes (#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>

* Finalize module-migration-02 change

* docs(backlog-auth): update auth docs and OpenSpec task status (#342)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* chore(openspec): archive completed changes and sync main specs

* docs(openspec): prefix module migration proposal titles with IDs

* Add bug change for ado required fields setting and update change order

* Update change order

* feat(core): finalize migration-03 auth removal and 3-core slim package (#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>

* Archive module-migration-03 change

* feat: remove flat command shims (category-only CLI) (#344)

* feat: remove flat command shims from grouped registry

* Finalize change module-migration-04 implementation

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Archived module-migration-04 and updated specs

* docs(openspec): finalize module-migration-05 tracking after modules PR 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>

* Archive module-migration-05 change and update specs

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

* 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>

* Archived module-migration-06 change and updated specs

* test: module-migration-07 core test ownership cleanup (#347)

* 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>

* Archived backlog-core-07 change and updated specs

* Update some docs and archive latest finished changes and specs

* Add docs update change

* feat: add agile-01-feature-hierarchy change and update CHANGE_ORDER.md (#376)

- Create openspec/changes/agile-01-feature-hierarchy/ with proposal.md and tasks.md
- Add Epics #256 (Architecture Layer Integration), #257 (AI IDE Integration),
  and #258 (Integration Governance and Dogfooding) to CHANGE_ORDER.md parent issues table
- 25 GitHub Feature issues created (#351-#375), linked to their parent Epics
- Feature label created; issue #185 closed (ceremony-cockpit-01, archived 2026-02-18)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: align core docs and sync pending changes (#377)

* docs: align core docs and sync pending changes

* fix: preserve partial staging in markdown autofix hook

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: stabilize release test suite after module migration

* Update module

* Fix module install

* Fix module install

* Fix failed tests

* Fix marketplace client regression

* Fix install regression for specfact-cli (#380)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add changes to improve runtime validation and backlog module remaining migration to module

* refactor: remove backlog ownership from core cli (#384)

* refactor: remove backlog ownership from core cli

* fix: align CI marketplace validation paths

* test: stabilize command audit validation and add command-surface change

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add new command alignment change

* fix: finalize cli runtime validation regressions (#387)

* fix: finalize cli runtime validation regressions

* test: align satisfied dependency logging assertions

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive cli-val-07 change

* Archive changes and update specs

* Add code-review change proposals

* test: align command surface regression coverage

* docs: add OpenSpec change for backlog-core commands migration (#390)

* feat: add OpenSpec change for backlog-core commands migration

Change: backlog-02-migrate-core-commands
- Add proposal, design, tasks, specs
- Add TDD_EVIDENCE.md with implementation progress
- GitHub Issue: #389

Rules applied: AGENTS.md Git Worktree Policy, TDD Hard Gate

Made-with: Cursor

* docs: update TDD_EVIDENCE and tasks for quality gate results

Made-with: Cursor

* docs: update TDD_EVIDENCE with test fix results

Made-with: Cursor

* docs: update TDD_EVIDENCE with all test fixes complete

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: use POST instead of PATCH for ADO work item creation (#391)

* fix: use POST instead of PATCH for ADO work item creation

Azure DevOps API requires POST (not PATCH) for creating work items.

Also fixed category grouping to always register group commands.

Made-with: Cursor

* docs: add changelog entry for ADO POST fix

Made-with: Cursor

* chore: bump version to 0.40.4

Made-with: Cursor

* fix: update test mocks from PATCH to POST for ADO create

- Reverted incorrect unconditional _mount_installed_category_groups call

- Updated test_create_issue mocks to use requests.post instead of requests.patch

Made-with: Cursor

* test: skip category group test when bundles not installed

The test_bootstrap_with_category_grouping_disabled_registers_flat_commands test

expects bundles like specfact-codebase to be installed, but in CI they may not be.

Added pytest.skip() when 'code' command is not available.

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive backlog-02-migrate-core-commands change

- Archived backlog-02-migrate-core-commands change

- Updated CHANGE_ORDER.md with implementation status

- Updated main specs with backlog-add, backlog-analyze-deps, backlog-delta, backlog-sync, backlog-verify-readiness

Made-with: Cursor

* feat: document code-review module scaffold (#410)

* feat: document code-review module scaffold

* chore: sync 0.41.0 release version artifacts

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add change for project codebase ownership

* Realign code import ownership surface (#412)

* Realign code import ownership surface

* Harden temp registry command audit test

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Update code review changes

* docs: update reward ledger OpenSpec tracking (#413)

Link the existing change issue, record TDD evidence, and align the OpenSpec artifacts with the bundle-owned DDL and paired worktree implementation flow.

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Track house-rules skill OpenSpec changes (#414)

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: Update change-proposal for code-review-07 (#415)

* Track house-rules skill OpenSpec changes

Made-with: Cursor

* Cursor: Apply local changes for cloud agent

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Finalize code-review-07 status

* Finalize code-review-08 status

* feat: apply code-review-09 pre-commit integration

* fix: fall back when cached hatch test env is broken

* fix: avoid hatch env for coverage xml export

* fix: install type-check and lint tools directly in CI

* fix: install pytest fallback deps in test job

* fix: install pytest-cov for test fallback path

* Finalize code-review-09 status

* [Change] Align core docs with modules site ownership (#419)

* Align core docs with modules site ownership

* Close docs portal change PR task

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden docs parity URL assertions

* Archive finished changes and update specs

* docs: fix command syntax parity after lean-core/modules split (v0.42.2) (#421)

Replace all stale CLI syntax families in authored docs with current
shipped commands. Adds docs parity tests that guard against regression.

Removed syntax families corrected:
- specfact project plan → project devops-flow / project snapshot / govern enforce sdd
- project import from-bridge → code import from-bridge
- specfact backlog policy → backlog verify-readiness / backlog refine
- specfact spec contract → spec validate / spec generate-tests / spec mock
- specfact spec sdd constitution → govern enforce sdd [BUNDLE]
- spec generate <prompt-subcommands> → AI IDE skills or removed

Updated docs: README.md, docs/index.md, docs/README.md,
docs/reference/commands.md (+4 reference docs),
docs/getting-started/ (4 files), docs/guides/ (21 files),
docs/examples/ (5 files), docs/prompts/ (2 files).

Added 11 new docs parity tests in test_release_docs_parity.py:
- 7 tests asserting removed syntax families stay absent
- 4 tests asserting current command families remain documented

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Archive finished changes and update specs

- Archive docs-03-command-syntax-parity (2026-03-18)
- Sync delta specs: cli-output + documentation-alignment updated with
  post-split command-surface alignment requirements and scenarios
- Update CHANGE_ORDER.md: mark docs-03 as archived

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

* Update evidence

* Potential fix for pull request finding 'Unused global variable'

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>

* docs: align core docs ownership and parity (#424)

* docs: fix command syntax parity after lean-core/modules split (v0.42.2)

Replace all stale CLI syntax families in authored docs with current
shipped commands. Adds docs parity tests that guard against regression.

Removed syntax families corrected:
- specfact project plan → project devops-flow / project snapshot / govern enforce sdd
- project import from-bridge → code import from-bridge
- specfact backlog policy → backlog verify-readiness / backlog refine
- specfact spec contract → spec validate / spec generate-tests / spec mock
- specfact spec sdd constitution → govern enforce sdd [BUNDLE]
- spec generate <prompt-subcommands> → AI IDE skills or removed

Updated docs: README.md, docs/index.md, docs/README.md,
docs/reference/commands.md (+4 reference docs),
docs/getting-started/ (4 files), docs/guides/ (21 files),
docs/examples/ (5 files), docs/prompts/ (2 files).

Added 11 new docs parity tests in test_release_docs_parity.py:
- 7 tests asserting removed syntax families stay absent
- 4 tests asserting current command families remain documented

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

* docs: align core docs ownership and parity

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: fix quickstart install guidance

* docs: remove generated project plan docs

* Add code-review change

* fix: preserve native backlog import payloads (#429)

* fix: preserve native backlog import payloads

* fix: preserve imported proposal ids on reimport

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: add docs review workflow and repair docs links (#428)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: keep imported change ids stable across title changes (#431)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: remove conflicting pages file copies

* Add docs sync changs

* docs: update openspec clean-code planning

* Update change status

* fix: code-review-zero-findings dogfood remediation (v0.42.3) (#435)

* fix: continue code review remediation and align module signing

* fix: complete code-review-zero-findings dogfood remediation (v0.42.3)

Eliminates full-scope code review findings (types, Radon CC, contracts, lint) and records OpenSpec change code-review-zero-findings with tests and CHANGELOG. Module manifests may need re-signing before merge per project policy.

Made-with: Cursor

* chore: re-sign bundled modules after content changes

* fix: resolve review follow-up regressions

* fix: run ci smart-test directly

* fix: restore ci test progress output

* fix: stabilize command audit ci test

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add docs refactoring changes

* Add bug change tracking for encoding and resources

* docs: restructure core site IA to 6-section progressive nav (#442)

* docs: restructure core site IA from 5 flat sections to 6 progressive sections

Restructure docs.specfact.io from a flat 5-section sidebar to a 6-section
progressive navigation: Getting Started, Core CLI, Module System, Architecture,
Reference, Migration.

- Create docs/core-cli/, docs/module-system/, docs/migration/ directories
- Move 12 files to correct new sections with jekyll-redirect-from entries
- Write 3 new CLI reference pages: init.md, module.md, upgrade.md
- Replace first-steps.md with focused 5-minute quickstart
- Rewrite index.md as portal landing with core vs modules delineation
- Rewrite getting-started/README.md to link module tutorials to modules site
- Update sidebar navigation in _layouts/default.html
- Delete 6 obsolete files (competitive-analysis, ux-features, common-tasks,
  workflows, testing-terminal-output, guides/README)
- Add documentation-alignment delta spec for core-only focus policy

Implements: #438
OpenSpec: docs-05-core-site-ia-restructure

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

* docs: fix broken internal links after IA restructure

Update all relative links across 40 files to point to new file locations:
- ../reference/architecture.md → ../architecture/overview.md
- ../reference/debug-logging.md → ../core-cli/debug-logging.md
- ../reference/modes.md → ../core-cli/modes.md
- guides/ sibling links → ../module-system/ or ../migration/
- module-system/ back-links → ../guides/
- Remove links to deleted files (common-tasks, workflows)
- first-steps.md → quickstart.md

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

* fix: update test path for moved bootstrap-checklist and fix remaining broken links

- Update test_module_bootstrap_checklist_uses_current_bundle_ids to use
  new path docs/module-system/bootstrap-checklist.md
- Fix 2 remaining command-chains.md anchor links in migration-guide.md

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: harden cross-platform runtime and IDE resource discovery (#443)

* fix: harden cross-platform runtime and IDE resource discovery

* fix: bump patch version to 0.42.4

* fix: restore init lifecycle compatibility

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: resolve review type-safety findings

* Improve clarity and scope of ide prompt change

* feat(init): IDE prompt source catalog, --prompts, namespaced exports (#445)

* feat(init): IDE prompt source catalog, --prompts, namespaced exports

Implement init-ide-prompt-source-selection: discover core + module prompts,
default export all sources, interactive multi-select, non-interactive --prompts,
source-namespaced IDE paths. Fix project module roots to use metadata source
project. Extend discovery roots with user/marketplace. Update startup_checks
for nested exports. Bump init module to 0.1.14 with signed manifest.

Made-with: Cursor

* fix(init): scope VS Code prompt recommendations to exported sources

- Pass prompts_by_source into create_vscode_settings from copy_prompts_by_source_to_ide
- Strip prior .github/prompts/* recommendations on selective export to avoid stale paths
- Extract helpers for catalog paths and fallbacks; keep code review clean

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix tests

* release: bump version to 0.42.5 and update CHANGELOG

- Remove [Unreleased] sections; fold historical arch-08 notes under [0.34.0]
- Document init ide catalog, VS Code recommendations, integration test isolation

Made-with: Cursor

* Fix review findings

* feat(init): selective IDE prompt export cleanup and VS Code recommendation strip

- Prune stale exports and unselected catalog segments in copy_prompts_by_source_to_ide
- Strip only specfact*.prompt.md under .github/prompts/ when merging VS Code settings
- Tighten e2e missing-templates assertions to match CLI output
- Add unit tests for prompt path helper and selective export behavior

Made-with: Cursor

* Fix review findings

* Add missing import

* Bump patch version and changelog

* Fix failed tests

* Fix review findings

* docs: core vs modules URL contract and OpenSpec alignment (#448)

* docs: add core vs modules URL contract and OpenSpec alignment

Document cross-site permalink rules in docs/reference, extend documentation-alignment
and module-docs-ownership specs, update docs-07 and openspec config, and note the
dependency on modules URL policy in CHANGE_ORDER.

Made-with: Cursor

* docs: convert core handoff pages to modules canonical links (docs-07)

- Replace 20 duplicate guides/tutorials with thin summaries, prerequisites,
  and links to modules.specfact.io per URL contract
- Add docs/reference/core-to-modules-handoff-urls.md mapping table
- Align OpenSpec documentation-alignment spec delta with ADDED Requirements
- Complete docs-07-core-handoff-conversion tasks checklist

Refs: #439
Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat(docs-12): docs command validation and cross-site link checks (#449)

* feat(docs-12): docs command validation and cross-site link checks

- Add check-docs-commands (Typer CliRunner prefix + --help) and exclusions for migration/illustrative pages
- Add check-cross-site-links with robust URL extraction; warn-only in docs-validate and CI while live site may lag
- Extend docs-review: Hatch env, validation steps, pytest tests/unit/docs/
- Opt-in handoff map HTTP test (SPECFACT_RUN_HANDOFF_URL_CHECK=1)
- OpenSpec deltas, TDD_EVIDENCE, tasks complete; CHANGELOG [Unreleased]

Made-with: Cursor

* fix(docs-validate): strip leading global flags before command path

- Parse --mode/--input-format/--output-format + value, then other root flags
- Add test for specfact --mode copilot import from-code …
- Fix showcase docs: hatch run contract-test-exploration (not specfact)

Made-with: Cursor

* fix(docs-12): harden link/command validators and spec wording

- Capitalize Markdown in cross-site link spec requirement
- Cross-site: redirect-only HTTP success, UTF-8 read failures, URL delimiter/trim fixes
- Docs commands: catch Typer exceptions on --help, UTF-8 read failures
- Tests: shared loader for check-cross-site-links module

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(scripts): CliRunner without mix_stderr for Click 8.3+ compatibility (#451)

Default CliRunner() merges stderr into stdout; read stdout only so
accessing result.stderr does not raise when streams are combined.

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: review gates (semgrep print, radon CC, icontract, questionary types) (#452)

* fix: satisfy review gates for docs scripts and module_lifecycle typing

- Replace print() with Rich Console in docs validation scripts (semgrep)
- Split HTTP URL checks and doc scans to reduce cyclomatic complexity (radon)
- Add icontract require/ensure on public helpers; use CliRunner() without mix_stderr
- Cast questionary API for basedpyright reportUnknownMemberType

Made-with: Cursor

* fix(scripts): address #452 review (HTTP helpers, icontract, CLI streams)

- _http_success_code: use int directly after None guard
- _response_status: safe getcode via getattr/callable
- check-docs: drop @require preconditions duplicated by beartype
- _cli_invoke_streams_text: merge stdout + stderr for not-installed detection

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add speckit adapter alignment change and update affected change specs

* feat(adapters): spec-kit v0.4.x adapter alignment (#454)

* feat(adapters): spec-kit v0.4.x adapter alignment — extensions, presets, hooks, version detection, 7-command presets

Update SpecKitAdapter, ToolCapabilities, BridgeConfig presets, and
SpecKitScanner for spec-kit v0.4.3 compatibility:

- ToolCapabilities: 5 new optional fields (extensions, extension_commands,
  presets, hook_events, detected_version_source)
- SpecKitScanner: scan_extensions(), scan_presets(), scan_hook_events()
  with .extensionignore support and defensive JSON parsing
- SpecKitAdapter: 3-tier version detection (CLI → heuristic → None),
  refactored get_capabilities() with reduced cyclomatic complexity
- BridgeConfig: all 3 speckit presets expanded from 2 to 7 command
  mappings (specify, plan, tasks, implement, constitution, clarify, analyze)
- 42 new tests across 4 test files (110 targeted, 2248 full suite pass)
- Docs updated: comparison matrix, journey guide, integrations overview,
  adapter development guide

Closes #453

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

* fix: address CodeRabbit review findings

- Use get_bridge_logger instead of logging.getLogger in speckit adapter
  and scanner (production command path convention)
- Narrow except Exception to except OSError in _load_extensionignore
- Simplify redundant base_path conditional in get_capabilities
- Use SimpleNamespace instead of dynamic type() in tests
- Add subprocess.TimeoutExpired and OSError exception tests for CLI
  version detection
- Fix duplicate MD heading in bridge-adapter spec
- Add blank lines after markdown headings in proposal (MD022)

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump version to 0.43.0 for spec-kit v0.4.x alignment (#455)

* chore: bump version to 0.43.0 and add changelog entry

Minor version bump for spec-kit v0.4.x adapter alignment feature.
Syncs version across pyproject.toml, setup.py, and __init__.py.
Adds changelog entry documenting new capabilities.

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

* Sync deps and fix changelog

* Sync deps and fix changelog

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(packaging): remove workflow prompts from core wheel (packaging-02 #441, v0.43.1) (#456)

* fix(packaging): drop duplicate workflow prompts from core wheel (packaging-02 3.5)

Remove resources/prompts from wheel force-include and repo tree; canonical
copies remain in specfact-cli-modules bundles. Align startup IDE drift
checks and init template resolution with discover_prompt_template_files.
Bump to 0.43.1; re-sign init module 0.1.19. Update CHANGELOG, docs, OpenSpec.

Made-with: Cursor

* fix: address PR review (changelog, TDD evidence, startup checks, tests)

- Changelog 0.43.1 header uses Unreleased until release tag
- TDD_EVIDENCE: pre-fail block for Task 3.5 before passing verification
- TemplateCheckResult.sources_available; skip last_checked_version bump when no
  discoverable prompts; drift missing only when source exists
- Integration _fake_discover respects include_package_fallback
- test_validate_all_prompts uses tmp_path; re-enable file in default test run
- test_print_startup_checks_version_update_no_type uses stale version timestamp

Made-with: Cursor

* fix: address follow-up PR review (startup metadata, tests)

- Use ide_dir directly in TemplateCheckResult when IDE folder exists
- Set last_checked_version only after successful template-source checks
- Integration test: assert discover_prompt_template_files fallback + stable startup patches
- validate_all_prompts test: valid vs invalid specfact.*.md outcomes

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Potential fix for pull request finding 'Empty except'

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>

* Fix changelog version

* docs: unify core docs portal UX (#459)

* docs: unify core docs portal UX

* Fix docs-13 core review findings

* Address docs-13 PR review feedback

* Address follow-up docs review feedback

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Harden docs home URL test assertion

* feat: doc frontmatter validation, v0.43.2 review JSON gate, and pre-commit review UX (#463)

* chore(release): v0.43.2 pre-commit review JSON + OpenSpec dogfood rules

- Pre-commit gate writes ReviewReport JSON to .specfact/code-review.json
- openspec/config.yaml: require fresh review JSON and remediate findings
- Docs and unit tests updated

Made-with: Cursor

* fix: CodeRabbit — changelog, openspec TDD_EVIDENCE freshness, review hook timeout

- CHANGELOG 0.43.2: expanded entries, line wrap
- openspec/config.yaml: exclude TDD_EVIDENCE.md from review JSON staleness
- pre_commit_code_review: timeout 300s, TimeoutExpired handling
- tests: exact cwd, timeout assertion and timeout failure test

Made-with: Cursor

* Add code review to pre-commit and frontmatter docs validation

* Improve pre-commit script output

* Improve specfact code review findings output

* Fix review findings

* Improve pre-commit hook output

* Enable dev branch code review

* Update code review hook

* Fix contract review findings

* Fix review findings

* Fix review warnings

* feat: doc frontmatter hardening and code-review gate fixes

- Typer CLI for doc-frontmatter-check; safer owner resolution (split helpers for CC)
- Strict exempt handling; pre-commit hook matches USAGE-FAQ.md; review script JSON typing
- Shared test fixtures/types; integration/unit test updates; OpenSpec tasks and TDD evidence
- Changelog: pre-commit code-review-gate UX note

Made-with: Cursor

* Fix test failures and add docs review to github action runner

* Fix test failure due to UTF8 encoding

* Apply review findings

* Optimize pr orchestrator runtime

* Optimize pr orchestrator runtime

* Fix caching on pr-orchestrator

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive doc-frontmatter-schema openspec change

* Apply suggestions from code review

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>

* fix: restore protocol stubs for type checking

* Add frontamtter check

* fix: harden protocol stubs for code quality

* Add PR test hardening change

* fix: remediate review findings and harden review gates

* fix: rebuild review report model for pydantic

* Add story and onboarding change

* Update change tracking

* Improve scope for ci/cd requirements

* docs: sharpen first-contact story and onboarding (#467)

* docs: sharpen first-contact story and onboarding

* docs: address first-contact review feedback

* docs: address onboarding review fixes

* test: accept default-filtered site tokens in docs parity

* docs: record completed onboarding quality gates

* test: improve first-contact assertion failures

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden review blockers and bump patch version

* test: harden modules docs url assertions

* fix: harden trustworthy green checks (#469)

* fix: harden trustworthy green checks

* fix: restore contract-first ci repro command

* fix: apply CodeRabbit auto-fixes

Fixed 3 file(s) based on 3 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

* fix: resolve CI failures for trustworthy green checks PR

- Use hatch run contract-test instead of specfact code repro in CI
  (CLI bundle not available in CI environment)
- Allow test_bundle_import.py in migration cleanup legacy-import check
  (_bundle_import is an internal helper, not a removed module package)
- Fix formatting in test_trustworthy_green_checks.py (CodeRabbit commit
  was unformatted)

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

* fix: address CodeRabbit review findings

- Add trailing newline to TDD_EVIDENCE.md (MD047)
- Make _load_hooks() search for repo: local instead of assuming index 0
- Replace fragile multi-line string assertion in actionlint test with
  semantic line-by-line checks

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address CodeRabbit review findings for ci-02 (#471)

- Widen workflow_changed filter to include scripts/run_actionlint.sh
  and scripts/yaml-tools.sh so Workflow Lint triggers on script changes
- Pin actionlint default to v1.7.11 (matches CI) instead of latest
- Fix run_actionlint.sh conflating "not installed" with "lint failures"
  by separating availability check from execution
- Restore sys.path after test_bundle_import to avoid cross-test leakage
- Normalize CHANGE_ORDER.md status format to semicolon convention

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: propagate docker actionlint exit code instead of masking failures (#472)

Simplify run_actionlint.sh control flow so both local and docker
execution paths propagate actionlint's exit code via `exit $?`. Previously
the docker path used `if run_with_docker; then exit 0; fi` which treated
lint errors as "docker unavailable" and fell through to install guidance.

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: assert hook id stability and cd to repo root for local actionlint (#473)

- Assert hook id == "specfact-smart-checks" to prevent silent renames
- cd to REPO_ROOT before running local actionlint so it finds workflows
  regardless of caller's cwd

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat: clean-code-01-principle-gates — 7-principle charter gates, v0.44.0 (#474)

* feat: clean-code-01-principle-gates — 7-principle charter gates, v0.44.0

Implements openspec/changes/clean-code-01-principle-gates:

- Rewrote .cursor/rules/clean-code-principles.mdc as a canonical alias
  surface for the 7-principle clean-code charter (naming, kiss, yagni,
  dry, solid) defined in nold-ai/specfact-cli-modules. Documents Phase A
  KISS thresholds (>80 warning / >120 error LOC), nesting-depth and
  parameter-count checks active, and Phase B (>40/80) explicitly deferred.
- Added Clean-Code Review Gate sections to AGENTS.md and CLAUDE.md listing
  all 5 expanded review categories and the Phase A thresholds.
- Created .github/copilot-instructions.md as a lightweight alias (< 30 lines)
  referencing the canonical charter without duplicating it inline.
- Added unit tests (test_clean_code_principle_gates.py) covering all three
  spec scenarios: charter references, compliance gate, LOC/nesting thresholds.
- TDD evidence recorded in openspec/changes/clean-code-01-principle-gates/TDD_EVIDENCE.md.
- Bumped version 0.43.3 → 0.44.0 (minor — feature branch).
- Updated CHANGELOG.md and openspec/CHANGE_ORDER.md.

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

* fix: clean-code-01-principle-gates review findings and broad exception handling\n\n- Fix coderabbitai review findings:\n  - Clarify T20 and W0718 are aspirational in clean-code-principles.mdc\n  - Add language specifier to TDD_EVIDENCE.md fenced code block\n  - Update test to check all 7 canonical principles\n  - Make LOC threshold assertion more specific\n- Improve exception handling throughout codebase:\n  - Replace broad except Exception with specific exceptions\n  - Apply SOLID principle for better error handling\n- Update tasks.md to reflect completion status\n\nFixes #434\n\nGenerated by Mistral Vibe.\nCo-Authored-By: Mistral Vibe <vibe@mistral.ai>

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: archive completed openspec changes and update main specs

Archive 11 completed OpenSpec changes:
- bugfix-02-ado-import-payload-slugging
- ci-02-trustworthy-green-checks
- clean-code-01-principle-gates
- code-review-zero-findings
- docs-04-docs-review-gate-and-link-integrity
- docs-05-core-site-ia-restructure
- docs-07-core-handoff-conversion
- docs-12-docs-validation-ci
- docs-13-core-nav-search-theme-roles
- docs-14-first-contact-story-and-onboarding
- init-ide-prompt-source-selection
- packaging-02-cross-platform-runtime-and-module-resources
- speckit-02-v04-adapter-alignment

Fix spec validation errors:
- Add proper delta headers (ADDED/MODIFIED/REMOVED/RENAMED)
- Use correct scenario format with GIVEN/WHEN/THEN bullets
- Ensure requirement headers match between delta and main specs
- Use correct operation type based on existing requirements

Update main specs with archived changes:
- backlog-adapter: various updates
- bridge-adapter: Spec-Kit v0.4.x capabilities
- bridge-registry: BridgeConfig preset updates
- code-review-module: new requirements
- debug-logging: enhancements
- devops-sync: improvements
- documentation-alignment: core vs modules separation
- review-cli-contracts: new contracts
- review-run-command: command updates

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* Add new user onboarding change

* docs & tooling: new user onboarding + smart-test and pre-commit review fixes (#477)

* Fix content for install, sync, uninstallä

* test(docs): align first-contact contracts and stabilize module CLI tests

- docs/index: restore Why does it exist?, tagline, OpenSpec, canonical core CLI story
- Update init profile tests for solo-developer + install all (code-review, six bundles)
- Lean help test accepts uvx init hint; upgrade/core_compatibility tests match runtime
- Autouse fixture re-bootstraps CommandRegistry after category-group tests
- Rebase tasks conflict resolved; TDD_EVIDENCE + tasks for gates 7.1/7.2/12.1/12.2

Made-with: Cursor

* fix(tools): smart-test baseline and pre-commit single code-review run

- Run full suite when smart-test cache has no last_full_run; force+auto falls back to full when incremental is a no-op
- Pre-commit: invoke pre_commit_code_review.py once (no xargs split) so .specfact/code-review.json is not clobbered
- Tests and OpenSpec tasks for docs-new-user-onboarding

Made-with: Cursor

* test: fix CI backlog copy assertions and module install test isolation

- Align backlog not-installed tests with solo-developer init guidance (no <profile> placeholder)
- Autouse: reset CommandRegistry, register_builtin_commands, rebuild_root_app_from_registry so module install tests work after registry-only clears

Made-with: Cursor

* docs: README wow path + tests locking entrypoint with docs

- README leads with uvx init + code review run --scope full; pip install secondary
- Unit contract tests: README and docs/index.md share canonical uvx strings and order
- E2E: init --profile solo-developer in temp git repo; registry ready for step two with mock bundles

Made-with: Cursor

* feat(init): solo-developer includes code-review bundle and marketplace install

- Add specfact-code-review to canonical bundles and solo-developer preset
- Install marketplace module nold-ai/specfact-code-review via install_bundles_for_init
- Docs index: core CLI story and default starting point copy for parity tests
- CLI: missing-module hint references solo-developer profile
- smart_test_coverage: icontract requires use (self, test_level) for method contracts
- Re-sign init and module_registry manifests; tests and registry updates

Made-with: Cursor

* fix(tools): align _run_changed_only with tuple return and baseline full run

- Return (success, ran_any) from _run_changed_only; run full suite when no last_full_run
- run_smart_tests(auto, force): fall back to full tests when incremental ran nothing
- Fix wow e2e fixture typing (Iterator[None]) for basedpyright

Unblocks PR #477 CI: type-check, tests, lint job.

Made-with: Cursor

* chore(release): bump to 0.45.1 and update OpenSpec tasks status

- Sync version across pyproject.toml, setup.py, and __init__ modules
- Changelog: 0.45.1 entry for dependency profiles, smart-test baseline, CI, UX
- openspec: rolling status snapshot and task checkboxes for PR verification
- Includes prior branch work: init/profile, module registry, docs entry path, workflows

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: code-review gate (Typer params), typer<0.24 vs semgrep, module upgrade tests (#479)

* fix: code-review gate (Typer params), typer<0.24 vs semgrep, module upgrade tests

- Split root/install Typer callbacks into merged param stubs (KISS param count).
- Patch typer.main via importlib; merge install param specs in module_registry.
- Cap typer<0.24 to stay compatible with semgrep click~=8.1.8.
- Invoke module_registry app directly in upgrade CLI tests (root app may lack module group).
- Refactors for first_run_selection, module_packages, registry tests, semgrep README.

Worktree: specfact-cli-worktrees/bugfix/code-review-cli-tests
Made-with: Cursor

* docs: use code import in examples (flat import removed from CLI)

Replace specfact [--flags] import from-code with specfact [--flags] code import
from-code so check-docs-commands matches the nested Typer path after removing
the flat import shim.

Made-with: Cursor

* Fix review findings

---------

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: restructure README for star conversion (#480)

* docs: restructure readme for star conversion

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: sync readme change tracking

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: relocate readme support artifacts

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: fix readme workflow snippet and pin demo capture

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: address remaining readme review findings

Co-authored-by: Dom <djm81@users.noreply.github.com>

---------

Co-authored-by: Dom <djm81@users.noreply.github.com>

* archived implemented changes

* Archive and remove outdated changes

* Split and refactor change proposals between both repos

* Archive alignment change

* Add changes and github hierarchy scripts

* feat: add GitHub hierarchy cache sync (#492)

* feat: add github hierarchy cache sync

* Backport improvements from modules scripts

* Fix review findings

* Make github sync script executable

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* [codex] Compact agent governance loading (#493)

* feat: compact agent governance loading

* docs: mark governance PR task complete

* docs: sync governance-03 github issue metadata

* fix: restore dev branch governance block

* Apply review findings

* docs: add sibling internal wiki context for OpenSpec design

Point AGENTS.md, Claude/Copilot/Cursor surfaces, and the OpenSpec rule at
docs/agent-rules/40-openspec-and-tdd.md to read-only wiki paths (hot.md,
graph.md, concepts) via absolute paths when specfact-cli-internal is present.
Update INDEX applicability notes and extend governance tests.

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Archived github hierarchy change

* Update rules for openspec archive

* Potential fix for pull request finding 'Unused local variable'

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>

* Add wiki update notes

* Archive governance-03 change, format markdown, add wiki instructions for update

* Fix review findings

* Fix type errors

* fix: safe VS Code settings merge and project artifact writes (#490) (#496)

* fix: safe merge for VS Code settings.json on init ide (profile-04)

- Add project_artifact_write.merge_vscode_settings_prompt_recommendations with fail-safe
  on invalid JSON / bad chat shape; --force backs up to .specfact/recovery/ then replaces.
- Route ide_setup create_vscode_settings through helper; thread force; catch errors for CLI exit.
- Lint gate: scripts/verify_safe_project_writes.py blocks json.load/dump in ide_setup.py.
- Tests, installation docs, 0.45.2 changelog and version pins.

OpenSpec: profile-04-safe-project-artifact-writes
Made-with: Cursor

* fix(profile-04): satisfy review gate, pin setuptools for semgrep

- Refactor project_artifact_write merge path (KISS); icontract predicates
- Deduplicate ide_setup prompt helpers; import from project_artifact_write
- verify_safe_project_writes: ast.walk, contracts, beartype
- Pin setuptools<82 for Semgrep pkg_resources chain
- Update TDD_EVIDENCE and tasks checklist

Made-with: Cursor

* ci: run safe-write verifier in PR orchestrator lint job

Match hatch run lint by invoking scripts/verify_safe_project_writes.py
after ruff/basedpyright/pylint. Use set -euo pipefail so the first lint
failure is not masked by later commands.

Made-with: Cursor

* fix(profile-04): address CodeRabbit review (docs, guard, contracts, tests)

- Wrap installation.md VS Code merge paragraph to <=120 chars per line
- tasks 4.7 + TDD_EVIDENCE: openspec validate --strict sign-off
- verify_safe_project_writes: detect from-json import and aliases
- settings_relative_nonblank: reject absolute paths and .. segments
- ide_setup: _handle_structured_json_document_error for duplicate handlers
- ProjectWriteMode docstring (reserved policy surface); backup stamp + collision loop
- Tests: malformed settings preserved on init ide exit; force+chat coercion; AST guard tests

Made-with: Cursor

* fix(profile-04): JSON5 settings, repo containment, review follow-ups

- merge_vscode_settings: resolve containment before mkdir/write; JSON5 load/dump
  (JSONC comments; trailing_commas=False for strict JSON output)
- ide_setup: empty prompts_by_source skips catalog fallback (_finalize allow_empty_fallback)
- verify_safe_project_writes: detect import json as js attribute calls
- contract_predicates: prompt_files_all_strings accepts list[Any] for mixed-type checks
- Tests: symlink escape, JSONC merge, empty export strip, import-json-as-js guard
- tasks.md / TDD_EVIDENCE: wrap lines to <=120 chars; CHANGELOG + json5 dep + setup.py sync

Made-with: Cursor

* docs(profile-04): tasks pre-flight + full pytest; narrow icontract ensure

- tasks 1.1: hatch env create then smart-test-status and contract-test-status
- tasks 4.3: add hatch test --cover -v to quality gates
- TDD_EVIDENCE: shorter module-signatures and report lines (<=120 cols)
- project_artifact_write: isinstance(result, Path) in @ensure postconditions

Made-with: Cursor

* fix: clear specfact code review on safe-write modules

- verify_safe_project_writes: flatten json binding helpers; stderr writes
  instead of print; inline Import/ImportFrom loops to drop duplicate-shape DRY
- project_artifact_write: _VscodeChatMergeContext dataclass (KISS param count);
  typed chat_body cast before .get for pyright

Made-with: Cursor

* docs(profile-04): record hatch test --cover -v in T…
djm81 added a commit that referenced this pull request Apr 14, 2026
…y) (#502)

* feat(backlog): add backlog add for interactive issue creation (#289)

* feat: add interactive backlog issue creation flow

* feat(backlog): add interactive issue creation and mapping setup

* fix: align backlog protocol test fakes and module manifest versions

* Fix type error

* fix(backlog): persist ado sprint and normalize github create id

* fix(backlog-core): address review findings for add/config/github

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* chore(openspec): archive completed changes and align architecture docs (#292)

* chore(openspec): archive completed changes and align architecture docs

* docs(architecture): refresh discrepancies report after arch-08 remediation

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs(change): Archive architecture discrepancy remediation change

* fix(codeql): preserve module contract marker and document fallback excepts

* fix(backlog): restore installed-runtime discovery parity and add backlog prompt (#294)

* fix(backlog): restore installed runtime discovery and add backlog prompt

* Archive bugfix change

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(version): sync manifests to 0.36.1 and archive backlog-core-04 (#297)

* fix(backlog): restore installed runtime discovery and add backlog prompt

* Archive bugfix change

* fix(version): sync built-in module manifests to 0.36.1

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden module lifecycle bootstrap and signing workflows (#299)

* fix: harden module lifecycle bootstrap and signing workflows

* fix: stabilize module signature hashing across environments

* fix: stabilize bundle module signature verification in CI

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* test: simplify monkeypatch callables in module_security tests

* Fix duplicate with statement

* chore(release): bump to v0.37.1 and harden signature gates

* test: fix init command regression assertions

* fix: release v0.37.2 with runtime crypto deps

* fix: address signature-backend warning and module version drift

* fix: use hatch build in PyPI publish workflow script (#304)

* fix: resolve startup module freshness home path dynamically (#306)

* fix: harden module signing workflow and reduce startup log noise

* test: align module migration compatibility with decoupled module versions

* fix: fail fast on invalid base ref in changed-only module signing

* fix: stabilize module precedence and backlog github mapping flow

* fix(module-registry): persist disables and correct bundled availability

* Re-sign module registry and fix / ignore local temp artifacts

* bump module registry version to 0.1.3

* fix(registry): restore protocol reporting logs in debug mode

* fix(backlog): harden refine writeback, prompts, and any-filter semantics (#311)

* fix(backlog): harden refine writeback, prompts, and daily any filters

* fix(github): default story type fallback to feature

* Fix format

* Fix codex review findings

* bump and sign changed modules

* chore(hooks): enforce module signature verification in pre-commit

* chore(hooks): add markdownlint to pre-commit checks

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(hooks,ado): correct format gate and enforce iteration on direct
  id lookup

* Apply review findings and fix tests

* Pin virtualenv < 21 to avoid incaopatibility failure

* fix: finalize backlog-core-06 ado comment API versioning (#314)

* fix(backlog): harden refine writeback, prompts, and daily any filters

* fix(github): default story type fallback to feature

* Fix format

* Fix codex review findings

* bump and sign changed modules

* chore(hooks): enforce module signature verification in pre-commit

* chore(hooks): add markdownlint to pre-commit checks

* fix: finalize backlog-core-06 ado comment api versioning and ci hatch pins

* fix: address review findings for formatter safety and ado metric patch guards

* docs(openspec): update CHANGE_ORDER status tracking

* fix(ado): apply iteration filter for direct issue_id lookup

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat: Advanced marketplace features (marketplace-02) - dependency resolution, aliases, custom registries, publishing (#318)

* feat: advanced marketplace features (marketplace-02) - dependency resolution, aliases, custom registries, namespace enforcement, publishing

- dependency_resolver: resolve_dependencies(), --skip-deps, --force on install
- alias_manager: alias create/list/remove (no top-level alias commands)
- custom_registries: add-registry, list-registries, remove-registry; fetch_all_indexes; search Registry column
- module_installer: namespace/name enforcement, collision detection
- scripts/publish-module.py + .github/workflows/publish-modules.yml (optional signing)
- docs: publishing-modules, custom-registries, dependency-resolution; updated installing-modules, module-marketplace, commands
- version 0.38.0, CHANGELOG

Made-with: Cursor

* docs(openspec): defer 6.2.4 and 6.2.5 (index update/PR, workflow test) to later

Made-with: Cursor

* Add follow-up change proposals for marketplace

* Fix codex review findings

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: complete marketplace publish registry PR flow and bump (#320)

0.38.1

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: update init ide hint and repair publish workflow
  condition

* feat(backlog): normalize daily summarize Markdown output (#323)

* 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>

* Update version

* Add github skills

* Add new marketplace changes

* feat(cli): category groups and flat shims using real module Typer (#331)

* 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>

* Update docs regarding module migration change

* feat: module-migration-02 bundle extraction (#332)

* 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>

* Implement blockers to prepare for module-migration-03 change. (#336)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat: module-migration-03 core slimming closeout and registry fixes (#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>

* Finalize module-migration-02 change

* docs(backlog-auth): update auth docs and OpenSpec task status (#342)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* chore(openspec): archive completed changes and sync main specs

* docs(openspec): prefix module migration proposal titles with IDs

* Add bug change for ado required fields setting and update change order

* Update change order

* feat(core): finalize migration-03 auth removal and 3-core slim package (#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>

* Archive module-migration-03 change

* feat: remove flat command shims (category-only CLI) (#344)

* feat: remove flat command shims from grouped registry

* Finalize change module-migration-04 implementation

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Archived module-migration-04 and updated specs

* docs(openspec): finalize module-migration-05 tracking after modules PR 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>

* Archive module-migration-05 change and update specs

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

* 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>

* Archived module-migration-06 change and updated specs

* test: module-migration-07 core test ownership cleanup (#347)

* 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>

* Archived backlog-core-07 change and updated specs

* Update some docs and archive latest finished changes and specs

* Add docs update change

* feat: add agile-01-feature-hierarchy change and update CHANGE_ORDER.md (#376)

- Create openspec/changes/agile-01-feature-hierarchy/ with proposal.md and tasks.md
- Add Epics #256 (Architecture Layer Integration), #257 (AI IDE Integration),
  and #258 (Integration Governance and Dogfooding) to CHANGE_ORDER.md parent issues table
- 25 GitHub Feature issues created (#351-#375), linked to their parent Epics
- Feature label created; issue #185 closed (ceremony-cockpit-01, archived 2026-02-18)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: align core docs and sync pending changes (#377)

* docs: align core docs and sync pending changes

* fix: preserve partial staging in markdown autofix hook

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: stabilize release test suite after module migration

* Update module

* Fix module install

* Fix module install

* Fix failed tests

* Fix marketplace client regression

* Fix install regression for specfact-cli (#380)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add changes to improve runtime validation and backlog module remaining migration to module

* refactor: remove backlog ownership from core cli (#384)

* refactor: remove backlog ownership from core cli

* fix: align CI marketplace validation paths

* test: stabilize command audit validation and add command-surface change

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add new command alignment change

* fix: finalize cli runtime validation regressions (#387)

* fix: finalize cli runtime validation regressions

* test: align satisfied dependency logging assertions

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive cli-val-07 change

* Archive changes and update specs

* Add code-review change proposals

* test: align command surface regression coverage

* docs: add OpenSpec change for backlog-core commands migration (#390)

* feat: add OpenSpec change for backlog-core commands migration

Change: backlog-02-migrate-core-commands
- Add proposal, design, tasks, specs
- Add TDD_EVIDENCE.md with implementation progress
- GitHub Issue: #389

Rules applied: AGENTS.md Git Worktree Policy, TDD Hard Gate

Made-with: Cursor

* docs: update TDD_EVIDENCE and tasks for quality gate results

Made-with: Cursor

* docs: update TDD_EVIDENCE with test fix results

Made-with: Cursor

* docs: update TDD_EVIDENCE with all test fixes complete

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: use POST instead of PATCH for ADO work item creation (#391)

* fix: use POST instead of PATCH for ADO work item creation

Azure DevOps API requires POST (not PATCH) for creating work items.

Also fixed category grouping to always register group commands.

Made-with: Cursor

* docs: add changelog entry for ADO POST fix

Made-with: Cursor

* chore: bump version to 0.40.4

Made-with: Cursor

* fix: update test mocks from PATCH to POST for ADO create

- Reverted incorrect unconditional _mount_installed_category_groups call

- Updated test_create_issue mocks to use requests.post instead of requests.patch

Made-with: Cursor

* test: skip category group test when bundles not installed

The test_bootstrap_with_category_grouping_disabled_registers_flat_commands test

expects bundles like specfact-codebase to be installed, but in CI they may not be.

Added pytest.skip() when 'code' command is not available.

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive backlog-02-migrate-core-commands change

- Archived backlog-02-migrate-core-commands change

- Updated CHANGE_ORDER.md with implementation status

- Updated main specs with backlog-add, backlog-analyze-deps, backlog-delta, backlog-sync, backlog-verify-readiness

Made-with: Cursor

* feat: document code-review module scaffold (#410)

* feat: document code-review module scaffold

* chore: sync 0.41.0 release version artifacts

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add change for project codebase ownership

* Realign code import ownership surface (#412)

* Realign code import ownership surface

* Harden temp registry command audit test

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Update code review changes

* docs: update reward ledger OpenSpec tracking (#413)

Link the existing change issue, record TDD evidence, and align the OpenSpec artifacts with the bundle-owned DDL and paired worktree implementation flow.

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Track house-rules skill OpenSpec changes (#414)

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: Update change-proposal for code-review-07 (#415)

* Track house-rules skill OpenSpec changes

Made-with: Cursor

* Cursor: Apply local changes for cloud agent

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Finalize code-review-07 status

* Finalize code-review-08 status

* feat: apply code-review-09 pre-commit integration

* fix: fall back when cached hatch test env is broken

* fix: avoid hatch env for coverage xml export

* fix: install type-check and lint tools directly in CI

* fix: install pytest fallback deps in test job

* fix: install pytest-cov for test fallback path

* Finalize code-review-09 status

* [Change] Align core docs with modules site ownership (#419)

* Align core docs with modules site ownership

* Close docs portal change PR task

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden docs parity URL assertions

* Archive finished changes and update specs

* docs: fix command syntax parity after lean-core/modules split (v0.42.2) (#421)

Replace all stale CLI syntax families in authored docs with current
shipped commands. Adds docs parity tests that guard against regression.

Removed syntax families corrected:
- specfact project plan → project devops-flow / project snapshot / govern enforce sdd
- project import from-bridge → code import from-bridge
- specfact backlog policy → backlog verify-readiness / backlog refine
- specfact spec contract → spec validate / spec generate-tests / spec mock
- specfact spec sdd constitution → govern enforce sdd [BUNDLE]
- spec generate <prompt-subcommands> → AI IDE skills or removed

Updated docs: README.md, docs/index.md, docs/README.md,
docs/reference/commands.md (+4 reference docs),
docs/getting-started/ (4 files), docs/guides/ (21 files),
docs/examples/ (5 files), docs/prompts/ (2 files).

Added 11 new docs parity tests in test_release_docs_parity.py:
- 7 tests asserting removed syntax families stay absent
- 4 tests asserting current command families remain documented

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Archive finished changes and update specs

- Archive docs-03-command-syntax-parity (2026-03-18)
- Sync delta specs: cli-output + documentation-alignment updated with
  post-split command-surface alignment requirements and scenarios
- Update CHANGE_ORDER.md: mark docs-03 as archived

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

* Update evidence

* Potential fix for pull request finding 'Unused global variable'

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>

* docs: align core docs ownership and parity (#424)

* docs: fix command syntax parity after lean-core/modules split (v0.42.2)

Replace all stale CLI syntax families in authored docs with current
shipped commands. Adds docs parity tests that guard against regression.

Removed syntax families corrected:
- specfact project plan → project devops-flow / project snapshot / govern enforce sdd
- project import from-bridge → code import from-bridge
- specfact backlog policy → backlog verify-readiness / backlog refine
- specfact spec contract → spec validate / spec generate-tests / spec mock
- specfact spec sdd constitution → govern enforce sdd [BUNDLE]
- spec generate <prompt-subcommands> → AI IDE skills or removed

Updated docs: README.md, docs/index.md, docs/README.md,
docs/reference/commands.md (+4 reference docs),
docs/getting-started/ (4 files), docs/guides/ (21 files),
docs/examples/ (5 files), docs/prompts/ (2 files).

Added 11 new docs parity tests in test_release_docs_parity.py:
- 7 tests asserting removed syntax families stay absent
- 4 tests asserting current command families remain documented

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

* docs: align core docs ownership and parity

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: fix quickstart install guidance

* docs: remove generated project plan docs

* Add code-review change

* fix: preserve native backlog import payloads (#429)

* fix: preserve native backlog import payloads

* fix: preserve imported proposal ids on reimport

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: add docs review workflow and repair docs links (#428)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: keep imported change ids stable across title changes (#431)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: remove conflicting pages file copies

* Add docs sync changs

* docs: update openspec clean-code planning

* Update change status

* fix: code-review-zero-findings dogfood remediation (v0.42.3) (#435)

* fix: continue code review remediation and align module signing

* fix: complete code-review-zero-findings dogfood remediation (v0.42.3)

Eliminates full-scope code review findings (types, Radon CC, contracts, lint) and records OpenSpec change code-review-zero-findings with tests and CHANGELOG. Module manifests may need re-signing before merge per project policy.

Made-with: Cursor

* chore: re-sign bundled modules after content changes

* fix: resolve review follow-up regressions

* fix: run ci smart-test directly

* fix: restore ci test progress output

* fix: stabilize command audit ci test

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add docs refactoring changes

* Add bug change tracking for encoding and resources

* docs: restructure core site IA to 6-section progressive nav (#442)

* docs: restructure core site IA from 5 flat sections to 6 progressive sections

Restructure docs.specfact.io from a flat 5-section sidebar to a 6-section
progressive navigation: Getting Started, Core CLI, Module System, Architecture,
Reference, Migration.

- Create docs/core-cli/, docs/module-system/, docs/migration/ directories
- Move 12 files to correct new sections with jekyll-redirect-from entries
- Write 3 new CLI reference pages: init.md, module.md, upgrade.md
- Replace first-steps.md with focused 5-minute quickstart
- Rewrite index.md as portal landing with core vs modules delineation
- Rewrite getting-started/README.md to link module tutorials to modules site
- Update sidebar navigation in _layouts/default.html
- Delete 6 obsolete files (competitive-analysis, ux-features, common-tasks,
  workflows, testing-terminal-output, guides/README)
- Add documentation-alignment delta spec for core-only focus policy

Implements: #438
OpenSpec: docs-05-core-site-ia-restructure

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

* docs: fix broken internal links after IA restructure

Update all relative links across 40 files to point to new file locations:
- ../reference/architecture.md → ../architecture/overview.md
- ../reference/debug-logging.md → ../core-cli/debug-logging.md
- ../reference/modes.md → ../core-cli/modes.md
- guides/ sibling links → ../module-system/ or ../migration/
- module-system/ back-links → ../guides/
- Remove links to deleted files (common-tasks, workflows)
- first-steps.md → quickstart.md

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

* fix: update test path for moved bootstrap-checklist and fix remaining broken links

- Update test_module_bootstrap_checklist_uses_current_bundle_ids to use
  new path docs/module-system/bootstrap-checklist.md
- Fix 2 remaining command-chains.md anchor links in migration-guide.md

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: harden cross-platform runtime and IDE resource discovery (#443)

* fix: harden cross-platform runtime and IDE resource discovery

* fix: bump patch version to 0.42.4

* fix: restore init lifecycle compatibility

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: resolve review type-safety findings

* Improve clarity and scope of ide prompt change

* feat(init): IDE prompt source catalog, --prompts, namespaced exports (#445)

* feat(init): IDE prompt source catalog, --prompts, namespaced exports

Implement init-ide-prompt-source-selection: discover core + module prompts,
default export all sources, interactive multi-select, non-interactive --prompts,
source-namespaced IDE paths. Fix project module roots to use metadata source
project. Extend discovery roots with user/marketplace. Update startup_checks
for nested exports. Bump init module to 0.1.14 with signed manifest.

Made-with: Cursor

* fix(init): scope VS Code prompt recommendations to exported sources

- Pass prompts_by_source into create_vscode_settings from copy_prompts_by_source_to_ide
- Strip prior .github/prompts/* recommendations on selective export to avoid stale paths
- Extract helpers for catalog paths and fallbacks; keep code review clean

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix tests

* release: bump version to 0.42.5 and update CHANGELOG

- Remove [Unreleased] sections; fold historical arch-08 notes under [0.34.0]
- Document init ide catalog, VS Code recommendations, integration test isolation

Made-with: Cursor

* Fix review findings

* feat(init): selective IDE prompt export cleanup and VS Code recommendation strip

- Prune stale exports and unselected catalog segments in copy_prompts_by_source_to_ide
- Strip only specfact*.prompt.md under .github/prompts/ when merging VS Code settings
- Tighten e2e missing-templates assertions to match CLI output
- Add unit tests for prompt path helper and selective export behavior

Made-with: Cursor

* Fix review findings

* Add missing import

* Bump patch version and changelog

* Fix failed tests

* Fix review findings

* docs: core vs modules URL contract and OpenSpec alignment (#448)

* docs: add core vs modules URL contract and OpenSpec alignment

Document cross-site permalink rules in docs/reference, extend documentation-alignment
and module-docs-ownership specs, update docs-07 and openspec config, and note the
dependency on modules URL policy in CHANGE_ORDER.

Made-with: Cursor

* docs: convert core handoff pages to modules canonical links (docs-07)

- Replace 20 duplicate guides/tutorials with thin summaries, prerequisites,
  and links to modules.specfact.io per URL contract
- Add docs/reference/core-to-modules-handoff-urls.md mapping table
- Align OpenSpec documentation-alignment spec delta with ADDED Requirements
- Complete docs-07-core-handoff-conversion tasks checklist

Refs: #439
Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat(docs-12): docs command validation and cross-site link checks (#449)

* feat(docs-12): docs command validation and cross-site link checks

- Add check-docs-commands (Typer CliRunner prefix + --help) and exclusions for migration/illustrative pages
- Add check-cross-site-links with robust URL extraction; warn-only in docs-validate and CI while live site may lag
- Extend docs-review: Hatch env, validation steps, pytest tests/unit/docs/
- Opt-in handoff map HTTP test (SPECFACT_RUN_HANDOFF_URL_CHECK=1)
- OpenSpec deltas, TDD_EVIDENCE, tasks complete; CHANGELOG [Unreleased]

Made-with: Cursor

* fix(docs-validate): strip leading global flags before command path

- Parse --mode/--input-format/--output-format + value, then other root flags
- Add test for specfact --mode copilot import from-code …
- Fix showcase docs: hatch run contract-test-exploration (not specfact)

Made-with: Cursor

* fix(docs-12): harden link/command validators and spec wording

- Capitalize Markdown in cross-site link spec requirement
- Cross-site: redirect-only HTTP success, UTF-8 read failures, URL delimiter/trim fixes
- Docs commands: catch Typer exceptions on --help, UTF-8 read failures
- Tests: shared loader for check-cross-site-links module

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(scripts): CliRunner without mix_stderr for Click 8.3+ compatibility (#451)

Default CliRunner() merges stderr into stdout; read stdout only so
accessing result.stderr does not raise when streams are combined.

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: review gates (semgrep print, radon CC, icontract, questionary types) (#452)

* fix: satisfy review gates for docs scripts and module_lifecycle typing

- Replace print() with Rich Console in docs validation scripts (semgrep)
- Split HTTP URL checks and doc scans to reduce cyclomatic complexity (radon)
- Add icontract require/ensure on public helpers; use CliRunner() without mix_stderr
- Cast questionary API for basedpyright reportUnknownMemberType

Made-with: Cursor

* fix(scripts): address #452 review (HTTP helpers, icontract, CLI streams)

- _http_success_code: use int directly after None guard
- _response_status: safe getcode via getattr/callable
- check-docs: drop @require preconditions duplicated by beartype
- _cli_invoke_streams_text: merge stdout + stderr for not-installed detection

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add speckit adapter alignment change and update affected change specs

* feat(adapters): spec-kit v0.4.x adapter alignment (#454)

* feat(adapters): spec-kit v0.4.x adapter alignment — extensions, presets, hooks, version detection, 7-command presets

Update SpecKitAdapter, ToolCapabilities, BridgeConfig presets, and
SpecKitScanner for spec-kit v0.4.3 compatibility:

- ToolCapabilities: 5 new optional fields (extensions, extension_commands,
  presets, hook_events, detected_version_source)
- SpecKitScanner: scan_extensions(), scan_presets(), scan_hook_events()
  with .extensionignore support and defensive JSON parsing
- SpecKitAdapter: 3-tier version detection (CLI → heuristic → None),
  refactored get_capabilities() with reduced cyclomatic complexity
- BridgeConfig: all 3 speckit presets expanded from 2 to 7 command
  mappings (specify, plan, tasks, implement, constitution, clarify, analyze)
- 42 new tests across 4 test files (110 targeted, 2248 full suite pass)
- Docs updated: comparison matrix, journey guide, integrations overview,
  adapter development guide

Closes #453

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

* fix: address CodeRabbit review findings

- Use get_bridge_logger instead of logging.getLogger in speckit adapter
  and scanner (production command path convention)
- Narrow except Exception to except OSError in _load_extensionignore
- Simplify redundant base_path conditional in get_capabilities
- Use SimpleNamespace instead of dynamic type() in tests
- Add subprocess.TimeoutExpired and OSError exception tests for CLI
  version detection
- Fix duplicate MD heading in bridge-adapter spec
- Add blank lines after markdown headings in proposal (MD022)

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump version to 0.43.0 for spec-kit v0.4.x alignment (#455)

* chore: bump version to 0.43.0 and add changelog entry

Minor version bump for spec-kit v0.4.x adapter alignment feature.
Syncs version across pyproject.toml, setup.py, and __init__.py.
Adds changelog entry documenting new capabilities.

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

* Sync deps and fix changelog

* Sync deps and fix changelog

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(packaging): remove workflow prompts from core wheel (packaging-02 #441, v0.43.1) (#456)

* fix(packaging): drop duplicate workflow prompts from core wheel (packaging-02 3.5)

Remove resources/prompts from wheel force-include and repo tree; canonical
copies remain in specfact-cli-modules bundles. Align startup IDE drift
checks and init template resolution with discover_prompt_template_files.
Bump to 0.43.1; re-sign init module 0.1.19. Update CHANGELOG, docs, OpenSpec.

Made-with: Cursor

* fix: address PR review (changelog, TDD evidence, startup checks, tests)

- Changelog 0.43.1 header uses Unreleased until release tag
- TDD_EVIDENCE: pre-fail block for Task 3.5 before passing verification
- TemplateCheckResult.sources_available; skip last_checked_version bump when no
  discoverable prompts; drift missing only when source exists
- Integration _fake_discover respects include_package_fallback
- test_validate_all_prompts uses tmp_path; re-enable file in default test run
- test_print_startup_checks_version_update_no_type uses stale version timestamp

Made-with: Cursor

* fix: address follow-up PR review (startup metadata, tests)

- Use ide_dir directly in TemplateCheckResult when IDE folder exists
- Set last_checked_version only after successful template-source checks
- Integration test: assert discover_prompt_template_files fallback + stable startup patches
- validate_all_prompts test: valid vs invalid specfact.*.md outcomes

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Potential fix for pull request finding 'Empty except'

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>

* Fix changelog version

* docs: unify core docs portal UX (#459)

* docs: unify core docs portal UX

* Fix docs-13 core review findings

* Address docs-13 PR review feedback

* Address follow-up docs review feedback

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Harden docs home URL test assertion

* feat: doc frontmatter validation, v0.43.2 review JSON gate, and pre-commit review UX (#463)

* chore(release): v0.43.2 pre-commit review JSON + OpenSpec dogfood rules

- Pre-commit gate writes ReviewReport JSON to .specfact/code-review.json
- openspec/config.yaml: require fresh review JSON and remediate findings
- Docs and unit tests updated

Made-with: Cursor

* fix: CodeRabbit — changelog, openspec TDD_EVIDENCE freshness, review hook timeout

- CHANGELOG 0.43.2: expanded entries, line wrap
- openspec/config.yaml: exclude TDD_EVIDENCE.md from review JSON staleness
- pre_commit_code_review: timeout 300s, TimeoutExpired handling
- tests: exact cwd, timeout assertion and timeout failure test

Made-with: Cursor

* Add code review to pre-commit and frontmatter docs validation

* Improve pre-commit script output

* Improve specfact code review findings output

* Fix review findings

* Improve pre-commit hook output

* Enable dev branch code review

* Update code review hook

* Fix contract review findings

* Fix review findings

* Fix review warnings

* feat: doc frontmatter hardening and code-review gate fixes

- Typer CLI for doc-frontmatter-check; safer owner resolution (split helpers for CC)
- Strict exempt handling; pre-commit hook matches USAGE-FAQ.md; review script JSON typing
- Shared test fixtures/types; integration/unit test updates; OpenSpec tasks and TDD evidence
- Changelog: pre-commit code-review-gate UX note

Made-with: Cursor

* Fix test failures and add docs review to github action runner

* Fix test failure due to UTF8 encoding

* Apply review findings

* Optimize pr orchestrator runtime

* Optimize pr orchestrator runtime

* Fix caching on pr-orchestrator

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive doc-frontmatter-schema openspec change

* Apply suggestions from code review

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>

* fix: restore protocol stubs for type checking

* Add frontamtter check

* fix: harden protocol stubs for code quality

* Add PR test hardening change

* fix: remediate review findings and harden review gates

* fix: rebuild review report model for pydantic

* Add story and onboarding change

* Update change tracking

* Improve scope for ci/cd requirements

* docs: sharpen first-contact story and onboarding (#467)

* docs: sharpen first-contact story and onboarding

* docs: address first-contact review feedback

* docs: address onboarding review fixes

* test: accept default-filtered site tokens in docs parity

* docs: record completed onboarding quality gates

* test: improve first-contact assertion failures

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden review blockers and bump patch version

* test: harden modules docs url assertions

* fix: harden trustworthy green checks (#469)

* fix: harden trustworthy green checks

* fix: restore contract-first ci repro command

* fix: apply CodeRabbit auto-fixes

Fixed 3 file(s) based on 3 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

* fix: resolve CI failures for trustworthy green checks PR

- Use hatch run contract-test instead of specfact code repro in CI
  (CLI bundle not available in CI environment)
- Allow test_bundle_import.py in migration cleanup legacy-import check
  (_bundle_import is an internal helper, not a removed module package)
- Fix formatting in test_trustworthy_green_checks.py (CodeRabbit commit
  was unformatted)

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

* fix: address CodeRabbit review findings

- Add trailing newline to TDD_EVIDENCE.md (MD047)
- Make _load_hooks() search for repo: local instead of assuming index 0
- Replace fragile multi-line string assertion in actionlint test with
  semantic line-by-line checks

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address CodeRabbit review findings for ci-02 (#471)

- Widen workflow_changed filter to include scripts/run_actionlint.sh
  and scripts/yaml-tools.sh so Workflow Lint triggers on script changes
- Pin actionlint default to v1.7.11 (matches CI) instead of latest
- Fix run_actionlint.sh conflating "not installed" with "lint failures"
  by separating availability check from execution
- Restore sys.path after test_bundle_import to avoid cross-test leakage
- Normalize CHANGE_ORDER.md status format to semicolon convention

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: propagate docker actionlint exit code instead of masking failures (#472)

Simplify run_actionlint.sh control flow so both local and docker
execution paths propagate actionlint's exit code via `exit $?`. Previously
the docker path used `if run_with_docker; then exit 0; fi` which treated
lint errors as "docker unavailable" and fell through to install guidance.

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: assert hook id stability and cd to repo root for local actionlint (#473)

- Assert hook id == "specfact-smart-checks" to prevent silent renames
- cd to REPO_ROOT before running local actionlint so it finds workflows
  regardless of caller's cwd

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat: clean-code-01-principle-gates — 7-principle charter gates, v0.44.0 (#474)

* feat: clean-code-01-principle-gates — 7-principle charter gates, v0.44.0

Implements openspec/changes/clean-code-01-principle-gates:

- Rewrote .cursor/rules/clean-code-principles.mdc as a canonical alias
  surface for the 7-principle clean-code charter (naming, kiss, yagni,
  dry, solid) defined in nold-ai/specfact-cli-modules. Documents Phase A
  KISS thresholds (>80 warning / >120 error LOC), nesting-depth and
  parameter-count checks active, and Phase B (>40/80) explicitly deferred.
- Added Clean-Code Review Gate sections to AGENTS.md and CLAUDE.md listing
  all 5 expanded review categories and the Phase A thresholds.
- Created .github/copilot-instructions.md as a lightweight alias (< 30 lines)
  referencing the canonical charter without duplicating it inline.
- Added unit tests (test_clean_code_principle_gates.py) covering all three
  spec scenarios: charter references, compliance gate, LOC/nesting thresholds.
- TDD evidence recorded in openspec/changes/clean-code-01-principle-gates/TDD_EVIDENCE.md.
- Bumped version 0.43.3 → 0.44.0 (minor — feature branch).
- Updated CHANGELOG.md and openspec/CHANGE_ORDER.md.

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

* fix: clean-code-01-principle-gates review findings and broad exception handling\n\n- Fix coderabbitai review findings:\n  - Clarify T20 and W0718 are aspirational in clean-code-principles.mdc\n  - Add language specifier to TDD_EVIDENCE.md fenced code block\n  - Update test to check all 7 canonical principles\n  - Make LOC threshold assertion more specific\n- Improve exception handling throughout codebase:\n  - Replace broad except Exception with specific exceptions\n  - Apply SOLID principle for better error handling\n- Update tasks.md to reflect completion status\n\nFixes #434\n\nGenerated by Mistral Vibe.\nCo-Authored-By: Mistral Vibe <vibe@mistral.ai>

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: archive completed openspec changes and update main specs

Archive 11 completed OpenSpec changes:
- bugfix-02-ado-import-payload-slugging
- ci-02-trustworthy-green-checks
- clean-code-01-principle-gates
- code-review-zero-findings
- docs-04-docs-review-gate-and-link-integrity
- docs-05-core-site-ia-restructure
- docs-07-core-handoff-conversion
- docs-12-docs-validation-ci
- docs-13-core-nav-search-theme-roles
- docs-14-first-contact-story-and-onboarding
- init-ide-prompt-source-selection
- packaging-02-cross-platform-runtime-and-module-resources
- speckit-02-v04-adapter-alignment

Fix spec validation errors:
- Add proper delta headers (ADDED/MODIFIED/REMOVED/RENAMED)
- Use correct scenario format with GIVEN/WHEN/THEN bullets
- Ensure requirement headers match between delta and main specs
- Use correct operation type based on existing requirements

Update main specs with archived changes:
- backlog-adapter: various updates
- bridge-adapter: Spec-Kit v0.4.x capabilities
- bridge-registry: BridgeConfig preset updates
- code-review-module: new requirements
- debug-logging: enhancements
- devops-sync: improvements
- documentation-alignment: core vs modules separation
- review-cli-contracts: new contracts
- review-run-command: command updates

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* Add new user onboarding change

* docs & tooling: new user onboarding + smart-test and pre-commit review fixes (#477)

* Fix content for install, sync, uninstallä

* test(docs): align first-contact contracts and stabilize module CLI tests

- docs/index: restore Why does it exist?, tagline, OpenSpec, canonical core CLI story
- Update init profile tests for solo-developer + install all (code-review, six bundles)
- Lean help test accepts uvx init hint; upgrade/core_compatibility tests match runtime
- Autouse fixture re-bootstraps CommandRegistry after category-group tests
- Rebase tasks conflict resolved; TDD_EVIDENCE + tasks for gates 7.1/7.2/12.1/12.2

Made-with: Cursor

* fix(tools): smart-test baseline and pre-commit single code-review run

- Run full suite when smart-test cache has no last_full_run; force+auto falls back to full when incremental is a no-op
- Pre-commit: invoke pre_commit_code_review.py once (no xargs split) so .specfact/code-review.json is not clobbered
- Tests and OpenSpec tasks for docs-new-user-onboarding

Made-with: Cursor

* test: fix CI backlog copy assertions and module install test isolation

- Align backlog not-installed tests with solo-developer init guidance (no <profile> placeholder)
- Autouse: reset CommandRegistry, register_builtin_commands, rebuild_root_app_from_registry so module install tests work after registry-only clears

Made-with: Cursor

* docs: README wow path + tests locking entrypoint with docs

- README leads with uvx init + code review run --scope full; pip install secondary
- Unit contract tests: README and docs/index.md share canonical uvx strings and order
- E2E: init --profile solo-developer in temp git repo; registry ready for step two with mock bundles

Made-with: Cursor

* feat(init): solo-developer includes code-review bundle and marketplace install

- Add specfact-code-review to canonical bundles and solo-developer preset
- Install marketplace module nold-ai/specfact-code-review via install_bundles_for_init
- Docs index: core CLI story and default starting point copy for parity tests
- CLI: missing-module hint references solo-developer profile
- smart_test_coverage: icontract requires use (self, test_level) for method contracts
- Re-sign init and module_registry manifests; tests and registry updates

Made-with: Cursor

* fix(tools): align _run_changed_only with tuple return and baseline full run

- Return (success, ran_any) from _run_changed_only; run full suite when no last_full_run
- run_smart_tests(auto, force): fall back to full tests when incremental ran nothing
- Fix wow e2e fixture typing (Iterator[None]) for basedpyright

Unblocks PR #477 CI: type-check, tests, lint job.

Made-with: Cursor

* chore(release): bump to 0.45.1 and update OpenSpec tasks status

- Sync version across pyproject.toml, setup.py, and __init__ modules
- Changelog: 0.45.1 entry for dependency profiles, smart-test baseline, CI, UX
- openspec: rolling status snapshot and task checkboxes for PR verification
- Includes prior branch work: init/profile, module registry, docs entry path, workflows

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: code-review gate (Typer params), typer<0.24 vs semgrep, module upgrade tests (#479)

* fix: code-review gate (Typer params), typer<0.24 vs semgrep, module upgrade tests

- Split root/install Typer callbacks into merged param stubs (KISS param count).
- Patch typer.main via importlib; merge install param specs in module_registry.
- Cap typer<0.24 to stay compatible with semgrep click~=8.1.8.
- Invoke module_registry app directly in upgrade CLI tests (root app may lack module group).
- Refactors for first_run_selection, module_packages, registry tests, semgrep README.

Worktree: specfact-cli-worktrees/bugfix/code-review-cli-tests
Made-with: Cursor

* docs: use code import in examples (flat import removed from CLI)

Replace specfact [--flags] import from-code with specfact [--flags] code import
from-code so check-docs-commands matches the nested Typer path after removing
the flat import shim.

Made-with: Cursor

* Fix review findings

---------

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: restructure README for star conversion (#480)

* docs: restructure readme for star conversion

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: sync readme change tracking

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: relocate readme support artifacts

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: fix readme workflow snippet and pin demo capture

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: address remaining readme review findings

Co-authored-by: Dom <djm81@users.noreply.github.com>

---------

Co-authored-by: Dom <djm81@users.noreply.github.com>

* archived implemented changes

* Archive and remove outdated changes

* Split and refactor change proposals between both repos

* Archive alignment change

* Add changes and github hierarchy scripts

* feat: add GitHub hierarchy cache sync (#492)

* feat: add github hierarchy cache sync

* Backport improvements from modules scripts

* Fix review findings

* Make github sync script executable

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* [codex] Compact agent governance loading (#493)

* feat: compact agent governance loading

* docs: mark governance PR task complete

* docs: sync governance-03 github issue metadata

* fix: restore dev branch governance block

* Apply review findings

* docs: add sibling internal wiki context for OpenSpec design

Point AGENTS.md, Claude/Copilot/Cursor surfaces, and the OpenSpec rule at
docs/agent-rules/40-openspec-and-tdd.md to read-only wiki paths (hot.md,
graph.md, concepts) via absolute paths when specfact-cli-internal is present.
Update INDEX applicability notes and extend governance tests.

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Archived github hierarchy change

* Update rules for openspec archive

* Potential fix for pull request finding 'Unused local variable'

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>

* Add wiki update notes

* Archive governance-03 change, format markdown, add wiki instructions for update

* Fix review findings

* Fix type errors

* fix: safe VS Code settings merge and project artifact writes (#490) (#496)

* fix: safe merge for VS Code settings.json on init ide (profile-04)

- Add project_artifact_write.merge_vscode_settings_prompt_recommendations with fail-safe
  on invalid JSON / bad chat shape; --force backs up to .specfact/recovery/ then replaces.
- Route ide_setup create_vscode_settings through helper; thread force; catch errors for CLI exit.
- Lint gate: scripts/verify_safe_project_writes.py blocks json.load/dump in ide_setup.py.
- Tests, installation docs, 0.45.2 changelog and version pins.

OpenSpec: profile-04-safe-project-artifact-writes
Made-with: Cursor

* fix(profile-04): satisfy review gate, pin setuptools for semgrep

- Refactor project_artifact_write merge path (KISS); icontract predicates
- Deduplicate ide_setup prompt helpers; import from project_artifact_write
- verify_safe_project_writes: ast.walk, contracts, beartype
- Pin setuptools<82 for Semgrep pkg_resources chain
- Update TDD_EVIDENCE and tasks checklist

Made-with: Cursor

* ci: run safe-write verifier in PR orchestrator lint job

Match hatch run lint by invoking scripts/verify_safe_project_writes.py
after ruff/basedpyright/pylint. Use set -euo pipefail so the first lint
failure is not masked by later commands.

Made-with: Cursor

* fix(profile-04): address CodeRabbit review (docs, guard, contracts, tests)

- Wrap installation.md VS Code merge paragraph to <=120 chars per line
- tasks 4.7 + TDD_EVIDENCE: openspec validate --strict sign-off
- verify_safe_project_writes: detect from-json import and aliases
- settings_relative_nonblank: reject absolute paths and .. segments
- ide_setup: _handle_structured_json_document_error for duplicate handlers
- ProjectWriteMode docstring (reserved policy surface); backup stamp + collision loop
- Tests: malformed settings preserved on init ide exit; force+chat coercion; AST guard tests

Made-with: Cursor

* fix(profile-04): JSON5 settings, repo containment, review follow-ups

- merge_vscode_settings: resolve containment before mkdir/write; JSON5 load/dump
  (JSONC comments; trailing_commas=False for strict JSON output)
- ide_setup: empty prompts_by_source skips catalog fallback (_finalize allow_empty_fallback)
- verify_safe_project_writes: detect import json as js attribute calls
- contract_predicates: prompt_files_all_strings accepts list[Any] for mixed-type checks
- Tests: symlink escape, JSONC merge, empty export strip, import-json-as-js guard
- tasks.md / TDD_EVIDENCE: wrap lines to <=120 chars; CHANGELOG + json5 dep + setup.py sync

Made-with: Cursor

* docs(profile-04): tasks pre-flight + full pytest; narrow icontract ensure

- tasks 1.1: hatch env create then smart-test-status and contract-test-status
- tasks 4.3: add hatch test --cover -v to quality gates
- TDD_EVIDENCE: shorter module-signatures and report lines (<=120 cols)
- project_artifact_write: isinstance(result, Path) in @ensure postconditions

Made-with: Cursor

* fix: clear specfact code review on safe-write modules

- verify_safe_project_writes: flatten json binding helpers; stderr writes
  instead of print; inline Import/ImportFrom loops to drop duplicate-shape DRY
- project_artifact_write: _VscodeChatMergeContext dataclass (KISS param count);
  typed chat_body cast before .get for pyright

Made-with: Cursor

* docs(profile-04): record hatch test --cover -v in TDD_EVIDENCE

Align passing evidence with tasks.md 4.3 full-suite coverage gate.

Made-with: Cursor

* fix: reduce KISS blockers (bridge sync contexts, tools, partial adapters)

Refactors high-parameter call sites into dataclasses/context objects and splits hot spots (export devops pipeline, smart_test_coverage incremental run, suggest_frontmatter, crosshair summary loop).

API: BridgeSync.export_change_proposals_to_devops(adapter_type, ExportChangeProposalsOptions | None); LoggerSetup.create_logger(name, LoggerCreateOptions | None); run_crosshair(path, CrosshairRunOptions | None).

Full specfact code review --scope full still reports error-severity kiss/radon findings (remaining nesting/LOC and param counts in ADO, analyzers, generators, source_scanner, module_installer, bundle-mapper, etc.). Gate PASS requires follow-up.

Made-with: Cursor

* Fix review findings and sign modules

* fix(tests): register dynamic check_doc_frontmatter module; align _update_cache tests

- Insert check_doc_frontmatter into sys.modules before exec_module so
  dataclasses can resolve string annotations (fixes Docs Review / agent
  rules governance fixture).
- Call SmartCoverageManager._update_cache with _SmartCacheUpdate after
  signature refactor (fixes basedpyright reportCallIssue).

Made-with: Cursor

* fix(tests): align install_module mocks with InstallModuleOptions; register verify_bundle script

- Monkeypatch/patch fakes now accept (module_id, options=None) matching
  install_module(module_id, InstallModuleOptions(...)).
- Read install_root, trust_non_official, non_interactive, reinstall from
  InstallModuleOptions in CLI command tests.
- Dynamic load of verify-bundle-published registers sys.modules before
  exec_module (same dataclass annotation issue as check_doc_frontmatter).

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Fix review findings (#498)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat(openspec): add marketplace-06-ci-module-signing change proposal

Moves module signing from local interactive requirement to CI step
triggered by PR approval (pull_request_review). Eliminates local private
key dependency for non-interactive development on feature/dev branches.
Trust boundary remains at main.

Scope:
- NEW .github/workflows/sign-modules-on-approval.yml
- MODIFY scripts/pre-commit-smart-checks.sh (branch-aware policy)
- MODIFY .github/workflows/pr-orchestrator.yml (split verify by target)
- MODIFY .github/workflows/sign-modules.yml (main-only enforcement)

GitHub: #500
Parent Feature: #353 (M…
djm81 added a commit that referenced this pull request Apr 14, 2026
* fix(version): sync manifests to 0.36.1 and archive backlog-core-04 (#297)

* fix(backlog): restore installed runtime discovery and add backlog prompt

* Archive bugfix change

* fix(version): sync built-in module manifests to 0.36.1

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden module lifecycle bootstrap and signing workflows (#299)

* fix: harden module lifecycle bootstrap and signing workflows

* fix: stabilize module signature hashing across environments

* fix: stabilize bundle module signature verification in CI

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* test: simplify monkeypatch callables in module_security tests

* Fix duplicate with statement

* chore(release): bump to v0.37.1 and harden signature gates

* test: fix init command regression assertions

* fix: release v0.37.2 with runtime crypto deps

* fix: address signature-backend warning and module version drift

* fix: use hatch build in PyPI publish workflow script (#304)

* fix: resolve startup module freshness home path dynamically (#306)

* fix: harden module signing workflow and reduce startup log noise

* test: align module migration compatibility with decoupled module versions

* fix: fail fast on invalid base ref in changed-only module signing

* fix: stabilize module precedence and backlog github mapping flow

* fix(module-registry): persist disables and correct bundled availability

* Re-sign module registry and fix / ignore local temp artifacts

* bump module registry version to 0.1.3

* fix(registry): restore protocol reporting logs in debug mode

* fix(backlog): harden refine writeback, prompts, and any-filter semantics (#311)

* fix(backlog): harden refine writeback, prompts, and daily any filters

* fix(github): default story type fallback to feature

* Fix format

* Fix codex review findings

* bump and sign changed modules

* chore(hooks): enforce module signature verification in pre-commit

* chore(hooks): add markdownlint to pre-commit checks

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(hooks,ado): correct format gate and enforce iteration on direct
  id lookup

* Apply review findings and fix tests

* Pin virtualenv < 21 to avoid incaopatibility failure

* fix: finalize backlog-core-06 ado comment API versioning (#314)

* fix(backlog): harden refine writeback, prompts, and daily any filters

* fix(github): default story type fallback to feature

* Fix format

* Fix codex review findings

* bump and sign changed modules

* chore(hooks): enforce module signature verification in pre-commit

* chore(hooks): add markdownlint to pre-commit checks

* fix: finalize backlog-core-06 ado comment api versioning and ci hatch pins

* fix: address review findings for formatter safety and ado metric patch guards

* docs(openspec): update CHANGE_ORDER status tracking

* fix(ado): apply iteration filter for direct issue_id lookup

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat: Advanced marketplace features (marketplace-02) - dependency resolution, aliases, custom registries, publishing (#318)

* feat: advanced marketplace features (marketplace-02) - dependency resolution, aliases, custom registries, namespace enforcement, publishing

- dependency_resolver: resolve_dependencies(), --skip-deps, --force on install
- alias_manager: alias create/list/remove (no top-level alias commands)
- custom_registries: add-registry, list-registries, remove-registry; fetch_all_indexes; search Registry column
- module_installer: namespace/name enforcement, collision detection
- scripts/publish-module.py + .github/workflows/publish-modules.yml (optional signing)
- docs: publishing-modules, custom-registries, dependency-resolution; updated installing-modules, module-marketplace, commands
- version 0.38.0, CHANGELOG

Made-with: Cursor

* docs(openspec): defer 6.2.4 and 6.2.5 (index update/PR, workflow test) to later

Made-with: Cursor

* Add follow-up change proposals for marketplace

* Fix codex review findings

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: complete marketplace publish registry PR flow and bump (#320)

0.38.1

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: update init ide hint and repair publish workflow
  condition

* feat(backlog): normalize daily summarize Markdown output (#323)

* 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>

* Update version

* Add github skills

* Add new marketplace changes

* feat(cli): category groups and flat shims using real module Typer (#331)

* 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>

* Update docs regarding module migration change

* feat: module-migration-02 bundle extraction (#332)

* 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>

* Implement blockers to prepare for module-migration-03 change. (#336)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat: module-migration-03 core slimming closeout and registry fixes (#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>

* Finalize module-migration-02 change

* docs(backlog-auth): update auth docs and OpenSpec task status (#342)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* chore(openspec): archive completed changes and sync main specs

* docs(openspec): prefix module migration proposal titles with IDs

* Add bug change for ado required fields setting and update change order

* Update change order

* feat(core): finalize migration-03 auth removal and 3-core slim package (#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>

* Archive module-migration-03 change

* feat: remove flat command shims (category-only CLI) (#344)

* feat: remove flat command shims from grouped registry

* Finalize change module-migration-04 implementation

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Archived module-migration-04 and updated specs

* docs(openspec): finalize module-migration-05 tracking after modules PR 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>

* Archive module-migration-05 change and update specs

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

* 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>

* Archived module-migration-06 change and updated specs

* test: module-migration-07 core test ownership cleanup (#347)

* 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>

* Archived backlog-core-07 change and updated specs

* Update some docs and archive latest finished changes and specs

* Add docs update change

* feat: add agile-01-feature-hierarchy change and update CHANGE_ORDER.md (#376)

- Create openspec/changes/agile-01-feature-hierarchy/ with proposal.md and tasks.md
- Add Epics #256 (Architecture Layer Integration), #257 (AI IDE Integration),
  and #258 (Integration Governance and Dogfooding) to CHANGE_ORDER.md parent issues table
- 25 GitHub Feature issues created (#351-#375), linked to their parent Epics
- Feature label created; issue #185 closed (ceremony-cockpit-01, archived 2026-02-18)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: align core docs and sync pending changes (#377)

* docs: align core docs and sync pending changes

* fix: preserve partial staging in markdown autofix hook

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: stabilize release test suite after module migration

* Update module

* Fix module install

* Fix module install

* Fix failed tests

* Fix marketplace client regression

* Fix install regression for specfact-cli (#380)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add changes to improve runtime validation and backlog module remaining migration to module

* refactor: remove backlog ownership from core cli (#384)

* refactor: remove backlog ownership from core cli

* fix: align CI marketplace validation paths

* test: stabilize command audit validation and add command-surface change

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add new command alignment change

* fix: finalize cli runtime validation regressions (#387)

* fix: finalize cli runtime validation regressions

* test: align satisfied dependency logging assertions

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive cli-val-07 change

* Archive changes and update specs

* Add code-review change proposals

* test: align command surface regression coverage

* docs: add OpenSpec change for backlog-core commands migration (#390)

* feat: add OpenSpec change for backlog-core commands migration

Change: backlog-02-migrate-core-commands
- Add proposal, design, tasks, specs
- Add TDD_EVIDENCE.md with implementation progress
- GitHub Issue: #389

Rules applied: AGENTS.md Git Worktree Policy, TDD Hard Gate

Made-with: Cursor

* docs: update TDD_EVIDENCE and tasks for quality gate results

Made-with: Cursor

* docs: update TDD_EVIDENCE with test fix results

Made-with: Cursor

* docs: update TDD_EVIDENCE with all test fixes complete

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: use POST instead of PATCH for ADO work item creation (#391)

* fix: use POST instead of PATCH for ADO work item creation

Azure DevOps API requires POST (not PATCH) for creating work items.

Also fixed category grouping to always register group commands.

Made-with: Cursor

* docs: add changelog entry for ADO POST fix

Made-with: Cursor

* chore: bump version to 0.40.4

Made-with: Cursor

* fix: update test mocks from PATCH to POST for ADO create

- Reverted incorrect unconditional _mount_installed_category_groups call

- Updated test_create_issue mocks to use requests.post instead of requests.patch

Made-with: Cursor

* test: skip category group test when bundles not installed

The test_bootstrap_with_category_grouping_disabled_registers_flat_commands test

expects bundles like specfact-codebase to be installed, but in CI they may not be.

Added pytest.skip() when 'code' command is not available.

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive backlog-02-migrate-core-commands change

- Archived backlog-02-migrate-core-commands change

- Updated CHANGE_ORDER.md with implementation status

- Updated main specs with backlog-add, backlog-analyze-deps, backlog-delta, backlog-sync, backlog-verify-readiness

Made-with: Cursor

* feat: document code-review module scaffold (#410)

* feat: document code-review module scaffold

* chore: sync 0.41.0 release version artifacts

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add change for project codebase ownership

* Realign code import ownership surface (#412)

* Realign code import ownership surface

* Harden temp registry command audit test

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Update code review changes

* docs: update reward ledger OpenSpec tracking (#413)

Link the existing change issue, record TDD evidence, and align the OpenSpec artifacts with the bundle-owned DDL and paired worktree implementation flow.

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Track house-rules skill OpenSpec changes (#414)

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: Update change-proposal for code-review-07 (#415)

* Track house-rules skill OpenSpec changes

Made-with: Cursor

* Cursor: Apply local changes for cloud agent

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Finalize code-review-07 status

* Finalize code-review-08 status

* feat: apply code-review-09 pre-commit integration

* fix: fall back when cached hatch test env is broken

* fix: avoid hatch env for coverage xml export

* fix: install type-check and lint tools directly in CI

* fix: install pytest fallback deps in test job

* fix: install pytest-cov for test fallback path

* Finalize code-review-09 status

* [Change] Align core docs with modules site ownership (#419)

* Align core docs with modules site ownership

* Close docs portal change PR task

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden docs parity URL assertions

* Archive finished changes and update specs

* docs: fix command syntax parity after lean-core/modules split (v0.42.2) (#421)

Replace all stale CLI syntax families in authored docs with current
shipped commands. Adds docs parity tests that guard against regression.

Removed syntax families corrected:
- specfact project plan → project devops-flow / project snapshot / govern enforce sdd
- project import from-bridge → code import from-bridge
- specfact backlog policy → backlog verify-readiness / backlog refine
- specfact spec contract → spec validate / spec generate-tests / spec mock
- specfact spec sdd constitution → govern enforce sdd [BUNDLE]
- spec generate <prompt-subcommands> → AI IDE skills or removed

Updated docs: README.md, docs/index.md, docs/README.md,
docs/reference/commands.md (+4 reference docs),
docs/getting-started/ (4 files), docs/guides/ (21 files),
docs/examples/ (5 files), docs/prompts/ (2 files).

Added 11 new docs parity tests in test_release_docs_parity.py:
- 7 tests asserting removed syntax families stay absent
- 4 tests asserting current command families remain documented

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Archive finished changes and update specs

- Archive docs-03-command-syntax-parity (2026-03-18)
- Sync delta specs: cli-output + documentation-alignment updated with
  post-split command-surface alignment requirements and scenarios
- Update CHANGE_ORDER.md: mark docs-03 as archived

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

* Update evidence

* Potential fix for pull request finding 'Unused global variable'

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>

* docs: align core docs ownership and parity (#424)

* docs: fix command syntax parity after lean-core/modules split (v0.42.2)

Replace all stale CLI syntax families in authored docs with current
shipped commands. Adds docs parity tests that guard against regression.

Removed syntax families corrected:
- specfact project plan → project devops-flow / project snapshot / govern enforce sdd
- project import from-bridge → code import from-bridge
- specfact backlog policy → backlog verify-readiness / backlog refine
- specfact spec contract → spec validate / spec generate-tests / spec mock
- specfact spec sdd constitution → govern enforce sdd [BUNDLE]
- spec generate <prompt-subcommands> → AI IDE skills or removed

Updated docs: README.md, docs/index.md, docs/README.md,
docs/reference/commands.md (+4 reference docs),
docs/getting-started/ (4 files), docs/guides/ (21 files),
docs/examples/ (5 files), docs/prompts/ (2 files).

Added 11 new docs parity tests in test_release_docs_parity.py:
- 7 tests asserting removed syntax families stay absent
- 4 tests asserting current command families remain documented

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

* docs: align core docs ownership and parity

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: fix quickstart install guidance

* docs: remove generated project plan docs

* Add code-review change

* fix: preserve native backlog import payloads (#429)

* fix: preserve native backlog import payloads

* fix: preserve imported proposal ids on reimport

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: add docs review workflow and repair docs links (#428)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: keep imported change ids stable across title changes (#431)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: remove conflicting pages file copies

* Add docs sync changs

* docs: update openspec clean-code planning

* Update change status

* fix: code-review-zero-findings dogfood remediation (v0.42.3) (#435)

* fix: continue code review remediation and align module signing

* fix: complete code-review-zero-findings dogfood remediation (v0.42.3)

Eliminates full-scope code review findings (types, Radon CC, contracts, lint) and records OpenSpec change code-review-zero-findings with tests and CHANGELOG. Module manifests may need re-signing before merge per project policy.

Made-with: Cursor

* chore: re-sign bundled modules after content changes

* fix: resolve review follow-up regressions

* fix: run ci smart-test directly

* fix: restore ci test progress output

* fix: stabilize command audit ci test

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add docs refactoring changes

* Add bug change tracking for encoding and resources

* docs: restructure core site IA to 6-section progressive nav (#442)

* docs: restructure core site IA from 5 flat sections to 6 progressive sections

Restructure docs.specfact.io from a flat 5-section sidebar to a 6-section
progressive navigation: Getting Started, Core CLI, Module System, Architecture,
Reference, Migration.

- Create docs/core-cli/, docs/module-system/, docs/migration/ directories
- Move 12 files to correct new sections with jekyll-redirect-from entries
- Write 3 new CLI reference pages: init.md, module.md, upgrade.md
- Replace first-steps.md with focused 5-minute quickstart
- Rewrite index.md as portal landing with core vs modules delineation
- Rewrite getting-started/README.md to link module tutorials to modules site
- Update sidebar navigation in _layouts/default.html
- Delete 6 obsolete files (competitive-analysis, ux-features, common-tasks,
  workflows, testing-terminal-output, guides/README)
- Add documentation-alignment delta spec for core-only focus policy

Implements: #438
OpenSpec: docs-05-core-site-ia-restructure

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

* docs: fix broken internal links after IA restructure

Update all relative links across 40 files to point to new file locations:
- ../reference/architecture.md → ../architecture/overview.md
- ../reference/debug-logging.md → ../core-cli/debug-logging.md
- ../reference/modes.md → ../core-cli/modes.md
- guides/ sibling links → ../module-system/ or ../migration/
- module-system/ back-links → ../guides/
- Remove links to deleted files (common-tasks, workflows)
- first-steps.md → quickstart.md

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

* fix: update test path for moved bootstrap-checklist and fix remaining broken links

- Update test_module_bootstrap_checklist_uses_current_bundle_ids to use
  new path docs/module-system/bootstrap-checklist.md
- Fix 2 remaining command-chains.md anchor links in migration-guide.md

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: harden cross-platform runtime and IDE resource discovery (#443)

* fix: harden cross-platform runtime and IDE resource discovery

* fix: bump patch version to 0.42.4

* fix: restore init lifecycle compatibility

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: resolve review type-safety findings

* Improve clarity and scope of ide prompt change

* feat(init): IDE prompt source catalog, --prompts, namespaced exports (#445)

* feat(init): IDE prompt source catalog, --prompts, namespaced exports

Implement init-ide-prompt-source-selection: discover core + module prompts,
default export all sources, interactive multi-select, non-interactive --prompts,
source-namespaced IDE paths. Fix project module roots to use metadata source
project. Extend discovery roots with user/marketplace. Update startup_checks
for nested exports. Bump init module to 0.1.14 with signed manifest.

Made-with: Cursor

* fix(init): scope VS Code prompt recommendations to exported sources

- Pass prompts_by_source into create_vscode_settings from copy_prompts_by_source_to_ide
- Strip prior .github/prompts/* recommendations on selective export to avoid stale paths
- Extract helpers for catalog paths and fallbacks; keep code review clean

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix tests

* release: bump version to 0.42.5 and update CHANGELOG

- Remove [Unreleased] sections; fold historical arch-08 notes under [0.34.0]
- Document init ide catalog, VS Code recommendations, integration test isolation

Made-with: Cursor

* Fix review findings

* feat(init): selective IDE prompt export cleanup and VS Code recommendation strip

- Prune stale exports and unselected catalog segments in copy_prompts_by_source_to_ide
- Strip only specfact*.prompt.md under .github/prompts/ when merging VS Code settings
- Tighten e2e missing-templates assertions to match CLI output
- Add unit tests for prompt path helper and selective export behavior

Made-with: Cursor

* Fix review findings

* Add missing import

* Bump patch version and changelog

* Fix failed tests

* Fix review findings

* docs: core vs modules URL contract and OpenSpec alignment (#448)

* docs: add core vs modules URL contract and OpenSpec alignment

Document cross-site permalink rules in docs/reference, extend documentation-alignment
and module-docs-ownership specs, update docs-07 and openspec config, and note the
dependency on modules URL policy in CHANGE_ORDER.

Made-with: Cursor

* docs: convert core handoff pages to modules canonical links (docs-07)

- Replace 20 duplicate guides/tutorials with thin summaries, prerequisites,
  and links to modules.specfact.io per URL contract
- Add docs/reference/core-to-modules-handoff-urls.md mapping table
- Align OpenSpec documentation-alignment spec delta with ADDED Requirements
- Complete docs-07-core-handoff-conversion tasks checklist

Refs: #439
Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat(docs-12): docs command validation and cross-site link checks (#449)

* feat(docs-12): docs command validation and cross-site link checks

- Add check-docs-commands (Typer CliRunner prefix + --help) and exclusions for migration/illustrative pages
- Add check-cross-site-links with robust URL extraction; warn-only in docs-validate and CI while live site may lag
- Extend docs-review: Hatch env, validation steps, pytest tests/unit/docs/
- Opt-in handoff map HTTP test (SPECFACT_RUN_HANDOFF_URL_CHECK=1)
- OpenSpec deltas, TDD_EVIDENCE, tasks complete; CHANGELOG [Unreleased]

Made-with: Cursor

* fix(docs-validate): strip leading global flags before command path

- Parse --mode/--input-format/--output-format + value, then other root flags
- Add test for specfact --mode copilot import from-code …
- Fix showcase docs: hatch run contract-test-exploration (not specfact)

Made-with: Cursor

* fix(docs-12): harden link/command validators and spec wording

- Capitalize Markdown in cross-site link spec requirement
- Cross-site: redirect-only HTTP success, UTF-8 read failures, URL delimiter/trim fixes
- Docs commands: catch Typer exceptions on --help, UTF-8 read failures
- Tests: shared loader for check-cross-site-links module

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(scripts): CliRunner without mix_stderr for Click 8.3+ compatibility (#451)

Default CliRunner() merges stderr into stdout; read stdout only so
accessing result.stderr does not raise when streams are combined.

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: review gates (semgrep print, radon CC, icontract, questionary types) (#452)

* fix: satisfy review gates for docs scripts and module_lifecycle typing

- Replace print() with Rich Console in docs validation scripts (semgrep)
- Split HTTP URL checks and doc scans to reduce cyclomatic complexity (radon)
- Add icontract require/ensure on public helpers; use CliRunner() without mix_stderr
- Cast questionary API for basedpyright reportUnknownMemberType

Made-with: Cursor

* fix(scripts): address #452 review (HTTP helpers, icontract, CLI streams)

- _http_success_code: use int directly after None guard
- _response_status: safe getcode via getattr/callable
- check-docs: drop @require preconditions duplicated by beartype
- _cli_invoke_streams_text: merge stdout + stderr for not-installed detection

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add speckit adapter alignment change and update affected change specs

* feat(adapters): spec-kit v0.4.x adapter alignment (#454)

* feat(adapters): spec-kit v0.4.x adapter alignment — extensions, presets, hooks, version detection, 7-command presets

Update SpecKitAdapter, ToolCapabilities, BridgeConfig presets, and
SpecKitScanner for spec-kit v0.4.3 compatibility:

- ToolCapabilities: 5 new optional fields (extensions, extension_commands,
  presets, hook_events, detected_version_source)
- SpecKitScanner: scan_extensions(), scan_presets(), scan_hook_events()
  with .extensionignore support and defensive JSON parsing
- SpecKitAdapter: 3-tier version detection (CLI → heuristic → None),
  refactored get_capabilities() with reduced cyclomatic complexity
- BridgeConfig: all 3 speckit presets expanded from 2 to 7 command
  mappings (specify, plan, tasks, implement, constitution, clarify, analyze)
- 42 new tests across 4 test files (110 targeted, 2248 full suite pass)
- Docs updated: comparison matrix, journey guide, integrations overview,
  adapter development guide

Closes #453

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

* fix: address CodeRabbit review findings

- Use get_bridge_logger instead of logging.getLogger in speckit adapter
  and scanner (production command path convention)
- Narrow except Exception to except OSError in _load_extensionignore
- Simplify redundant base_path conditional in get_capabilities
- Use SimpleNamespace instead of dynamic type() in tests
- Add subprocess.TimeoutExpired and OSError exception tests for CLI
  version detection
- Fix duplicate MD heading in bridge-adapter spec
- Add blank lines after markdown headings in proposal (MD022)

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump version to 0.43.0 for spec-kit v0.4.x alignment (#455)

* chore: bump version to 0.43.0 and add changelog entry

Minor version bump for spec-kit v0.4.x adapter alignment feature.
Syncs version across pyproject.toml, setup.py, and __init__.py.
Adds changelog entry documenting new capabilities.

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

* Sync deps and fix changelog

* Sync deps and fix changelog

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(packaging): remove workflow prompts from core wheel (packaging-02 #441, v0.43.1) (#456)

* fix(packaging): drop duplicate workflow prompts from core wheel (packaging-02 3.5)

Remove resources/prompts from wheel force-include and repo tree; canonical
copies remain in specfact-cli-modules bundles. Align startup IDE drift
checks and init template resolution with discover_prompt_template_files.
Bump to 0.43.1; re-sign init module 0.1.19. Update CHANGELOG, docs, OpenSpec.

Made-with: Cursor

* fix: address PR review (changelog, TDD evidence, startup checks, tests)

- Changelog 0.43.1 header uses Unreleased until release tag
- TDD_EVIDENCE: pre-fail block for Task 3.5 before passing verification
- TemplateCheckResult.sources_available; skip last_checked_version bump when no
  discoverable prompts; drift missing only when source exists
- Integration _fake_discover respects include_package_fallback
- test_validate_all_prompts uses tmp_path; re-enable file in default test run
- test_print_startup_checks_version_update_no_type uses stale version timestamp

Made-with: Cursor

* fix: address follow-up PR review (startup metadata, tests)

- Use ide_dir directly in TemplateCheckResult when IDE folder exists
- Set last_checked_version only after successful template-source checks
- Integration test: assert discover_prompt_template_files fallback + stable startup patches
- validate_all_prompts test: valid vs invalid specfact.*.md outcomes

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Potential fix for pull request finding 'Empty except'

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>

* Fix changelog version

* docs: unify core docs portal UX (#459)

* docs: unify core docs portal UX

* Fix docs-13 core review findings

* Address docs-13 PR review feedback

* Address follow-up docs review feedback

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Harden docs home URL test assertion

* feat: doc frontmatter validation, v0.43.2 review JSON gate, and pre-commit review UX (#463)

* chore(release): v0.43.2 pre-commit review JSON + OpenSpec dogfood rules

- Pre-commit gate writes ReviewReport JSON to .specfact/code-review.json
- openspec/config.yaml: require fresh review JSON and remediate findings
- Docs and unit tests updated

Made-with: Cursor

* fix: CodeRabbit — changelog, openspec TDD_EVIDENCE freshness, review hook timeout

- CHANGELOG 0.43.2: expanded entries, line wrap
- openspec/config.yaml: exclude TDD_EVIDENCE.md from review JSON staleness
- pre_commit_code_review: timeout 300s, TimeoutExpired handling
- tests: exact cwd, timeout assertion and timeout failure test

Made-with: Cursor

* Add code review to pre-commit and frontmatter docs validation

* Improve pre-commit script output

* Improve specfact code review findings output

* Fix review findings

* Improve pre-commit hook output

* Enable dev branch code review

* Update code review hook

* Fix contract review findings

* Fix review findings

* Fix review warnings

* feat: doc frontmatter hardening and code-review gate fixes

- Typer CLI for doc-frontmatter-check; safer owner resolution (split helpers for CC)
- Strict exempt handling; pre-commit hook matches USAGE-FAQ.md; review script JSON typing
- Shared test fixtures/types; integration/unit test updates; OpenSpec tasks and TDD evidence
- Changelog: pre-commit code-review-gate UX note

Made-with: Cursor

* Fix test failures and add docs review to github action runner

* Fix test failure due to UTF8 encoding

* Apply review findings

* Optimize pr orchestrator runtime

* Optimize pr orchestrator runtime

* Fix caching on pr-orchestrator

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive doc-frontmatter-schema openspec change

* Apply suggestions from code review

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>

* fix: restore protocol stubs for type checking

* Add frontamtter check

* fix: harden protocol stubs for code quality

* Add PR test hardening change

* fix: remediate review findings and harden review gates

* fix: rebuild review report model for pydantic

* Add story and onboarding change

* Update change tracking

* Improve scope for ci/cd requirements

* docs: sharpen first-contact story and onboarding (#467)

* docs: sharpen first-contact story and onboarding

* docs: address first-contact review feedback

* docs: address onboarding review fixes

* test: accept default-filtered site tokens in docs parity

* docs: record completed onboarding quality gates

* test: improve first-contact assertion failures

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden review blockers and bump patch version

* test: harden modules docs url assertions

* fix: harden trustworthy green checks (#469)

* fix: harden trustworthy green checks

* fix: restore contract-first ci repro command

* fix: apply CodeRabbit auto-fixes

Fixed 3 file(s) based on 3 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

* fix: resolve CI failures for trustworthy green checks PR

- Use hatch run contract-test instead of specfact code repro in CI
  (CLI bundle not available in CI environment)
- Allow test_bundle_import.py in migration cleanup legacy-import check
  (_bundle_import is an internal helper, not a removed module package)
- Fix formatting in test_trustworthy_green_checks.py (CodeRabbit commit
  was unformatted)

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

* fix: address CodeRabbit review findings

- Add trailing newline to TDD_EVIDENCE.md (MD047)
- Make _load_hooks() search for repo: local instead of assuming index 0
- Replace fragile multi-line string assertion in actionlint test with
  semantic line-by-line checks

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address CodeRabbit review findings for ci-02 (#471)

- Widen workflow_changed filter to include scripts/run_actionlint.sh
  and scripts/yaml-tools.sh so Workflow Lint triggers on script changes
- Pin actionlint default to v1.7.11 (matches CI) instead of latest
- Fix run_actionlint.sh conflating "not installed" with "lint failures"
  by separating availability check from execution
- Restore sys.path after test_bundle_import to avoid cross-test leakage
- Normalize CHANGE_ORDER.md status format to semicolon convention

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: propagate docker actionlint exit code instead of masking failures (#472)

Simplify run_actionlint.sh control flow so both local and docker
execution paths propagate actionlint's exit code via `exit $?`. Previously
the docker path used `if run_with_docker; then exit 0; fi` which treated
lint errors as "docker unavailable" and fell through to install guidance.

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: assert hook id stability and cd to repo root for local actionlint (#473)

- Assert hook id == "specfact-smart-checks" to prevent silent renames
- cd to REPO_ROOT before running local actionlint so it finds workflows
  regardless of caller's cwd

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat: clean-code-01-principle-gates — 7-principle charter gates, v0.44.0 (#474)

* feat: clean-code-01-principle-gates — 7-principle charter gates, v0.44.0

Implements openspec/changes/clean-code-01-principle-gates:

- Rewrote .cursor/rules/clean-code-principles.mdc as a canonical alias
  surface for the 7-principle clean-code charter (naming, kiss, yagni,
  dry, solid) defined in nold-ai/specfact-cli-modules. Documents Phase A
  KISS thresholds (>80 warning / >120 error LOC), nesting-depth and
  parameter-count checks active, and Phase B (>40/80) explicitly deferred.
- Added Clean-Code Review Gate sections to AGENTS.md and CLAUDE.md listing
  all 5 expanded review categories and the Phase A thresholds.
- Created .github/copilot-instructions.md as a lightweight alias (< 30 lines)
  referencing the canonical charter without duplicating it inline.
- Added unit tests (test_clean_code_principle_gates.py) covering all three
  spec scenarios: charter references, compliance gate, LOC/nesting thresholds.
- TDD evidence recorded in openspec/changes/clean-code-01-principle-gates/TDD_EVIDENCE.md.
- Bumped version 0.43.3 → 0.44.0 (minor — feature branch).
- Updated CHANGELOG.md and openspec/CHANGE_ORDER.md.

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

* fix: clean-code-01-principle-gates review findings and broad exception handling\n\n- Fix coderabbitai review findings:\n  - Clarify T20 and W0718 are aspirational in clean-code-principles.mdc\n  - Add language specifier to TDD_EVIDENCE.md fenced code block\n  - Update test to check all 7 canonical principles\n  - Make LOC threshold assertion more specific\n- Improve exception handling throughout codebase:\n  - Replace broad except Exception with specific exceptions\n  - Apply SOLID principle for better error handling\n- Update tasks.md to reflect completion status\n\nFixes #434\n\nGenerated by Mistral Vibe.\nCo-Authored-By: Mistral Vibe <vibe@mistral.ai>

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: archive completed openspec changes and update main specs

Archive 11 completed OpenSpec changes:
- bugfix-02-ado-import-payload-slugging
- ci-02-trustworthy-green-checks
- clean-code-01-principle-gates
- code-review-zero-findings
- docs-04-docs-review-gate-and-link-integrity
- docs-05-core-site-ia-restructure
- docs-07-core-handoff-conversion
- docs-12-docs-validation-ci
- docs-13-core-nav-search-theme-roles
- docs-14-first-contact-story-and-onboarding
- init-ide-prompt-source-selection
- packaging-02-cross-platform-runtime-and-module-resources
- speckit-02-v04-adapter-alignment

Fix spec validation errors:
- Add proper delta headers (ADDED/MODIFIED/REMOVED/RENAMED)
- Use correct scenario format with GIVEN/WHEN/THEN bullets
- Ensure requirement headers match between delta and main specs
- Use correct operation type based on existing requirements

Update main specs with archived changes:
- backlog-adapter: various updates
- bridge-adapter: Spec-Kit v0.4.x capabilities
- bridge-registry: BridgeConfig preset updates
- code-review-module: new requirements
- debug-logging: enhancements
- devops-sync: improvements
- documentation-alignment: core vs modules separation
- review-cli-contracts: new contracts
- review-run-command: command updates

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* Add new user onboarding change

* docs & tooling: new user onboarding + smart-test and pre-commit review fixes (#477)

* Fix content for install, sync, uninstallä

* test(docs): align first-contact contracts and stabilize module CLI tests

- docs/index: restore Why does it exist?, tagline, OpenSpec, canonical core CLI story
- Update init profile tests for solo-developer + install all (code-review, six bundles)
- Lean help test accepts uvx init hint; upgrade/core_compatibility tests match runtime
- Autouse fixture re-bootstraps CommandRegistry after category-group tests
- Rebase tasks conflict resolved; TDD_EVIDENCE + tasks for gates 7.1/7.2/12.1/12.2

Made-with: Cursor

* fix(tools): smart-test baseline and pre-commit single code-review run

- Run full suite when smart-test cache has no last_full_run; force+auto falls back to full when incremental is a no-op
- Pre-commit: invoke pre_commit_code_review.py once (no xargs split) so .specfact/code-review.json is not clobbered
- Tests and OpenSpec tasks for docs-new-user-onboarding

Made-with: Cursor

* test: fix CI backlog copy assertions and module install test isolation

- Align backlog not-installed tests with solo-developer init guidance (no <profile> placeholder)
- Autouse: reset CommandRegistry, register_builtin_commands, rebuild_root_app_from_registry so module install tests work after registry-only clears

Made-with: Cursor

* docs: README wow path + tests locking entrypoint with docs

- README leads with uvx init + code review run --scope full; pip install secondary
- Unit contract tests: README and docs/index.md share canonical uvx strings and order
- E2E: init --profile solo-developer in temp git repo; registry ready for step two with mock bundles

Made-with: Cursor

* feat(init): solo-developer includes code-review bundle and marketplace install

- Add specfact-code-review to canonical bundles and solo-developer preset
- Install marketplace module nold-ai/specfact-code-review via install_bundles_for_init
- Docs index: core CLI story and default starting point copy for parity tests
- CLI: missing-module hint references solo-developer profile
- smart_test_coverage: icontract requires use (self, test_level) for method contracts
- Re-sign init and module_registry manifests; tests and registry updates

Made-with: Cursor

* fix(tools): align _run_changed_only with tuple return and baseline full run

- Return (success, ran_any) from _run_changed_only; run full suite when no last_full_run
- run_smart_tests(auto, force): fall back to full tests when incremental ran nothing
- Fix wow e2e fixture typing (Iterator[None]) for basedpyright

Unblocks PR #477 CI: type-check, tests, lint job.

Made-with: Cursor

* chore(release): bump to 0.45.1 and update OpenSpec tasks status

- Sync version across pyproject.toml, setup.py, and __init__ modules
- Changelog: 0.45.1 entry for dependency profiles, smart-test baseline, CI, UX
- openspec: rolling status snapshot and task checkboxes for PR verification
- Includes prior branch work: init/profile, module registry, docs entry path, workflows

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: code-review gate (Typer params), typer<0.24 vs semgrep, module upgrade tests (#479)

* fix: code-review gate (Typer params), typer<0.24 vs semgrep, module upgrade tests

- Split root/install Typer callbacks into merged param stubs (KISS param count).
- Patch typer.main via importlib; merge install param specs in module_registry.
- Cap typer<0.24 to stay compatible with semgrep click~=8.1.8.
- Invoke module_registry app directly in upgrade CLI tests (root app may lack module group).
- Refactors for first_run_selection, module_packages, registry tests, semgrep README.

Worktree: specfact-cli-worktrees/bugfix/code-review-cli-tests
Made-with: Cursor

* docs: use code import in examples (flat import removed from CLI)

Replace specfact [--flags] import from-code with specfact [--flags] code import
from-code so check-docs-commands matches the nested Typer path after removing
the flat import shim.

Made-with: Cursor

* Fix review findings

---------

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: restructure README for star conversion (#480)

* docs: restructure readme for star conversion

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: sync readme change tracking

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: relocate readme support artifacts

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: fix readme workflow snippet and pin demo capture

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: address remaining readme review findings

Co-authored-by: Dom <djm81@users.noreply.github.com>

---------

Co-authored-by: Dom <djm81@users.noreply.github.com>

* archived implemented changes

* Archive and remove outdated changes

* Split and refactor change proposals between both repos

* Archive alignment change

* Add changes and github hierarchy scripts

* feat: add GitHub hierarchy cache sync (#492)

* feat: add github hierarchy cache sync

* Backport improvements from modules scripts

* Fix review findings

* Make github sync script executable

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* [codex] Compact agent governance loading (#493)

* feat: compact agent governance loading

* docs: mark governance PR task complete

* docs: sync governance-03 github issue metadata

* fix: restore dev branch governance block

* Apply review findings

* docs: add sibling internal wiki context for OpenSpec design

Point AGENTS.md, Claude/Copilot/Cursor surfaces, and the OpenSpec rule at
docs/agent-rules/40-openspec-and-tdd.md to read-only wiki paths (hot.md,
graph.md, concepts) via absolute paths when specfact-cli-internal is present.
Update INDEX applicability notes and extend governance tests.

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Archived github hierarchy change

* Update rules for openspec archive

* Potential fix for pull request finding 'Unused local variable'

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>

* Add wiki update notes

* Archive governance-03 change, format markdown, add wiki instructions for update

* Fix review findings

* Fix type errors

* fix: safe VS Code settings merge and project artifact writes (#490) (#496)

* fix: safe merge for VS Code settings.json on init ide (profile-04)

- Add project_artifact_write.merge_vscode_settings_prompt_recommendations with fail-safe
  on invalid JSON / bad chat shape; --force backs up to .specfact/recovery/ then replaces.
- Route ide_setup create_vscode_settings through helper; thread force; catch errors for CLI exit.
- Lint gate: scripts/verify_safe_project_writes.py blocks json.load/dump in ide_setup.py.
- Tests, installation docs, 0.45.2 changelog and version pins.

OpenSpec: profile-04-safe-project-artifact-writes
Made-with: Cursor

* fix(profile-04): satisfy review gate, pin setuptools for semgrep

- Refactor project_artifact_write merge path (KISS); icontract predicates
- Deduplicate ide_setup prompt helpers; import from project_artifact_write
- verify_safe_project_writes: ast.walk, contracts, beartype
- Pin setuptools<82 for Semgrep pkg_resources chain
- Update TDD_EVIDENCE and tasks checklist

Made-with: Cursor

* ci: run safe-write verifier in PR orchestrator lint job

Match hatch run lint by invoking scripts/verify_safe_project_writes.py
after ruff/basedpyright/pylint. Use set -euo pipefail so the first lint
failure is not masked by later commands.

Made-with: Cursor

* fix(profile-04): address CodeRabbit review (docs, guard, contracts, tests)

- Wrap installation.md VS Code merge paragraph to <=120 chars per line
- tasks 4.7 + TDD_EVIDENCE: openspec validate --strict sign-off
- verify_safe_project_writes: detect from-json import and aliases
- settings_relative_nonblank: reject absolute paths and .. segments
- ide_setup: _handle_structured_json_document_error for duplicate handlers
- ProjectWriteMode docstring (reserved policy surface); backup stamp + collision loop
- Tests: malformed settings preserved on init ide exit; force+chat coercion; AST guard tests

Made-with: Cursor

* fix(profile-04): JSON5 settings, repo containment, review follow-ups

- merge_vscode_settings: resolve containment before mkdir/write; JSON5 load/dump
  (JSONC comments; trailing_commas=False for strict JSON output)
- ide_setup: empty prompts_by_source skips catalog fallback (_finalize allow_empty_fallback)
- verify_safe_project_writes: detect import json as js attribute calls
- contract_predicates: prompt_files_all_strings accepts list[Any] for mixed-type checks
- Tests: symlink escape, JSONC merge, empty export strip, import-json-as-js guard
- tasks.md / TDD_EVIDENCE: wrap lines to <=120 chars; CHANGELOG + json5 dep + setup.py sync

Made-with: Cursor

* docs(profile-04): tasks pre-flight + full pytest; narrow icontract ensure

- tasks 1.1: hatch env create then smart-test-status and contract-test-status
- tasks 4.3: add hatch test --cover -v to quality gates
- TDD_EVIDENCE: shorter module-signatures and report lines (<=120 cols)
- project_artifact_write: isinstance(result, Path) in @ensure postconditions

Made-with: Cursor

* fix: clear specfact code review on safe-write modules

- verify_safe_project_writes: flatten json binding helpers; stderr writes
  instead of print; inline Import/ImportFrom loops to drop duplicate-shape DRY
- project_artifact_write: _VscodeChatMergeContext dataclass (KISS param count);
  typed chat_body cast before .get for pyright

Made-with: Cursor

* docs(profile-04): record hatch test --cover -v in TDD_EVIDENCE

Align passing evidence with tasks.md 4.3 full-suite coverage gate.

Made-with: Cursor

* fix: reduce KISS blockers (bridge sync contexts, tools, partial adapters)

Refactors high-parameter call sites into dataclasses/context objects and splits hot spots (export devops pipeline, smart_test_coverage incremental run, suggest_frontmatter, crosshair summary loop).

API: BridgeSync.export_change_proposals_to_devops(adapter_type, ExportChangeProposalsOptions | None); LoggerSetup.create_logger(name, LoggerCreateOptions | None); run_crosshair(path, CrosshairRunOptions | None).

Full specfact code review --scope full still reports error-severity kiss/radon findings (remaining nesting/LOC and param counts in ADO, analyzers, generators, source_scanner, module_installer, bundle-mapper, etc.). Gate PASS requires follow-up.

Made-with: Cursor

* Fix review findings and sign modules

* fix(tests): register dynamic check_doc_frontmatter module; align _update_cache tests

- Insert check_doc_frontmatter into sys.modules before exec_module so
  dataclasses can resolve string annotations (fixes Docs Review / agent
  rules governance fixture).
- Call SmartCoverageManager._update_cache with _SmartCacheUpdate after
  signature refactor (fixes basedpyright reportCallIssue).

Made-with: Cursor

* fix(tests): align install_module mocks with InstallModuleOptions; register verify_bundle script

- Monkeypatch/patch fakes now accept (module_id, options=None) matching
  install_module(module_id, InstallModuleOptions(...)).
- Read install_root, trust_non_official, non_interactive, reinstall from
  InstallModuleOptions in CLI command tests.
- Dynamic load of verify-bundle-published registers sys.modules before
  exec_module (same dataclass annotation issue as check_doc_frontmatter).

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Fix review findings (#498)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat(openspec): add marketplace-06-ci-module-signing change proposal

Moves module signing from local interactive requirement to CI step
triggered by PR approval (pull_request_review). Eliminates local private
key dependency for non-interactive development on feature/dev branches.
Trust boundary remains at main.

Scope:
- NEW .github/workflows/sign-modules-on-approval.yml
- MODIFY scripts/pre-commit-smart-checks.sh (branch-aware policy)
- MODIFY .github/workflows/pr-orchestrator.yml (split verify by target)
- MODIFY .github/workflows/sign-modules.yml (main-only enforcement)

GitHub: #500
Parent Feature: #353 (Marketplace Module Distribution) → #194 (Architecture Epic)
Paired modules change: specfact-cli-modules#185

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

* chore(pre-commit): modular hooks + branch-aware module verify (#501)

* chore(pre-commit): modular hooks aligned with specfact-cli-modules

- Add scripts/pre-commit-quality-checks.sh (block1 stages + block2; all for manual/shim)
- Replace monolithic smart-checks with shim to quality-checks all
- .pre-commit-config: fail_fast, verify-module-signatures + check-version-sources,
  cli-block1-* hooks, cli-block2, doc frontmatter
- Match modules: hatch run lint when Python staged; scoped code review paths
- CLI extras: Markdown fix/lint, workflow actionlint (no packages/ bundle-import gate)
- Bump to 0.46.1; docs: README, CONTRIBUTING, code-review.md, agent-rules/70

Made-with: Cursor

* fix(pre-commit): branch-aware module verify hook (marketplace-06 policy)

- Add scripts/pre-commit-verify-modules.sh and git-branch-module-signature-flag.sh
- Point verify-module-signatures hook at wrapper (script); skip when no staged module paths
- pre-commit-quality-checks all: delegate module step to wrapper; safe-change allowlist
- Tests + CONTRIBUTING/CHANGELOG alignment

Made-with: Cursor

* fix(pre-commit): address r…
djm81 added a commit that referenced this pull request Apr 16, 2026
…#509)

* fix: address signature-backend warning and module version drift

* fix: use hatch build in PyPI publish workflow script (#304)

* fix: resolve startup module freshness home path dynamically (#306)

* fix: harden module signing workflow and reduce startup log noise

* test: align module migration compatibility with decoupled module versions

* fix: fail fast on invalid base ref in changed-only module signing

* fix: stabilize module precedence and backlog github mapping flow

* fix(module-registry): persist disables and correct bundled availability

* Re-sign module registry and fix / ignore local temp artifacts

* bump module registry version to 0.1.3

* fix(registry): restore protocol reporting logs in debug mode

* fix(backlog): harden refine writeback, prompts, and any-filter semantics (#311)

* fix(backlog): harden refine writeback, prompts, and daily any filters

* fix(github): default story type fallback to feature

* Fix format

* Fix codex review findings

* bump and sign changed modules

* chore(hooks): enforce module signature verification in pre-commit

* chore(hooks): add markdownlint to pre-commit checks

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(hooks,ado): correct format gate and enforce iteration on direct
  id lookup

* Apply review findings and fix tests

* Pin virtualenv < 21 to avoid incaopatibility failure

* fix: finalize backlog-core-06 ado comment API versioning (#314)

* fix(backlog): harden refine writeback, prompts, and daily any filters

* fix(github): default story type fallback to feature

* Fix format

* Fix codex review findings

* bump and sign changed modules

* chore(hooks): enforce module signature verification in pre-commit

* chore(hooks): add markdownlint to pre-commit checks

* fix: finalize backlog-core-06 ado comment api versioning and ci hatch pins

* fix: address review findings for formatter safety and ado metric patch guards

* docs(openspec): update CHANGE_ORDER status tracking

* fix(ado): apply iteration filter for direct issue_id lookup

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat: Advanced marketplace features (marketplace-02) - dependency resolution, aliases, custom registries, publishing (#318)

* feat: advanced marketplace features (marketplace-02) - dependency resolution, aliases, custom registries, namespace enforcement, publishing

- dependency_resolver: resolve_dependencies(), --skip-deps, --force on install
- alias_manager: alias create/list/remove (no top-level alias commands)
- custom_registries: add-registry, list-registries, remove-registry; fetch_all_indexes; search Registry column
- module_installer: namespace/name enforcement, collision detection
- scripts/publish-module.py + .github/workflows/publish-modules.yml (optional signing)
- docs: publishing-modules, custom-registries, dependency-resolution; updated installing-modules, module-marketplace, commands
- version 0.38.0, CHANGELOG

Made-with: Cursor

* docs(openspec): defer 6.2.4 and 6.2.5 (index update/PR, workflow test) to later

Made-with: Cursor

* Add follow-up change proposals for marketplace

* Fix codex review findings

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: complete marketplace publish registry PR flow and bump (#320)

0.38.1

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: update init ide hint and repair publish workflow
  condition

* feat(backlog): normalize daily summarize Markdown output (#323)

* 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>

* Update version

* Add github skills

* Add new marketplace changes

* feat(cli): category groups and flat shims using real module Typer (#331)

* 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>

* Update docs regarding module migration change

* feat: module-migration-02 bundle extraction (#332)

* 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>

* Implement blockers to prepare for module-migration-03 change. (#336)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat: module-migration-03 core slimming closeout and registry fixes (#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>

* Finalize module-migration-02 change

* docs(backlog-auth): update auth docs and OpenSpec task status (#342)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* chore(openspec): archive completed changes and sync main specs

* docs(openspec): prefix module migration proposal titles with IDs

* Add bug change for ado required fields setting and update change order

* Update change order

* feat(core): finalize migration-03 auth removal and 3-core slim package (#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>

* Archive module-migration-03 change

* feat: remove flat command shims (category-only CLI) (#344)

* feat: remove flat command shims from grouped registry

* Finalize change module-migration-04 implementation

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Archived module-migration-04 and updated specs

* docs(openspec): finalize module-migration-05 tracking after modules PR 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>

* Archive module-migration-05 change and update specs

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

* 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>

* Archived module-migration-06 change and updated specs

* test: module-migration-07 core test ownership cleanup (#347)

* 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>

* Archived backlog-core-07 change and updated specs

* Update some docs and archive latest finished changes and specs

* Add docs update change

* feat: add agile-01-feature-hierarchy change and update CHANGE_ORDER.md (#376)

- Create openspec/changes/agile-01-feature-hierarchy/ with proposal.md and tasks.md
- Add Epics #256 (Architecture Layer Integration), #257 (AI IDE Integration),
  and #258 (Integration Governance and Dogfooding) to CHANGE_ORDER.md parent issues table
- 25 GitHub Feature issues created (#351-#375), linked to their parent Epics
- Feature label created; issue #185 closed (ceremony-cockpit-01, archived 2026-02-18)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: align core docs and sync pending changes (#377)

* docs: align core docs and sync pending changes

* fix: preserve partial staging in markdown autofix hook

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: stabilize release test suite after module migration

* Update module

* Fix module install

* Fix module install

* Fix failed tests

* Fix marketplace client regression

* Fix install regression for specfact-cli (#380)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add changes to improve runtime validation and backlog module remaining migration to module

* refactor: remove backlog ownership from core cli (#384)

* refactor: remove backlog ownership from core cli

* fix: align CI marketplace validation paths

* test: stabilize command audit validation and add command-surface change

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add new command alignment change

* fix: finalize cli runtime validation regressions (#387)

* fix: finalize cli runtime validation regressions

* test: align satisfied dependency logging assertions

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive cli-val-07 change

* Archive changes and update specs

* Add code-review change proposals

* test: align command surface regression coverage

* docs: add OpenSpec change for backlog-core commands migration (#390)

* feat: add OpenSpec change for backlog-core commands migration

Change: backlog-02-migrate-core-commands
- Add proposal, design, tasks, specs
- Add TDD_EVIDENCE.md with implementation progress
- GitHub Issue: #389

Rules applied: AGENTS.md Git Worktree Policy, TDD Hard Gate

Made-with: Cursor

* docs: update TDD_EVIDENCE and tasks for quality gate results

Made-with: Cursor

* docs: update TDD_EVIDENCE with test fix results

Made-with: Cursor

* docs: update TDD_EVIDENCE with all test fixes complete

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: use POST instead of PATCH for ADO work item creation (#391)

* fix: use POST instead of PATCH for ADO work item creation

Azure DevOps API requires POST (not PATCH) for creating work items.

Also fixed category grouping to always register group commands.

Made-with: Cursor

* docs: add changelog entry for ADO POST fix

Made-with: Cursor

* chore: bump version to 0.40.4

Made-with: Cursor

* fix: update test mocks from PATCH to POST for ADO create

- Reverted incorrect unconditional _mount_installed_category_groups call

- Updated test_create_issue mocks to use requests.post instead of requests.patch

Made-with: Cursor

* test: skip category group test when bundles not installed

The test_bootstrap_with_category_grouping_disabled_registers_flat_commands test

expects bundles like specfact-codebase to be installed, but in CI they may not be.

Added pytest.skip() when 'code' command is not available.

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive backlog-02-migrate-core-commands change

- Archived backlog-02-migrate-core-commands change

- Updated CHANGE_ORDER.md with implementation status

- Updated main specs with backlog-add, backlog-analyze-deps, backlog-delta, backlog-sync, backlog-verify-readiness

Made-with: Cursor

* feat: document code-review module scaffold (#410)

* feat: document code-review module scaffold

* chore: sync 0.41.0 release version artifacts

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add change for project codebase ownership

* Realign code import ownership surface (#412)

* Realign code import ownership surface

* Harden temp registry command audit test

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Update code review changes

* docs: update reward ledger OpenSpec tracking (#413)

Link the existing change issue, record TDD evidence, and align the OpenSpec artifacts with the bundle-owned DDL and paired worktree implementation flow.

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Track house-rules skill OpenSpec changes (#414)

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: Update change-proposal for code-review-07 (#415)

* Track house-rules skill OpenSpec changes

Made-with: Cursor

* Cursor: Apply local changes for cloud agent

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Finalize code-review-07 status

* Finalize code-review-08 status

* feat: apply code-review-09 pre-commit integration

* fix: fall back when cached hatch test env is broken

* fix: avoid hatch env for coverage xml export

* fix: install type-check and lint tools directly in CI

* fix: install pytest fallback deps in test job

* fix: install pytest-cov for test fallback path

* Finalize code-review-09 status

* [Change] Align core docs with modules site ownership (#419)

* Align core docs with modules site ownership

* Close docs portal change PR task

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden docs parity URL assertions

* Archive finished changes and update specs

* docs: fix command syntax parity after lean-core/modules split (v0.42.2) (#421)

Replace all stale CLI syntax families in authored docs with current
shipped commands. Adds docs parity tests that guard against regression.

Removed syntax families corrected:
- specfact project plan → project devops-flow / project snapshot / govern enforce sdd
- project import from-bridge → code import from-bridge
- specfact backlog policy → backlog verify-readiness / backlog refine
- specfact spec contract → spec validate / spec generate-tests / spec mock
- specfact spec sdd constitution → govern enforce sdd [BUNDLE]
- spec generate <prompt-subcommands> → AI IDE skills or removed

Updated docs: README.md, docs/index.md, docs/README.md,
docs/reference/commands.md (+4 reference docs),
docs/getting-started/ (4 files), docs/guides/ (21 files),
docs/examples/ (5 files), docs/prompts/ (2 files).

Added 11 new docs parity tests in test_release_docs_parity.py:
- 7 tests asserting removed syntax families stay absent
- 4 tests asserting current command families remain documented

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Archive finished changes and update specs

- Archive docs-03-command-syntax-parity (2026-03-18)
- Sync delta specs: cli-output + documentation-alignment updated with
  post-split command-surface alignment requirements and scenarios
- Update CHANGE_ORDER.md: mark docs-03 as archived

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

* Update evidence

* Potential fix for pull request finding 'Unused global variable'

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>

* docs: align core docs ownership and parity (#424)

* docs: fix command syntax parity after lean-core/modules split (v0.42.2)

Replace all stale CLI syntax families in authored docs with current
shipped commands. Adds docs parity tests that guard against regression.

Removed syntax families corrected:
- specfact project plan → project devops-flow / project snapshot / govern enforce sdd
- project import from-bridge → code import from-bridge
- specfact backlog policy → backlog verify-readiness / backlog refine
- specfact spec contract → spec validate / spec generate-tests / spec mock
- specfact spec sdd constitution → govern enforce sdd [BUNDLE]
- spec generate <prompt-subcommands> → AI IDE skills or removed

Updated docs: README.md, docs/index.md, docs/README.md,
docs/reference/commands.md (+4 reference docs),
docs/getting-started/ (4 files), docs/guides/ (21 files),
docs/examples/ (5 files), docs/prompts/ (2 files).

Added 11 new docs parity tests in test_release_docs_parity.py:
- 7 tests asserting removed syntax families stay absent
- 4 tests asserting current command families remain documented

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

* docs: align core docs ownership and parity

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: fix quickstart install guidance

* docs: remove generated project plan docs

* Add code-review change

* fix: preserve native backlog import payloads (#429)

* fix: preserve native backlog import payloads

* fix: preserve imported proposal ids on reimport

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: add docs review workflow and repair docs links (#428)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: keep imported change ids stable across title changes (#431)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: remove conflicting pages file copies

* Add docs sync changs

* docs: update openspec clean-code planning

* Update change status

* fix: code-review-zero-findings dogfood remediation (v0.42.3) (#435)

* fix: continue code review remediation and align module signing

* fix: complete code-review-zero-findings dogfood remediation (v0.42.3)

Eliminates full-scope code review findings (types, Radon CC, contracts, lint) and records OpenSpec change code-review-zero-findings with tests and CHANGELOG. Module manifests may need re-signing before merge per project policy.

Made-with: Cursor

* chore: re-sign bundled modules after content changes

* fix: resolve review follow-up regressions

* fix: run ci smart-test directly

* fix: restore ci test progress output

* fix: stabilize command audit ci test

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add docs refactoring changes

* Add bug change tracking for encoding and resources

* docs: restructure core site IA to 6-section progressive nav (#442)

* docs: restructure core site IA from 5 flat sections to 6 progressive sections

Restructure docs.specfact.io from a flat 5-section sidebar to a 6-section
progressive navigation: Getting Started, Core CLI, Module System, Architecture,
Reference, Migration.

- Create docs/core-cli/, docs/module-system/, docs/migration/ directories
- Move 12 files to correct new sections with jekyll-redirect-from entries
- Write 3 new CLI reference pages: init.md, module.md, upgrade.md
- Replace first-steps.md with focused 5-minute quickstart
- Rewrite index.md as portal landing with core vs modules delineation
- Rewrite getting-started/README.md to link module tutorials to modules site
- Update sidebar navigation in _layouts/default.html
- Delete 6 obsolete files (competitive-analysis, ux-features, common-tasks,
  workflows, testing-terminal-output, guides/README)
- Add documentation-alignment delta spec for core-only focus policy

Implements: #438
OpenSpec: docs-05-core-site-ia-restructure

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

* docs: fix broken internal links after IA restructure

Update all relative links across 40 files to point to new file locations:
- ../reference/architecture.md → ../architecture/overview.md
- ../reference/debug-logging.md → ../core-cli/debug-logging.md
- ../reference/modes.md → ../core-cli/modes.md
- guides/ sibling links → ../module-system/ or ../migration/
- module-system/ back-links → ../guides/
- Remove links to deleted files (common-tasks, workflows)
- first-steps.md → quickstart.md

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

* fix: update test path for moved bootstrap-checklist and fix remaining broken links

- Update test_module_bootstrap_checklist_uses_current_bundle_ids to use
  new path docs/module-system/bootstrap-checklist.md
- Fix 2 remaining command-chains.md anchor links in migration-guide.md

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: harden cross-platform runtime and IDE resource discovery (#443)

* fix: harden cross-platform runtime and IDE resource discovery

* fix: bump patch version to 0.42.4

* fix: restore init lifecycle compatibility

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: resolve review type-safety findings

* Improve clarity and scope of ide prompt change

* feat(init): IDE prompt source catalog, --prompts, namespaced exports (#445)

* feat(init): IDE prompt source catalog, --prompts, namespaced exports

Implement init-ide-prompt-source-selection: discover core + module prompts,
default export all sources, interactive multi-select, non-interactive --prompts,
source-namespaced IDE paths. Fix project module roots to use metadata source
project. Extend discovery roots with user/marketplace. Update startup_checks
for nested exports. Bump init module to 0.1.14 with signed manifest.

Made-with: Cursor

* fix(init): scope VS Code prompt recommendations to exported sources

- Pass prompts_by_source into create_vscode_settings from copy_prompts_by_source_to_ide
- Strip prior .github/prompts/* recommendations on selective export to avoid stale paths
- Extract helpers for catalog paths and fallbacks; keep code review clean

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix tests

* release: bump version to 0.42.5 and update CHANGELOG

- Remove [Unreleased] sections; fold historical arch-08 notes under [0.34.0]
- Document init ide catalog, VS Code recommendations, integration test isolation

Made-with: Cursor

* Fix review findings

* feat(init): selective IDE prompt export cleanup and VS Code recommendation strip

- Prune stale exports and unselected catalog segments in copy_prompts_by_source_to_ide
- Strip only specfact*.prompt.md under .github/prompts/ when merging VS Code settings
- Tighten e2e missing-templates assertions to match CLI output
- Add unit tests for prompt path helper and selective export behavior

Made-with: Cursor

* Fix review findings

* Add missing import

* Bump patch version and changelog

* Fix failed tests

* Fix review findings

* docs: core vs modules URL contract and OpenSpec alignment (#448)

* docs: add core vs modules URL contract and OpenSpec alignment

Document cross-site permalink rules in docs/reference, extend documentation-alignment
and module-docs-ownership specs, update docs-07 and openspec config, and note the
dependency on modules URL policy in CHANGE_ORDER.

Made-with: Cursor

* docs: convert core handoff pages to modules canonical links (docs-07)

- Replace 20 duplicate guides/tutorials with thin summaries, prerequisites,
  and links to modules.specfact.io per URL contract
- Add docs/reference/core-to-modules-handoff-urls.md mapping table
- Align OpenSpec documentation-alignment spec delta with ADDED Requirements
- Complete docs-07-core-handoff-conversion tasks checklist

Refs: #439
Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat(docs-12): docs command validation and cross-site link checks (#449)

* feat(docs-12): docs command validation and cross-site link checks

- Add check-docs-commands (Typer CliRunner prefix + --help) and exclusions for migration/illustrative pages
- Add check-cross-site-links with robust URL extraction; warn-only in docs-validate and CI while live site may lag
- Extend docs-review: Hatch env, validation steps, pytest tests/unit/docs/
- Opt-in handoff map HTTP test (SPECFACT_RUN_HANDOFF_URL_CHECK=1)
- OpenSpec deltas, TDD_EVIDENCE, tasks complete; CHANGELOG [Unreleased]

Made-with: Cursor

* fix(docs-validate): strip leading global flags before command path

- Parse --mode/--input-format/--output-format + value, then other root flags
- Add test for specfact --mode copilot import from-code …
- Fix showcase docs: hatch run contract-test-exploration (not specfact)

Made-with: Cursor

* fix(docs-12): harden link/command validators and spec wording

- Capitalize Markdown in cross-site link spec requirement
- Cross-site: redirect-only HTTP success, UTF-8 read failures, URL delimiter/trim fixes
- Docs commands: catch Typer exceptions on --help, UTF-8 read failures
- Tests: shared loader for check-cross-site-links module

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix(scripts): CliRunner without mix_stderr for Click 8.3+ compatibility (#451)

Default CliRunner() merges stderr into stdout; read stdout only so
accessing result.stderr does not raise when streams are combined.

Made-with: Cursor

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: review gates (semgrep print, radon CC, icontract, questionary types) (#452)

* fix: satisfy review gates for docs scripts and module_lifecycle typing

- Replace print() with Rich Console in docs validation scripts (semgrep)
- Split HTTP URL checks and doc scans to reduce cyclomatic complexity (radon)
- Add icontract require/ensure on public helpers; use CliRunner() without mix_stderr
- Cast questionary API for basedpyright reportUnknownMemberType

Made-with: Cursor

* fix(scripts): address #452 review (HTTP helpers, icontract, CLI streams)

- _http_success_code: use int directly after None guard
- _response_status: safe getcode via getattr/callable
- check-docs: drop @require preconditions duplicated by beartype
- _cli_invoke_streams_text: merge stdout + stderr for not-installed detection

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Add speckit adapter alignment change and update affected change specs

* feat(adapters): spec-kit v0.4.x adapter alignment (#454)

* feat(adapters): spec-kit v0.4.x adapter alignment — extensions, presets, hooks, version detection, 7-command presets

Update SpecKitAdapter, ToolCapabilities, BridgeConfig presets, and
SpecKitScanner for spec-kit v0.4.3 compatibility:

- ToolCapabilities: 5 new optional fields (extensions, extension_commands,
  presets, hook_events, detected_version_source)
- SpecKitScanner: scan_extensions(), scan_presets(), scan_hook_events()
  with .extensionignore support and defensive JSON parsing
- SpecKitAdapter: 3-tier version detection (CLI → heuristic → None),
  refactored get_capabilities() with reduced cyclomatic complexity
- BridgeConfig: all 3 speckit presets expanded from 2 to 7 command
  mappings (specify, plan, tasks, implement, constitution, clarify, analyze)
- 42 new tests across 4 test files (110 targeted, 2248 full suite pass)
- Docs updated: comparison matrix, journey guide, integrations overview,
  adapter development guide

Closes #453

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

* fix: address CodeRabbit review findings

- Use get_bridge_logger instead of logging.getLogger in speckit adapter
  and scanner (production command path convention)
- Narrow except Exception to except OSError in _load_extensionignore
- Simplify redundant base_path conditional in get_capabilities
- Use SimpleNamespace instead of dynamic type() in tests
- Add subprocess.TimeoutExpired and OSError exception tests for CLI
  version detection
- Fix duplicate MD heading in bridge-adapter spec
- Add blank lines after markdown headings in proposal (MD022)

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump version to 0.43.0 for spec-kit v0.4.x alignment (#455)

* chore: bump version to 0.43.0 and add changelog entry

Minor version bump for spec-kit v0.4.x adapter alignment feature.
Syncs version across pyproject.toml, setup.py, and __init__.py.
Adds changelog entry documenting new capabilities.

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

* Sync deps and fix changelog

* Sync deps and fix changelog

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(packaging): remove workflow prompts from core wheel (packaging-02 #441, v0.43.1) (#456)

* fix(packaging): drop duplicate workflow prompts from core wheel (packaging-02 3.5)

Remove resources/prompts from wheel force-include and repo tree; canonical
copies remain in specfact-cli-modules bundles. Align startup IDE drift
checks and init template resolution with discover_prompt_template_files.
Bump to 0.43.1; re-sign init module 0.1.19. Update CHANGELOG, docs, OpenSpec.

Made-with: Cursor

* fix: address PR review (changelog, TDD evidence, startup checks, tests)

- Changelog 0.43.1 header uses Unreleased until release tag
- TDD_EVIDENCE: pre-fail block for Task 3.5 before passing verification
- TemplateCheckResult.sources_available; skip last_checked_version bump when no
  discoverable prompts; drift missing only when source exists
- Integration _fake_discover respects include_package_fallback
- test_validate_all_prompts uses tmp_path; re-enable file in default test run
- test_print_startup_checks_version_update_no_type uses stale version timestamp

Made-with: Cursor

* fix: address follow-up PR review (startup metadata, tests)

- Use ide_dir directly in TemplateCheckResult when IDE folder exists
- Set last_checked_version only after successful template-source checks
- Integration test: assert discover_prompt_template_files fallback + stable startup patches
- validate_all_prompts test: valid vs invalid specfact.*.md outcomes

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Potential fix for pull request finding 'Empty except'

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>

* Fix changelog version

* docs: unify core docs portal UX (#459)

* docs: unify core docs portal UX

* Fix docs-13 core review findings

* Address docs-13 PR review feedback

* Address follow-up docs review feedback

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Harden docs home URL test assertion

* feat: doc frontmatter validation, v0.43.2 review JSON gate, and pre-commit review UX (#463)

* chore(release): v0.43.2 pre-commit review JSON + OpenSpec dogfood rules

- Pre-commit gate writes ReviewReport JSON to .specfact/code-review.json
- openspec/config.yaml: require fresh review JSON and remediate findings
- Docs and unit tests updated

Made-with: Cursor

* fix: CodeRabbit — changelog, openspec TDD_EVIDENCE freshness, review hook timeout

- CHANGELOG 0.43.2: expanded entries, line wrap
- openspec/config.yaml: exclude TDD_EVIDENCE.md from review JSON staleness
- pre_commit_code_review: timeout 300s, TimeoutExpired handling
- tests: exact cwd, timeout assertion and timeout failure test

Made-with: Cursor

* Add code review to pre-commit and frontmatter docs validation

* Improve pre-commit script output

* Improve specfact code review findings output

* Fix review findings

* Improve pre-commit hook output

* Enable dev branch code review

* Update code review hook

* Fix contract review findings

* Fix review findings

* Fix review warnings

* feat: doc frontmatter hardening and code-review gate fixes

- Typer CLI for doc-frontmatter-check; safer owner resolution (split helpers for CC)
- Strict exempt handling; pre-commit hook matches USAGE-FAQ.md; review script JSON typing
- Shared test fixtures/types; integration/unit test updates; OpenSpec tasks and TDD evidence
- Changelog: pre-commit code-review-gate UX note

Made-with: Cursor

* Fix test failures and add docs review to github action runner

* Fix test failure due to UTF8 encoding

* Apply review findings

* Optimize pr orchestrator runtime

* Optimize pr orchestrator runtime

* Fix caching on pr-orchestrator

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* docs: archive doc-frontmatter-schema openspec change

* Apply suggestions from code review

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>

* fix: restore protocol stubs for type checking

* Add frontamtter check

* fix: harden protocol stubs for code quality

* Add PR test hardening change

* fix: remediate review findings and harden review gates

* fix: rebuild review report model for pydantic

* Add story and onboarding change

* Update change tracking

* Improve scope for ci/cd requirements

* docs: sharpen first-contact story and onboarding (#467)

* docs: sharpen first-contact story and onboarding

* docs: address first-contact review feedback

* docs: address onboarding review fixes

* test: accept default-filtered site tokens in docs parity

* docs: record completed onboarding quality gates

* test: improve first-contact assertion failures

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: harden review blockers and bump patch version

* test: harden modules docs url assertions

* fix: harden trustworthy green checks (#469)

* fix: harden trustworthy green checks

* fix: restore contract-first ci repro command

* fix: apply CodeRabbit auto-fixes

Fixed 3 file(s) based on 3 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

* fix: resolve CI failures for trustworthy green checks PR

- Use hatch run contract-test instead of specfact code repro in CI
  (CLI bundle not available in CI environment)
- Allow test_bundle_import.py in migration cleanup legacy-import check
  (_bundle_import is an internal helper, not a removed module package)
- Fix formatting in test_trustworthy_green_checks.py (CodeRabbit commit
  was unformatted)

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

* fix: address CodeRabbit review findings

- Add trailing newline to TDD_EVIDENCE.md (MD047)
- Make _load_hooks() search for repo: local instead of assuming index 0
- Replace fragile multi-line string assertion in actionlint test with
  semantic line-by-line checks

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

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address CodeRabbit review findings for ci-02 (#471)

- Widen workflow_changed filter to include scripts/run_actionlint.sh
  and scripts/yaml-tools.sh so Workflow Lint triggers on script changes
- Pin actionlint default to v1.7.11 (matches CI) instead of latest
- Fix run_actionlint.sh conflating "not installed" with "lint failures"
  by separating availability check from execution
- Restore sys.path after test_bundle_import to avoid cross-test leakage
- Normalize CHANGE_ORDER.md status format to semicolon convention

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: propagate docker actionlint exit code instead of masking failures (#472)

Simplify run_actionlint.sh control flow so both local and docker
execution paths propagate actionlint's exit code via `exit $?`. Previously
the docker path used `if run_with_docker; then exit 0; fi` which treated
lint errors as "docker unavailable" and fell through to install guidance.

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: assert hook id stability and cd to repo root for local actionlint (#473)

- Assert hook id == "specfact-smart-checks" to prevent silent renames
- cd to REPO_ROOT before running local actionlint so it finds workflows
  regardless of caller's cwd

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat: clean-code-01-principle-gates — 7-principle charter gates, v0.44.0 (#474)

* feat: clean-code-01-principle-gates — 7-principle charter gates, v0.44.0

Implements openspec/changes/clean-code-01-principle-gates:

- Rewrote .cursor/rules/clean-code-principles.mdc as a canonical alias
  surface for the 7-principle clean-code charter (naming, kiss, yagni,
  dry, solid) defined in nold-ai/specfact-cli-modules. Documents Phase A
  KISS thresholds (>80 warning / >120 error LOC), nesting-depth and
  parameter-count checks active, and Phase B (>40/80) explicitly deferred.
- Added Clean-Code Review Gate sections to AGENTS.md and CLAUDE.md listing
  all 5 expanded review categories and the Phase A thresholds.
- Created .github/copilot-instructions.md as a lightweight alias (< 30 lines)
  referencing the canonical charter without duplicating it inline.
- Added unit tests (test_clean_code_principle_gates.py) covering all three
  spec scenarios: charter references, compliance gate, LOC/nesting thresholds.
- TDD evidence recorded in openspec/changes/clean-code-01-principle-gates/TDD_EVIDENCE.md.
- Bumped version 0.43.3 → 0.44.0 (minor — feature branch).
- Updated CHANGELOG.md and openspec/CHANGE_ORDER.md.

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

* fix: clean-code-01-principle-gates review findings and broad exception handling\n\n- Fix coderabbitai review findings:\n  - Clarify T20 and W0718 are aspirational in clean-code-principles.mdc\n  - Add language specifier to TDD_EVIDENCE.md fenced code block\n  - Update test to check all 7 canonical principles\n  - Make LOC threshold assertion more specific\n- Improve exception handling throughout codebase:\n  - Replace broad except Exception with specific exceptions\n  - Apply SOLID principle for better error handling\n- Update tasks.md to reflect completion status\n\nFixes #434\n\nGenerated by Mistral Vibe.\nCo-Authored-By: Mistral Vibe <vibe@mistral.ai>

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: archive completed openspec changes and update main specs

Archive 11 completed OpenSpec changes:
- bugfix-02-ado-import-payload-slugging
- ci-02-trustworthy-green-checks
- clean-code-01-principle-gates
- code-review-zero-findings
- docs-04-docs-review-gate-and-link-integrity
- docs-05-core-site-ia-restructure
- docs-07-core-handoff-conversion
- docs-12-docs-validation-ci
- docs-13-core-nav-search-theme-roles
- docs-14-first-contact-story-and-onboarding
- init-ide-prompt-source-selection
- packaging-02-cross-platform-runtime-and-module-resources
- speckit-02-v04-adapter-alignment

Fix spec validation errors:
- Add proper delta headers (ADDED/MODIFIED/REMOVED/RENAMED)
- Use correct scenario format with GIVEN/WHEN/THEN bullets
- Ensure requirement headers match between delta and main specs
- Use correct operation type based on existing requirements

Update main specs with archived changes:
- backlog-adapter: various updates
- bridge-adapter: Spec-Kit v0.4.x capabilities
- bridge-registry: BridgeConfig preset updates
- code-review-module: new requirements
- debug-logging: enhancements
- devops-sync: improvements
- documentation-alignment: core vs modules separation
- review-cli-contracts: new contracts
- review-run-command: command updates

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* Add new user onboarding change

* docs & tooling: new user onboarding + smart-test and pre-commit review fixes (#477)

* Fix content for install, sync, uninstallä

* test(docs): align first-contact contracts and stabilize module CLI tests

- docs/index: restore Why does it exist?, tagline, OpenSpec, canonical core CLI story
- Update init profile tests for solo-developer + install all (code-review, six bundles)
- Lean help test accepts uvx init hint; upgrade/core_compatibility tests match runtime
- Autouse fixture re-bootstraps CommandRegistry after category-group tests
- Rebase tasks conflict resolved; TDD_EVIDENCE + tasks for gates 7.1/7.2/12.1/12.2

Made-with: Cursor

* fix(tools): smart-test baseline and pre-commit single code-review run

- Run full suite when smart-test cache has no last_full_run; force+auto falls back to full when incremental is a no-op
- Pre-commit: invoke pre_commit_code_review.py once (no xargs split) so .specfact/code-review.json is not clobbered
- Tests and OpenSpec tasks for docs-new-user-onboarding

Made-with: Cursor

* test: fix CI backlog copy assertions and module install test isolation

- Align backlog not-installed tests with solo-developer init guidance (no <profile> placeholder)
- Autouse: reset CommandRegistry, register_builtin_commands, rebuild_root_app_from_registry so module install tests work after registry-only clears

Made-with: Cursor

* docs: README wow path + tests locking entrypoint with docs

- README leads with uvx init + code review run --scope full; pip install secondary
- Unit contract tests: README and docs/index.md share canonical uvx strings and order
- E2E: init --profile solo-developer in temp git repo; registry ready for step two with mock bundles

Made-with: Cursor

* feat(init): solo-developer includes code-review bundle and marketplace install

- Add specfact-code-review to canonical bundles and solo-developer preset
- Install marketplace module nold-ai/specfact-code-review via install_bundles_for_init
- Docs index: core CLI story and default starting point copy for parity tests
- CLI: missing-module hint references solo-developer profile
- smart_test_coverage: icontract requires use (self, test_level) for method contracts
- Re-sign init and module_registry manifests; tests and registry updates

Made-with: Cursor

* fix(tools): align _run_changed_only with tuple return and baseline full run

- Return (success, ran_any) from _run_changed_only; run full suite when no last_full_run
- run_smart_tests(auto, force): fall back to full tests when incremental ran nothing
- Fix wow e2e fixture typing (Iterator[None]) for basedpyright

Unblocks PR #477 CI: type-check, tests, lint job.

Made-with: Cursor

* chore(release): bump to 0.45.1 and update OpenSpec tasks status

- Sync version across pyproject.toml, setup.py, and __init__ modules
- Changelog: 0.45.1 entry for dependency profiles, smart-test baseline, CI, UX
- openspec: rolling status snapshot and task checkboxes for PR verification
- Includes prior branch work: init/profile, module registry, docs entry path, workflows

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* fix: code-review gate (Typer params), typer<0.24 vs semgrep, module upgrade tests (#479)

* fix: code-review gate (Typer params), typer<0.24 vs semgrep, module upgrade tests

- Split root/install Typer callbacks into merged param stubs (KISS param count).
- Patch typer.main via importlib; merge install param specs in module_registry.
- Cap typer<0.24 to stay compatible with semgrep click~=8.1.8.
- Invoke module_registry app directly in upgrade CLI tests (root app may lack module group).
- Refactors for first_run_selection, module_packages, registry tests, semgrep README.

Worktree: specfact-cli-worktrees/bugfix/code-review-cli-tests
Made-with: Cursor

* docs: use code import in examples (flat import removed from CLI)

Replace specfact [--flags] import from-code with specfact [--flags] code import
from-code so check-docs-commands matches the nested Typer path after removing
the flat import shim.

Made-with: Cursor

* Fix review findings

---------

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: restructure README for star conversion (#480)

* docs: restructure readme for star conversion

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: sync readme change tracking

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: relocate readme support artifacts

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: fix readme workflow snippet and pin demo capture

Co-authored-by: Dom <djm81@users.noreply.github.com>

* docs: address remaining readme review findings

Co-authored-by: Dom <djm81@users.noreply.github.com>

---------

Co-authored-by: Dom <djm81@users.noreply.github.com>

* archived implemented changes

* Archive and remove outdated changes

* Split and refactor change proposals between both repos

* Archive alignment change

* Add changes and github hierarchy scripts

* feat: add GitHub hierarchy cache sync (#492)

* feat: add github hierarchy cache sync

* Backport improvements from modules scripts

* Fix review findings

* Make github sync script executable

---------

Signed-off-by: Dom <39115308+djm81@users.noreply.github.com>
Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* [codex] Compact agent governance loading (#493)

* feat: compact agent governance loading

* docs: mark governance PR task complete

* docs: sync governance-03 github issue metadata

* fix: restore dev branch governance block

* Apply review findings

* docs: add sibling internal wiki context for OpenSpec design

Point AGENTS.md, Claude/Copilot/Cursor surfaces, and the OpenSpec rule at
docs/agent-rules/40-openspec-and-tdd.md to read-only wiki paths (hot.md,
graph.md, concepts) via absolute paths when specfact-cli-internal is present.
Update INDEX applicability notes and extend governance tests.

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Archived github hierarchy change

* Update rules for openspec archive

* Potential fix for pull request finding 'Unused local variable'

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>

* Add wiki update notes

* Archive governance-03 change, format markdown, add wiki instructions for update

* Fix review findings

* Fix type errors

* fix: safe VS Code settings merge and project artifact writes (#490) (#496)

* fix: safe merge for VS Code settings.json on init ide (profile-04)

- Add project_artifact_write.merge_vscode_settings_prompt_recommendations with fail-safe
  on invalid JSON / bad chat shape; --force backs up to .specfact/recovery/ then replaces.
- Route ide_setup create_vscode_settings through helper; thread force; catch errors for CLI exit.
- Lint gate: scripts/verify_safe_project_writes.py blocks json.load/dump in ide_setup.py.
- Tests, installation docs, 0.45.2 changelog and version pins.

OpenSpec: profile-04-safe-project-artifact-writes
Made-with: Cursor

* fix(profile-04): satisfy review gate, pin setuptools for semgrep

- Refactor project_artifact_write merge path (KISS); icontract predicates
- Deduplicate ide_setup prompt helpers; import from project_artifact_write
- verify_safe_project_writes: ast.walk, contracts, beartype
- Pin setuptools<82 for Semgrep pkg_resources chain
- Update TDD_EVIDENCE and tasks checklist

Made-with: Cursor

* ci: run safe-write verifier in PR orchestrator lint job

Match hatch run lint by invoking scripts/verify_safe_project_writes.py
after ruff/basedpyright/pylint. Use set -euo pipefail so the first lint
failure is not masked by later commands.

Made-with: Cursor

* fix(profile-04): address CodeRabbit review (docs, guard, contracts, tests)

- Wrap installation.md VS Code merge paragraph to <=120 chars per line
- tasks 4.7 + TDD_EVIDENCE: openspec validate --strict sign-off
- verify_safe_project_writes: detect from-json import and aliases
- settings_relative_nonblank: reject absolute paths and .. segments
- ide_setup: _handle_structured_json_document_error for duplicate handlers
- ProjectWriteMode docstring (reserved policy surface); backup stamp + collision loop
- Tests: malformed settings preserved on init ide exit; force+chat coercion; AST guard tests

Made-with: Cursor

* fix(profile-04): JSON5 settings, repo containment, review follow-ups

- merge_vscode_settings: resolve containment before mkdir/write; JSON5 load/dump
  (JSONC comments; trailing_commas=False for strict JSON output)
- ide_setup: empty prompts_by_source skips catalog fallback (_finalize allow_empty_fallback)
- verify_safe_project_writes: detect import json as js attribute calls
- contract_predicates: prompt_files_all_strings accepts list[Any] for mixed-type checks
- Tests: symlink escape, JSONC merge, empty export strip, import-json-as-js guard
- tasks.md / TDD_EVIDENCE: wrap lines to <=120 chars; CHANGELOG + json5 dep + setup.py sync

Made-with: Cursor

* docs(profile-04): tasks pre-flight + full pytest; narrow icontract ensure

- tasks 1.1: hatch env create then smart-test-status and contract-test-status
- tasks 4.3: add hatch test --cover -v to quality gates
- TDD_EVIDENCE: shorter module-signatures and report lines (<=120 cols)
- project_artifact_write: isinstance(result, Path) in @ensure postconditions

Made-with: Cursor

* fix: clear specfact code review on safe-write modules

- verify_safe_project_writes: flatten json binding helpers; stderr writes
  instead of print; inline Import/ImportFrom loops to drop duplicate-shape DRY
- project_artifact_write: _VscodeChatMergeContext dataclass (KISS param count);
  typed chat_body cast before .get for pyright

Made-with: Cursor

* docs(profile-04): record hatch test --cover -v in TDD_EVIDENCE

Align passing evidence with tasks.md 4.3 full-suite coverage gate.

Made-with: Cursor

* fix: reduce KISS blockers (bridge sync contexts, tools, partial adapters)

Refactors high-parameter call sites into dataclasses/context objects and splits hot spots (export devops pipeline, smart_test_coverage incremental run, suggest_frontmatter, crosshair summary loop).

API: BridgeSync.export_change_proposals_to_devops(adapter_type, ExportChangeProposalsOptions | None); LoggerSetup.create_logger(name, LoggerCreateOptions | None); run_crosshair(path, CrosshairRunOptions | None).

Full specfact code review --scope full still reports error-severity kiss/radon findings (remaining nesting/LOC and param counts in ADO, analyzers, generators, source_scanner, module_installer, bundle-mapper, etc.). Gate PASS requires follow-up.

Made-with: Cursor

* Fix review findings and sign modules

* fix(tests): register dynamic check_doc_frontmatter module; align _update_cache tests

- Insert check_doc_frontmatter into sys.modules before exec_module so
  dataclasses can resolve string annotations (fixes Docs Review / agent
  rules governance fixture).
- Call SmartCoverageManager._update_cache with _SmartCacheUpdate after
  signature refactor (fixes basedpyright reportCallIssue).

Made-with: Cursor

* fix(tests): align install_module mocks with InstallModuleOptions; register verify_bundle script

- Monkeypatch/patch fakes now accept (module_id, options=None) matching
  install_module(module_id, InstallModuleOptions(...)).
- Read install_root, trust_non_official, non_interactive, reinstall from
  InstallModuleOptions in CLI command tests.
- Dynamic load of verify-bundle-published registers sys.modules before
  exec_module (same dataclass annotation issue as check_doc_frontmatter).

Made-with: Cursor

---------

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* Fix review findings (#498)

Co-authored-by: Dominikus Nold <djm81@users.noreply.github.com>

* feat(openspec): add marketplace-06-ci-module-signing change proposal

Moves module signing from local interactive requirement to CI step
triggered by PR approval (pull_request_review). Eliminates local private
key dependency for non-interactive development on feature/dev branches.
Trust boundary remains at main.

Scope:
- NEW .github/workflows/sign-modules-on-approval.yml
- MODIFY scripts/pre-commit-smart-checks.sh (branch-aware policy)
- MODIFY .github/workflows/pr-orchestrator.yml (split verify by target)
- MODIFY .github/workflows/sign-modules.yml (main-only enforcement)

GitHub: #500
Parent Feature: #353 (Marketplace Module Distribution) → #194 (Architecture Epic)
Paired modules change: specfact-cli-modules#185

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

* chore(pre-commit): modular hooks + branch-aware module verify (#501)

* chore(pre-commit): modular hooks aligned with specfact-cli-modules

- Add scripts/pre-commit-quality-checks.sh (block1 stages + block2; all for manual/shim)
- Replace monolithic smart-checks with shim to quality-checks all
- .pre-commit-config: fail_fast, verify-module-signatures + check-version-sources,
  cli-block1-* hooks, cli-block2, doc frontmatter
- Match modules: hatch run lint when Python staged; scoped code review paths
- CLI extras: Markdown fix/lint, workflow actionlint (no packages/ bundle-import gate)
- Bump to 0.46.1; docs: README, CONTRIBUTING, code-review.md, agent-rules/70

Made-with: Cursor

* fix(pre-commit): branch-aware module verify hook (marketplace-06 policy)

- Add scripts/pre-commit-verify-modules.sh and git-branch-module-signature-flag.sh
- Point verify-module-signatures hook at wrapper (script); skip when no staged module paths
- pre-commit-quality-checks all: delegate module step to wrapper; safe-change allowlist
- Tests + CONTRIBUTING/CHANGELOG alignment

Made-with: Cursor

* fix(pre-commit): address review — portable quality checks and signature policy

- Emit require/omit from git-branch-module-signature-flag; pass --require-signature only on main
- Resolve repo root in pre-commit-smart-checks via git rev-parse for .git/hooks copies
- Harden pre-commit-quality-checks: ACMR staged paths, pipefail, no xargs -r, safe loops
- CHANGELOG/CONTRIBUTING: Added vs Changed; document verifier CLI (no --allow-unsigned)
- Tests: omit/require expectations, detached HEAD; shim asserts repo-root exec

Made-with: Cursor

* docs: align signing and verification docs with verifier CLI

- Document checksum-only vs --require-signature; clarify --allow-unsigned is sign-modules.py only
- Add pre-commit and CI branch policy to module-security, signing guide, publishing, agent gates
- Refresh marketplace-06 OpenSpec proposal/design/tasks/spec delta; openspec validate --strict OK
- CHANGELOG: note d…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

architecture Architecture and design changes bug Something isn't working dependencies Dependency resolution and management enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Change] Safe project artifact writes for init and IDE setup bug: specfact init overwrites existing .vscode/settings.json completely

1 participant