Skip to content

Promote dev to main: requirements runtime module#328

Merged
djm81 merged 27 commits into
mainfrom
dev
Jul 8, 2026
Merged

Promote dev to main: requirements runtime module#328
djm81 merged 27 commits into
mainfrom
dev

Conversation

@djm81

@djm81 djm81 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Promotes the current dev branch to main after merging the requirements runtime module work.

Included changes:

Highlights:

  • Adds official nold-ai/specfact-requirements module package.
  • Adds grouped requirements runtime commands for import, validate, list, and coverage.
  • Updates OpenSpec, docs, command references, command validation wiring, tests, registry artifacts, and signatures.
  • Includes the CI fix that lazy-loads paired core requirements helpers so command discovery works before runtime use.

Validation

From #326 before merge:

  • openspec validate requirements-02-module-commands --strict
  • hatch run check-command-overview
  • hatch run check-command-contract
  • hatch run validate-prompt-commands
  • hatch run python scripts/check-docs-commands.py
  • targeted requirements tests: 7 passed
  • hatch run type-check
  • hatch run lint
  • module signature verification: Verified 7 module manifest(s).
  • SpecFact code review: PASS, score 120, no findings

Notes

This is a branch promotion PR only; no local files were changed while creating it.

@strix-security

strix-security Bot commented Jul 8, 2026

Copy link
Copy Markdown

Strix Security Review

No security issues found.

Updated for e87e2d3.


Reviewed by Strix
Re-run review · Configure security review settings

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dbc4b8f0-47f1-43e2-876b-c896659b92e1

📥 Commits

Reviewing files that changed from the base of the PR and between 5d2ddd9 and a0182a9.

⛔ Files ignored due to path filters (3)
  • registry/modules/specfact-requirements-0.1.2.tar.gz is excluded by !**/*.gz
  • registry/modules/specfact-requirements-0.1.4.tar.gz is excluded by !**/*.gz
  • registry/modules/specfact-requirements-0.1.5.tar.gz is excluded by !**/*.gz
📒 Files selected for processing (14)
  • openspec/changes/requirements-02-module-commands/CHANGE_VALIDATION.md
  • openspec/changes/requirements-02-module-commands/TDD_EVIDENCE.md
  • openspec/changes/requirements-02-module-commands/specs/backlog-adapter/spec.md
  • packages/specfact-requirements/module-package.yaml
  • packages/specfact-requirements/src/specfact_requirements/requirements/commands.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py
  • registry/index.json
  • registry/modules/specfact-requirements-0.1.2.tar.gz.sha256
  • registry/modules/specfact-requirements-0.1.4.tar.gz.sha256
  • registry/modules/specfact-requirements-0.1.5.tar.gz.sha256
  • registry/signatures/specfact-requirements-0.1.2.tar.sig
  • registry/signatures/specfact-requirements-0.1.4.tar.sig
  • registry/signatures/specfact-requirements-0.1.5.tar.sig
  • tests/unit/specfact_requirements/test_requirements_runtime.py
📝 Walkthrough

Walkthrough

Adds a new specfact-requirements bundle with specfact requirements import|validate|list|coverage commands, runtime normalization and bundle persistence, updated docs and generated command references, registry/signing artifacts, and test/tooling wiring.

Changes

Requirements bundle implementation

Layer / File(s) Summary
OpenSpec scope and contracts
openspec/changes/requirements-02-module-commands/*
Rewrites the proposal, design, tasks, validation record, and specs to define module-owned runtime commands, requirements.inputs storage, profile-aware validation, and coverage reporting.
Package, runtime, and commands
packages/specfact-requirements/..., packages/specfact-requirements/module-package.yaml
Adds the module package, exports, runtime helpers, and Typer commands for importing, validating, listing, and inspecting requirement coverage.
Validation wiring and test coverage
pyproject.toml, scripts/*, tests/*
Registers the new module across import/command/docs validation scripts and adds unit and integration coverage for the new CLI and runtime behavior.
Docs, generated references, registry, and signing artifacts
docs/*, llms.txt, registry/*
Adds bundle docs and navigation, generated command references, registry metadata, checksum/signature artifacts, and overview routing for the new commands.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

Possibly related PRs

Suggested labels: module, marketplace

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers summary and validation, but misses most required template sections, refs, scope checklist, bundle impact, and CI/signature details. Rewrite it to match the template: add refs, scope checkboxes, bundle version impacts, required gate results, signature/branch-protection notes, docs/pages, and checklist items.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects a branch-promotion PR for the requirements runtime module and matches the main change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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

@djm81 djm81 self-assigned this Jul 8, 2026
@djm81 djm81 added documentation Improvements or additions to documentation enhancement New feature or request dependencies Pull requests that update a dependency file labels Jul 8, 2026
@djm81 djm81 moved this from Todo to In Progress in SpecFact CLI Jul 8, 2026
@djm81 djm81 linked an issue Jul 8, 2026 that may be closed by this pull request

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

Copy link
Copy Markdown

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: e87e2d3386

ℹ️ 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 packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py Outdated
Comment thread packages/specfact-requirements/src/specfact_requirements/requirements/commands.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py (1)

21-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded profile allowlist risks drifting from core.

KNOWN_REQUIREMENT_CONTEXT_PROFILES duplicates the canonical profile set that presumably lives in specfact_cli.requirements.context. Since this module intentionally avoids eager-importing that core module (for CI-safe command discovery), any new/renamed profile added to core later will silently be rejected here until this list is manually updated.

As per path instructions, "Flag breaking assumptions about registry loading, lazy imports, and environment/mode behavior," and as per coding guidelines, "Preserve the clean-code compliance gate and its category references (naming, kiss, yagni, dry, and solid)" — this duplication is a dry-category risk worth tracking (e.g., a contract test asserting parity with core's profile enum).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py`
around lines 21 - 32, The hardcoded KNOWN_REQUIREMENT_CONTEXT_PROFILES allowlist
in runtime.py can drift from the canonical profile registry in
specfact_cli.requirements.context. Update the validation approach so runtime.py
does not maintain a separate profile list; instead, add a parity/contract check
against the core profile source (or a single shared constant) while preserving
the lazy-import behavior. Use KNOWN_REQUIREMENT_CONTEXT_PROFILES and the
requirement context loading path as the key symbols to refactor and keep future
profile additions/renames automatically aligned.

Sources: Coding guidelines, Path instructions

tests/unit/specfact_requirements/test_requirements_runtime.py (1)

1-90: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing coverage for the "paired core module unavailable" path.

Good coverage of the happy path, but there's no test that import_requirements_file_to_bundle/validate_requirements_bundle/etc. raise RequirementsCoreUnavailableError cleanly when specfact_cli.requirements.context or specfact_cli.models.requirements can't be imported (the scenario the lazy-load fix targets).

Want me to draft a test that monkeypatches _load_requirements_module (or blocks the import like the integration test does) to assert the error surfaces correctly?
As per path instructions, "Ensure changes to adapters or bridges have targeted coverage."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/specfact_requirements/test_requirements_runtime.py` around lines 1
- 90, Add a targeted test for the lazy-load failure path in the requirements
runtime helpers: cover `import_requirements_file_to_bundle`,
`validate_requirements_bundle`, and any shared loader path so they raise
`RequirementsCoreUnavailableError` when `specfact_cli.requirements.context` or
`specfact_cli.models.requirements` cannot be imported. Use the existing
`test_requirements_runtime.py` setup and either monkeypatch
`_load_requirements_module` or block the import in the same way as the
integration test, then assert the error surfaces cleanly from the public
functions.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openspec/changes/requirements-02-module-commands/CHANGE_VALIDATION.md`:
- Line 59: The validation artifact in CHANGE_VALIDATION.md contains a
machine-specific absolute public key path, which should be removed from the
checked-in evidence. Update the command under the validation report to use a
portable placeholder or repo-relative reference instead of the /Users/dom/...
path, keeping the verify-modules-signature command readable and reproducible.
Use the existing command entry and the referenced module-signing-public.pem path
as the target spot to redact.

In
`@openspec/changes/requirements-02-module-commands/specs/backlog-adapter/spec.md`:
- Around line 4-20: Update the scenario title in backlog-adapter spec so it
matches the import/normalization flow described in the body; the current title
for the acceptance-criteria scenario still uses “extraction,” which conflicts
with the requirements import workflow. Adjust the wording in the scenario header
within the backlog-adapter spec to align with the rest of the document and keep
the scenario text about adapter source fields, normalization, and item identity
unchanged.

In `@openspec/changes/requirements-02-module-commands/TDD_EVIDENCE.md`:
- Line 34: Redact the machine-specific absolute key path in the TDD evidence
entry so it no longer exposes a local /Users/... location and can be replayed
elsewhere. Update the logged `hatch run verify-modules-signature` command in
`TDD_EVIDENCE.md` to use a portable placeholder or relative path for the
`--public-key-file` argument, matching the same redaction approach used
elsewhere in the evidence file.

In
`@packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py`:
- Around line 86-90: The sidecar write in _write_requirements_sidecar is
non-atomic, unlike save_project_bundle, so update it to use the same atomic
write pattern when persisting requirements.inputs.yaml. Locate the helper by its
name and replace the direct write_text call with an atomic temp-file-and-rename
flow (or reuse the existing bundle atomic writer path in save_project_bundle),
so a crash during write cannot leave a partially written sidecar.

---

Nitpick comments:
In
`@packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py`:
- Around line 21-32: The hardcoded KNOWN_REQUIREMENT_CONTEXT_PROFILES allowlist
in runtime.py can drift from the canonical profile registry in
specfact_cli.requirements.context. Update the validation approach so runtime.py
does not maintain a separate profile list; instead, add a parity/contract check
against the core profile source (or a single shared constant) while preserving
the lazy-import behavior. Use KNOWN_REQUIREMENT_CONTEXT_PROFILES and the
requirement context loading path as the key symbols to refactor and keep future
profile additions/renames automatically aligned.

In `@tests/unit/specfact_requirements/test_requirements_runtime.py`:
- Around line 1-90: Add a targeted test for the lazy-load failure path in the
requirements runtime helpers: cover `import_requirements_file_to_bundle`,
`validate_requirements_bundle`, and any shared loader path so they raise
`RequirementsCoreUnavailableError` when `specfact_cli.requirements.context` or
`specfact_cli.models.requirements` cannot be imported. Use the existing
`test_requirements_runtime.py` setup and either monkeypatch
`_load_requirements_module` or block the import in the same way as the
integration test, then assert the error surfaces cleanly from the public
functions.
🪄 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: CHILL

Plan: Pro

Run ID: 8f9926ff-7831-488b-9934-625436f3c7e4

📥 Commits

Reviewing files that changed from the base of the PR and between ed32331 and e87e2d3.

⛔ Files ignored due to path filters (1)
  • registry/modules/specfact-requirements-0.1.1.tar.gz is excluded by !**/*.gz
📒 Files selected for processing (33)
  • docs/_data/nav.yml
  • docs/bundles/requirements/overview.md
  • docs/index.md
  • docs/reference/commands.generated.json
  • docs/reference/commands.generated.md
  • llms.txt
  • openspec/changes/requirements-02-module-commands/CHANGE_VALIDATION.md
  • openspec/changes/requirements-02-module-commands/TDD_EVIDENCE.md
  • openspec/changes/requirements-02-module-commands/design.md
  • openspec/changes/requirements-02-module-commands/proposal.md
  • openspec/changes/requirements-02-module-commands/specs/backlog-adapter/spec.md
  • openspec/changes/requirements-02-module-commands/specs/module-io-contract/spec.md
  • openspec/changes/requirements-02-module-commands/specs/requirements-module/spec.md
  • openspec/changes/requirements-02-module-commands/tasks.md
  • packages/specfact-requirements/module-package.yaml
  • packages/specfact-requirements/src/specfact_requirements/__init__.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/__init__.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/app.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/commands.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py
  • pyproject.toml
  • registry/index.json
  • registry/modules/specfact-requirements-0.1.1.tar.gz.sha256
  • registry/signatures/specfact-requirements-0.1.1.tar.sig
  • scripts/check-bundle-imports.py
  • scripts/check-command-contract.py
  • scripts/check-docs-commands.py
  • scripts/check-prompt-commands.py
  • scripts/generate-command-overview.py
  • tests/conftest.py
  • tests/integration/specfact_requirements/test_command_apps.py
  • tests/unit/docs/test_bundle_overview_cli_examples.py
  • tests/unit/specfact_requirements/test_requirements_runtime.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • nold-ai/specfact-cli (manual) → reviewed against branch dev instead of the default branch
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: quality (3.13)
  • GitHub Check: quality (3.12)
  • GitHub Check: quality (3.11)
⚠️ CI failures not shown inline (3)

GitHub Actions: Module Signature Hardening / 2_Verify Module Signatures.txt: Promote dev to main: requirements runtime module

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mif [ -z "${SPECFACT_MODULE_PRIVATE_SIGN_KEY}" ]; then�[0m
 �[36;1m  echo "::error::Missing SPECFACT_MODULE_PRIVATE_SIGN_KEY. Configure the secret so same-repo PRs can auto-sign module manifests."�[0m

GitHub Actions: Module Signature Hardening / Verify Module Signatures: Promote dev to main: requirements runtime module

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mBASE_REF=""�[0m
 �[36;1mif [ "pull_request" = "pull_request" ]; then�[0m
 �[36;1m  BASE_REF="origin/main"�[0m
 �[36;1melif [ "pull_request" = "workflow_dispatch" ]; then�[0m
 �[36;1m  BASE_REF="origin/"�[0m
 �[36;1mfi�[0m
 �[36;1mif [ -z "$BASE_REF" ]; then�[0m
 �[36;1m  echo "::error::Missing comparison base for module verification."�[0m

GitHub Actions: Module Signature Hardening / Verify Module Signatures: Promote dev to main: requirements runtime module

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mif [ -z "${SPECFACT_MODULE_PRIVATE_SIGN_KEY}" ]; then�[0m
 �[36;1m  echo "::error::Missing SPECFACT_MODULE_PRIVATE_SIGN_KEY. Configure the secret so same-repo PRs can auto-sign module manifests."�[0m
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,ts,tsx,jsx,py,java,cs,go,rb,php,cpp,c,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Preserve the clean-code compliance gate and its category references (naming, kiss, yagni, dry, and solid)

Files:

  • packages/specfact-requirements/src/specfact_requirements/__init__.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/__init__.py
  • scripts/check-prompt-commands.py
  • scripts/check-docs-commands.py
  • tests/conftest.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/app.py
  • tests/unit/specfact_requirements/test_requirements_runtime.py
  • tests/integration/specfact_requirements/test_command_apps.py
  • tests/unit/docs/test_bundle_overview_cli_examples.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/commands.py
  • scripts/generate-command-overview.py
  • scripts/check-bundle-imports.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py
  • scripts/check-command-contract.py
packages/**/src/**/*.py

⚙️ CodeRabbit configuration file

packages/**/src/**/*.py: Focus on adapter and bridge patterns: imports from specfact_cli (models, runtime, validators),
Typer/Rich command surfaces, and clear boundaries so core upgrades do not silently break bundles.
Flag breaking assumptions about registry loading, lazy imports, and environment/mode behavior.

Files:

  • packages/specfact-requirements/src/specfact_requirements/__init__.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/__init__.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/app.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/commands.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py
openspec/**/*.md

⚙️ CodeRabbit configuration file

openspec/**/*.md: Specification truth: proposal/tasks/spec deltas vs. bundle behavior, CHANGE_ORDER, and
drift vs. shipped modules or docs.

Files:

  • openspec/changes/requirements-02-module-commands/TDD_EVIDENCE.md
  • openspec/changes/requirements-02-module-commands/specs/requirements-module/spec.md
  • openspec/changes/requirements-02-module-commands/specs/module-io-contract/spec.md
  • openspec/changes/requirements-02-module-commands/specs/backlog-adapter/spec.md
  • openspec/changes/requirements-02-module-commands/design.md
  • openspec/changes/requirements-02-module-commands/proposal.md
  • openspec/changes/requirements-02-module-commands/CHANGE_VALIDATION.md
  • openspec/changes/requirements-02-module-commands/tasks.md
registry/**

⚙️ CodeRabbit configuration file

registry/**: Registry and index consistency: bundle listings, version pins, and compatibility with
published module artifacts.

Files:

  • registry/modules/specfact-requirements-0.1.1.tar.gz.sha256
  • registry/signatures/specfact-requirements-0.1.1.tar.sig
  • registry/index.json
scripts/**/*.py

⚙️ CodeRabbit configuration file

scripts/**/*.py: Deterministic tooling: signing, publishing, docs generation; subprocess and path safety.

Files:

  • scripts/check-prompt-commands.py
  • scripts/check-docs-commands.py
  • scripts/generate-command-overview.py
  • scripts/check-bundle-imports.py
  • scripts/check-command-contract.py
packages/**/module-package.yaml

⚙️ CodeRabbit configuration file

packages/**/module-package.yaml: Validate metadata: name, version, commands, dependencies, and parity with packaged src.
Call out semver and signing implications when manifests or payloads change.

Files:

  • packages/specfact-requirements/module-package.yaml
docs/**/*.md

⚙️ CodeRabbit configuration file

docs/**/*.md: User-facing and cross-site accuracy: Jekyll front matter, links per documentation-url-contract,
CLI examples matching bundled commands.

Files:

  • docs/reference/commands.generated.md
  • docs/bundles/requirements/overview.md
  • docs/index.md
tests/**/*.py

⚙️ CodeRabbit configuration file

tests/**/*.py: Contract-first and integration tests: migration suites, bundle validation, and flakiness.
Ensure changes to adapters or bridges have targeted coverage.

Files:

  • tests/conftest.py
  • tests/unit/specfact_requirements/test_requirements_runtime.py
  • tests/integration/specfact_requirements/test_command_apps.py
  • tests/unit/docs/test_bundle_overview_cli_examples.py
🧠 Learnings (1)
📚 Learning: 2026-04-02T21:49:07.435Z
Learnt from: djm81
Repo: nold-ai/specfact-cli-modules PR: 136
File: registry/modules/specfact-spec-0.40.17.tar.gz.sha256:1-1
Timestamp: 2026-04-02T21:49:07.435Z
Learning: In nold-ai/specfact-cli-modules, module tarball signature files under registry/signatures/*.tar.sig are produced by the publish-modules GitHub Actions runner during the publish workflow (not committed to the branch). During PR pre-merge review, do not flag missing *.tar.sig files as blockers; treat signatures as publish-time artifacts.

Applied to files:

  • registry/signatures/specfact-requirements-0.1.1.tar.sig
🪛 ast-grep (0.44.1)
tests/unit/specfact_requirements/test_requirements_runtime.py

[info] 45-52: use jsonify instead of json.dumps for JSON output
Context: json.dumps(
{
"requirements": [
_requirement_record(),
{"requirement_id": "REQ-BROKEN", "schema_version": "1", "title": "Missing source refs"},
]
}
)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 67-67: use jsonify instead of json.dumps for JSON output
Context: json.dumps([_requirement_record()])
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 79-79: use jsonify instead of json.dumps for JSON output
Context: json.dumps([_requirement_record("REQ-COVERED", with_evidence=True)])
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

tests/integration/specfact_requirements/test_command_apps.py

[info] 31-45: use jsonify instead of json.dumps for JSON output
Context: json.dumps(
[
{
"schema_version": "1",
"requirement_id": "REQ-CLI",
"title": "CLI imports requirement context",
"sources": [
{
"source_type": "issue",
"locator": "https://github.com//issues/165",
}
],
}
]
)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[error] 78-78: Command coming from incoming request
Context: subprocess.run([sys.executable, "-c", code], capture_output=True, check=False, text=True, env=env)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)

packages/specfact-requirements/src/specfact_requirements/requirements/commands.py

[info] 49-49: use jsonify instead of json.dumps for JSON output
Context: json.dumps(payload, indent=2, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 LanguageTool
docs/bundles/requirements/overview.md

[style] ~90-~90: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...alidation findings and coverage gaps. - It does not expose authoring templates. - ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~91-~91: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... does not expose authoring templates. - It does not perform bidirectional backlog ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

openspec/changes/requirements-02-module-commands/proposal.md

[style] ~32-~32: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...nifest and command overview wiring. - NEW: Command runtime preserves bounded co...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🔀 Multi-repo context nold-ai/specfact-cli

Linked repositories findings

nold-ai/specfact-cli (inspected at refs/heads/dev)

  • docs/architecture/implementation-status.md:26 and docs/architecture/overview.md:19 say older flat command families like specfact requirements ... are not canonical delivery targets. That conflicts with the new bundle docs/CLI surface being added in the PR and is worth checking for doc-model alignment. [::nold-ai/specfact-cli::]

  • openspec/parking-lot/ai-integration-04-intent-skills/design.md:18,32,49 and openspec/parking-lot/ai-integration-04-intent-skills/specs/agent-skill-intent-workflow/spec.md:17,25,30 still reference specfact requirements capture, specfact requirements validate, and specfact requirements trace, plus a prerequisite check for specfact requirements --help. The PR’s new command set is import/validate/list/coverage, so these references look stale or mismatched. [::nold-ai/specfact-cli::]

  • openspec/changes/requirements-02-module-commands/specs/requirements-module/spec.md:9,16,24 also still describes the older extract/author/validate/list shape for specfact requirements ..., which does not match the PR’s new runtime command names. [::nold-ai/specfact-cli::]

🔇 Additional comments (35)
openspec/changes/requirements-02-module-commands/proposal.md (1)

1-78: LGTM!

Also applies to: 87-89

openspec/changes/requirements-02-module-commands/design.md (1)

3-22: LGTM!

Also applies to: 32-66

openspec/changes/requirements-02-module-commands/specs/requirements-module/spec.md (1)

3-35: LGTM!

openspec/changes/requirements-02-module-commands/specs/module-io-contract/spec.md (1)

4-20: LGTM!

openspec/changes/requirements-02-module-commands/tasks.md (1)

5-36: LGTM!

docs/_data/nav.yml (1)

58-62: LGTM!

docs/bundles/requirements/overview.md (1)

26-36: 🗄️ Data Integrity & Integration

Verify command-surface parity with specfact-cli architecture docs and OpenSpec specs.

This page documents specfact requirements import|validate|list|coverage as the bundle's canonical command surface. Cross-repo findings show nold-ai/specfact-cli's docs/architecture/implementation-status.md/overview.md state that flat command families like specfact requirements ... are not canonical delivery targets, and OpenSpec parking-lot design/spec docs plus openspec/changes/requirements-02-module-commands/specs/requirements-module/spec.md still describe a different shape (capture/trace/extract/author instead of import/coverage). Confirm this page's command names/table are the source of truth going forward and that the stale cross-repo references will be updated to avoid conflicting guidance for users and agents.

Also applies to: 68-75

docs/index.md (1)

72-72: LGTM!

registry/signatures/specfact-requirements-0.1.1.tar.sig (1)

1-1: LGTM!

Based on learnings, module tarball signature files under registry/signatures/*.tar.sig are produced by the publish-modules CI workflow at publish time, so this artifact's presence and content are expected and not something to hand-verify in review.

Source: Learnings

tests/unit/docs/test_bundle_overview_cli_examples.py (1)

58-77: LGTM!

Also applies to: 132-132

docs/reference/commands.generated.json (1)

1698-1790: LGTM!

docs/reference/commands.generated.md (1)

96-100: LGTM!

llms.txt (1)

100-104: LGTM!

registry/index.json (1)

94-108: 🗄️ Data Integrity & Integration

Verify core_compatibility was intentionally omitted.

Every sibling registry entry publishes a core version range, but this new module record does not. If downstream consumers use that field for compatibility filtering, the bundle will be treated inconsistently; the current validator also won’t catch the omission.

registry/modules/specfact-requirements-0.1.1.tar.gz.sha256 (1)

1-1: LGTM!

packages/specfact-requirements/src/specfact_requirements/__init__.py (1)

1-6: LGTM!

packages/specfact-requirements/src/specfact_requirements/requirements/__init__.py (1)

1-7: LGTM!

packages/specfact-requirements/src/specfact_requirements/requirements/app.py (1)

1-7: LGTM!

packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py (1)

1-20: LGTM!

Also applies to: 39-65, 92-131, 146-188

packages/specfact-requirements/src/specfact_requirements/requirements/commands.py (3)

1-55: LGTM!

Also applies to: 86-122


6-6: 🎯 Functional Correctness

No action needed for enum.StrEnum. Python >=3.11 is declared in pyproject.toml, so this import is supported here.


56-139: 🩺 Stability & Availability

No separate catch needed here — the root CLI already wraps mounted Typer apps in a global except Exception handler and prints a clean error with a nonzero exit code, so RequirementsCoreUnavailableError does not reach users as a raw traceback when invoked through specfact_cli.cli.

			> Likely an incorrect or invalid review comment.
tests/integration/specfact_requirements/test_command_apps.py (2)

113-121: 🎯 Functional Correctness

This locked-in command surface conflicts with linked OpenSpec spec deltas.

This test correctly asserts the shipped surface is import/validate/list/coverage with no author command. However, per linked-repository findings, openspec/changes/requirements-02-module-commands/specs/requirements-module/spec.md still describes an extract/author/validate/list shape, and other OpenSpec parking-lot docs still reference specfact requirements capture/trace. That's a real docs/spec-vs-implementation drift for this module's public contract.

Please confirm the OpenSpec spec deltas for this change (layer 1 in the stack) have been updated to match the shipped import/validate/list/coverage surface before this promotes to main, since stale specs can mislead downstream consumers/agents relying on openspec/changes/requirements-02-module-commands/specs/requirements-module/spec.md.

Source: Linked repositories


1-112: LGTM!

packages/specfact-requirements/module-package.yaml (1)

9-10: 🗄️ Data Integrity & Integration

nold-ai/specfact-project is already listed in registry/index.json.

			> Likely an incorrect or invalid review comment.
scripts/check-command-contract.py (2)

214-216: 🎯 Functional Correctness

Same decorator-order note as scripts/check-bundle-imports.py.

Same @beartype above @ensure ordering here; see the note on scripts/check-bundle-imports.py (lines 174-176) for the recommended-order concern from beartype's docs.


16-17: LGTM!

Also applies to: 23-31, 94-101, 135-163, 214-215, 234-238

scripts/generate-command-overview.py (2)

259-261: 🎯 Functional Correctness

Same decorator-order note as scripts/check-bundle-imports.py.

Same @beartype-outermost/@ensure-innermost stacking as flagged on scripts/check-bundle-imports.py (lines 174-176); this is the third recurrence of the pattern in this PR.


17-18: LGTM!

Also applies to: 27-40, 163-164, 208-220, 233-256

pyproject.toml (1)

92-101: LGTM!

Also applies to: 130-139, 281-289

tests/conftest.py (1)

24-31: LGTM!

scripts/check-bundle-imports.py (2)

18-25: LGTM!

Also applies to: 62-69, 120-192


174-176: 🎯 Functional Correctness

Verify @beartype/@ensure decorator order on main().

@beartype is applied outermost here (and in check-command-contract.py's main/generate-command-overview.py's build_records/_check/main), wrapping the icontract.ensure-decorated function rather than the raw function. Beartype's own docs state for callable mode "@beartype should usually be listed last" (i.e., closest to the function). icontract's ensure does call functools.update_wrapper, so signature/annotations are likely preserved and this may work fine in practice — but it's worth confirming this order doesn't cause beartype to type-check a synthesized wrapper signature instead of the intended one, given the pattern repeats across multiple new decorators in this PR.

🐻 Suggested order per beartype's own guidance
-@beartype
-@ensure(lambda result: result in {0, 1})
+@ensure(lambda result: result in {0, 1})
+@beartype
 def main() -> int:
scripts/check-docs-commands.py (1)

76-89: LGTM!

scripts/check-prompt-commands.py (1)

35-48: LGTM!

Comment thread openspec/changes/requirements-02-module-commands/CHANGE_VALIDATION.md Outdated
Comment thread openspec/changes/requirements-02-module-commands/TDD_EVIDENCE.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/unit/specfact_requirements/test_requirements_runtime.py (1)

66-88: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider parametrizing the duplicate profile-alias test.

Lines 78-88 duplicate the body of the test at lines 66-76 (test_validate_requirements_bundle_uses_profile_aware_core_validation) with only the profile string differing. A @pytest.mark.parametrize over ("enterprise", "enterprise-full-stack") would consolidate this without losing coverage.
[optional_and_nitpick]

♻️ Proposed consolidation
-def test_validate_requirements_bundle_uses_profile_aware_core_validation(tmp_path: Path) -> None:
-    source = tmp_path / "requirements.json"
-    source.write_text(json.dumps([_requirement_record()]), encoding="utf-8")
-    bundle_dir = _bundle_dir(tmp_path)
-    import_requirements_file_to_bundle(source, bundle_dir)
-
-    report = validate_requirements_bundle(bundle_dir, profile="enterprise")
-
-    assert report.status == "failed"
-    assert report.violations[0]["location"] == "requirements.inputs[REQ-165].evidence_links"
-
-
-def test_validate_requirements_bundle_accepts_hyphenated_profile_alias(tmp_path: Path) -> None:
-    source = tmp_path / "requirements.json"
-    source.write_text(json.dumps([_requirement_record()]), encoding="utf-8")
-    bundle_dir = _bundle_dir(tmp_path)
-    import_requirements_file_to_bundle(source, bundle_dir)
-
-    report = validate_requirements_bundle(bundle_dir, profile="enterprise-full-stack")
-
-    assert report.status == "failed"
-    assert report.violations[0]["location"] == "requirements.inputs[REQ-165].evidence_links"
+@pytest.mark.parametrize("profile", ["enterprise", "enterprise-full-stack"])
+def test_validate_requirements_bundle_uses_profile_aware_core_validation(tmp_path: Path, profile: str) -> None:
+    source = tmp_path / "requirements.json"
+    source.write_text(json.dumps([_requirement_record()]), encoding="utf-8")
+    bundle_dir = _bundle_dir(tmp_path)
+    import_requirements_file_to_bundle(source, bundle_dir)
+
+    report = validate_requirements_bundle(bundle_dir, profile=profile)
+
+    assert report.status == "failed"
+    assert report.violations[0]["location"] == "requirements.inputs[REQ-165].evidence_links"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/specfact_requirements/test_requirements_runtime.py` around lines
66 - 88, Consolidate the two near-identical bundle validation tests into a
single parametrized pytest case by applying `@pytest.mark.parametrize` over the
profile argument with both "enterprise" and "enterprise-full-stack". Keep the
shared setup and assertions in the existing
test_validate_requirements_bundle_uses_profile_aware_core_validation path so
coverage stays the same while removing the duplicate test body.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/unit/specfact_requirements/test_requirements_runtime.py`:
- Around line 66-88: Consolidate the two near-identical bundle validation tests
into a single parametrized pytest case by applying `@pytest.mark.parametrize` over
the profile argument with both "enterprise" and "enterprise-full-stack". Keep
the shared setup and assertions in the existing
test_validate_requirements_bundle_uses_profile_aware_core_validation path so
coverage stays the same while removing the duplicate test body.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 26807f86-b85e-4f7f-964e-0b50bebc5d14

📥 Commits

Reviewing files that changed from the base of the PR and between e87e2d3 and 5d2ddd9.

📒 Files selected for processing (5)
  • packages/specfact-requirements/module-package.yaml
  • packages/specfact-requirements/src/specfact_requirements/requirements/commands.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py
  • tests/integration/specfact_requirements/test_command_apps.py
  • tests/unit/specfact_requirements/test_requirements_runtime.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • nold-ai/specfact-cli (manual) → reviewed against open PR #634 dev instead of the default branch
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/specfact-requirements/module-package.yaml
  • packages/specfact-requirements/src/specfact_requirements/requirements/commands.py
  • tests/integration/specfact_requirements/test_command_apps.py
  • packages/specfact-requirements/src/specfact_requirements/requirements/runtime.py
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: quality (3.13)
  • GitHub Check: quality (3.12)
  • GitHub Check: quality (3.11)
⚠️ CI failures not shown inline (3)

GitHub Actions: Module Signature Hardening / Verify Module Signatures: Promote dev to main: requirements runtime module

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mif [ -z "${SPECFACT_MODULE_PRIVATE_SIGN_KEY}" ]; then�[0m
 �[36;1m  echo "::error::Missing SPECFACT_MODULE_PRIVATE_SIGN_KEY. Configure the secret so same-repo PRs can auto-sign module manifests."�[0m

GitHub Actions: Module Signature Hardening / 2_Verify Module Signatures.txt: Promote dev to main: requirements runtime module

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mif [ -z "${SPECFACT_MODULE_PRIVATE_SIGN_KEY}" ]; then�[0m
 �[36;1m  echo "::error::Missing SPECFACT_MODULE_PRIVATE_SIGN_KEY. Configure the secret so same-repo PRs can auto-sign module manifests."�[0m

GitHub Actions: pr-orchestrator / 1_verify-module-signatures.txt: Promote dev to main: requirements runtime module

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mif [ -z "${SPECFACT_MODULE_PUBLIC_SIGN_KEY:-}" ] && [ -z "${SPECFACT_MODULE_SIGNING_PUBLIC_KEY_PEM:-}" ]; then�[0m
 �[36;1m  echo "warning: no public signing key secret set; verifier must resolve key from repo/default path"�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mVERIFY_CMD=(python scripts/verify-modules-signature.py --payload-from-filesystem --enforce-version-bump)�[0m
 �[36;1m�[0m
 �[36;1mif [ "pull_request" = "pull_request" ]; then�[0m
 �[36;1m  BASE_REF="origin/main"�[0m
 �[36;1m  TARGET_BRANCH="main"�[0m
 �[36;1m  VERIFY_CMD+=(--version-check-base "$BASE_REF")�[0m
 �[36;1m  if [ "$TARGET_BRANCH" = "main" ]; then�[0m
 �[36;1m    VERIFY_CMD+=(--require-signature)�[0m
 �[36;1m  fi�[0m
 �[36;1melse�[0m
 �[36;1m  # Push/workflow_dispatch: compare against the ref tip before this push (not HEAD~1).�[0m
 �[36;1m  # Merge commits and signing-only updates keep the same semver; HEAD~1 is the wrong�[0m
 �[36;1m  # parent for three-way merges and falsely fails --enforce-version-bump.�[0m
 �[36;1m  BEFORE="2859604993274fc01e5280c108fcac6cfce5e115"�[0m
 �[36;1m  if [ -z "$BEFORE" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then�[0m
 �[36;1m    BEFORE="HEAD~1"�[0m
 �[36;1m  fi�[0m
 �[36;1m  VERIFY_CMD+=(--version-check-base "$BEFORE")�[0m
 �[36;1m  if [ "328/merge" = "main" ]; then�[0m
 �[36;1m    VERIFY_CMD+=(--require-signature)�[0m
 �[36;1m  fi�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1m"${VERIFY_CMD[@]}"�[0m
 shell: /usr/bin/bash -e {0}
 env:
   SPECFACT_MODULE_PUBLIC_SIGN_KEY: ***
   SPECFACT_MODULE_SIGNING_PUBLIC_KEY_PEM:
   pythonLocation: /opt/hostedtoolcache/Python/3.12.13/x64
   PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.12.13/x64/lib/pkgconfig
   Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.13/x64
   Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.13/x64
   Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.13/x64
   LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.12...
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,ts,tsx,jsx,py,java,cs,go,rb,php,cpp,c,h}

📄 CodeRabbit inference engine (CLAUDE.md)

Preserve the clean-code compliance gate and its category references (naming, kiss, yagni, dry, and solid)

Files:

  • tests/unit/specfact_requirements/test_requirements_runtime.py
tests/**/*.py

⚙️ CodeRabbit configuration file

tests/**/*.py: Contract-first and integration tests: migration suites, bundle validation, and flakiness.
Ensure changes to adapters or bridges have targeted coverage.

Files:

  • tests/unit/specfact_requirements/test_requirements_runtime.py
🪛 ast-grep (0.44.1)
tests/unit/specfact_requirements/test_requirements_runtime.py

[info] 79-79: use jsonify instead of json.dumps for JSON output
Context: json.dumps([_requirement_record()])
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 91-91: use jsonify instead of json.dumps for JSON output
Context: json.dumps([_requirement_record("REQ-PRESERVE", with_evidence=True)])
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🔀 Multi-repo context nold-ai/specfact-cli

Linked repositories findings

nold-ai/specfact-cli (inspected at refs/heads/dev)

  • docs/architecture/implementation-status.md:26 and docs/architecture/overview.md:19 say specfact requirements ... is not part of the canonical current CLI surface, which conflicts with this PR adding a new specfact requirements runtime bundle/command group. [::nold-ai/specfact-cli::]

  • openspec/parking-lot/ai-integration-04-intent-skills/design.md:18,32,49, .../spec.md:17,25,30, and .../tasks.md:49-50,54 still reference specfact requirements capture, specfact requirements validate, specfact requirements trace, and specfact requirements --help. Those references are stale relative to the new import / validate / list / coverage surface. [::nold-ai/specfact-cli::]

  • openspec/changes/requirements-02-module-commands/specs/requirements-module/spec.md:1-40 and openspec/changes/archive/2026-04-08-cross-repo-issue-realignment/analysis.md:26,72 still describe the older flat specfact requirements ... family and/or older command names. These docs will need alignment with the new grouped runtime commands. [::nold-ai/specfact-cli::]

🔇 Additional comments (3)
tests/unit/specfact_requirements/test_requirements_runtime.py (3)

79-79: Static analysis hint is a false positive.

The use-jsonify hints on lines 79 and 91 don't apply — json.dumps here writes fixture JSON to a local test file, not an HTTP response body, so there's no output-encoding risk.

Also applies to: 91-91


90-106: LGTM! Good targeted coverage for the atomic-save persistence contract on the requirements sidecar, per path instructions for bridge/adapter changes.


43-65: LGTM!

Also applies to: 107-118

@djm81
djm81 merged commit 319a14b into main Jul 8, 2026
27 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in SpecFact CLI Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Requirements Input Runtime Commands Follow-Up

1 participant