Skip to content

feat(ci): marketplace-06 module signing on approval + branch-aware verify#188

Merged
djm81 merged 6 commits intodevfrom
feature/marketplace-06-ci-module-signing
Apr 14, 2026
Merged

feat(ci): marketplace-06 module signing on approval + branch-aware verify#188
djm81 merged 6 commits intodevfrom
feature/marketplace-06-ci-module-signing

Conversation

@djm81
Copy link
Copy Markdown
Contributor

@djm81 djm81 commented Apr 14, 2026

Implements marketplace-06-ci-module-signing (OpenSpec).

  • Branch-aware verify-module-signatures in pr-orchestrator.yml (no --require-signature for dev-targeting events).
  • New sign-modules-on-approval.yml on approved PR reviews targeting dev or main.
  • Workflow contract tests under tests/unit/workflows/.
  • Skip OpenSpec change *.md in pre-commit review gate (avoids false positives on task lists).

Closes #185
Related: nold-ai/specfact-cli#500

Made with Cursor

djm81 added 2 commits April 14, 2026 18:28
- Split pr-orchestrator verify-module-signatures: require signatures only
  for main-targeting PRs/pushes; dev uses checksum + version enforcement.
- Add sign-modules-on-approval workflow on approved reviews for PRs to
  dev/main: sign changed packages via sign-modules.py --changed-only,
  commit and push with [skip ci].
- Add workflow structure tests and TDD evidence for marketplace-06.
- Exclude openspec/changes Markdown from the pre-commit review gate so
  task lists are not parsed as Python; update filter test.

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 14, 2026

📝 Walkthrough

Overview

Implements marketplace-06 CI changes: adds a CI signing workflow that signs changed module manifests on approved PR reviews targeting dev or main, and makes module-signature verification branch-aware so cryptographic signatures are required only at the main boundary while dev/feature branches enforce checksum + version-bump checks.

Bundle & Module Surface

  • No runtime/adapter/bridge API changes to modules or to specfact_cli APIs; module-package.yaml shape and runtime behavior remain unchanged.
  • CI may auto-bump semver for manifests: signer runs scripts/sign-modules.py with --bump-version patch when signing changed manifests.
  • All signing/verification logic is implemented in CI/workflow scripts (scripts/sign-modules.py, scripts/verify-modules-signature.py) and a new local wrapper; no new public library exports introduced.

Manifest & Integrity

  • Manifest discovery path: packages/*/module-package.yaml (signing and discovery operate against packages/).
  • pr-orchestrator (.github/workflows/pr-orchestrator.yml)
    • verify-module-signatures builds VERIFY_CMD as an array, computes TARGET_BRANCH (PR base vs local ref), always runs --payload-from-filesystem and --enforce-version-bump, and conditionally appends --require-signature only when TARGET_BRANCH == "main". For PRs it also appends --version-check-base origin/.
  • New signing workflow (.github/workflows/sign-modules-on-approval.yml)
    • Trigger: pull_request_review submitted; job runs only when review.state == 'approved', base is dev or main, and head.repo == github.repository (same-repo only).
    • Discovers manifests via find packages -name 'module-package.yaml' and emits manifests_count.
    • Computes MERGE_BASE after git fetch origin and runs python scripts/sign-modules.py --changed-only --base-ref "$MERGE_BASE" --bump-version patch --payload-from-filesystem.
    • Requires SPECFACT_MODULE_PRIVATE_SIGN_KEY and SPECFACT_MODULE_PRIVATE_SIGN_KEY_PASSPHRASE; commits changed packages/ with message "chore(modules): ci sign changed modules [skip ci]" and pushes back to PR head branch.
    • If no changes, workflow exits cleanly without committing.
  • Local pre-commit
    • .pre-commit-config.yaml now invokes ./scripts/pre-commit-verify-modules-signature.sh.
    • scripts/pre-commit-verify-modules-signature.sh mirrors CI policy: detects GITHUB_BASE_REF (Actions PR contexts) or local branch and appends --require-signature only for main; otherwise runs with --payload-from-filesystem and --enforce-version-bump.

Cross-repo / Contract Alignment

  • Paired core change required: [Change] CI-Driven Module Signing On PR Approval specfact-cli#500 to align specfact-cli tooling and pre-commit/orchestration expectations.
  • Trust model preserved: cryptographic signatures are authoritative at main; dev/feature branches rely on checksum + enforced version bumps until CI signs on approval.
  • Signing workflow is intentionally limited to same-repo PRs because pushes to forks with the default GITHUB_TOKEN are unsupported.

Tests

  • Added/updated unit tests to assert workflow and wrapper behavior:
    • tests/unit/workflows/test_pr_orchestrator_signing.py — verifies conditional VERIFY_CMD and TARGET_BRANCH logic.
    • tests/unit/workflows/test_sign_modules_on_approval.py — verifies trigger, same-repo guard, manifest discovery, dependency install, secret guards, merge-base usage, sign invocation flags, commit/push, and summary outputs.
    • tests/unit/test_pre_commit_quality_parity.py & tests/unit/test_pre_commit_verify_modules_signature_script.py — assert pre-commit config uses the wrapper and that the wrapper matches CI branch policy.
    • tests/unit/scripts/test_pre_commit_code_review.py — updated to exclude openspec/changes/**/*.md from the pre-commit SpecFact review gate.

Documentation & OpenSpec

  • OpenSpec change set: openspec/changes/marketplace-06-ci-module-signing/ (proposal.md, design.md, spec.md, tasks.md, TDD_EVIDENCE.md) documents:
    • Branch-aware policy (require --require-signature only for main or GITHUB_BASE_REF=main).
    • Merge-base-based changed detection for PR-scoped signing (avoids moving-tip semantics).
    • Manifest discovery under packages/.
    • Tests and TDD evidence demonstrating red→green workflow tests.
  • docs/agent-rules/50-quality-gates-and-review.md and openspec specs updated to reflect wrapper usage and conditional --require-signature behavior.
  • No changes to published modules.specfact.io pages or CHANGELOG in this PR.

Registry / Deployment Impact

  • No consumer-facing registry interface changes; signed manifests are committed back to PR branches and become authoritative once merged to main.
  • Consumers relying on main signatures retain the same trust guarantees after merge.

OpenSpec Change ID & Scenario Coverage

  • OpenSpec change folder: marketplace-06-ci-module-signing
  • Scenarios covered include PR→dev and PR→main approved signing flows, missing-secret failure, fork PR exclusion, PRs with no package changes, idempotency (no-op re-runs), and pre-commit parity for local commits vs CI behavior.

Related Issues & Notes

Walkthrough

Adds an approval-triggered CI signing workflow, makes module-signature enforcement branch-aware (require signatures only for main) across CI and pre-commit, introduces a branch-aware pre-commit wrapper script, excludes OpenSpec markdown from the specfact review gate, and adds/updates unit tests and OpenSpec docs/TDD evidence.

Changes

Cohort / File(s) Summary
Signing workflows & CI
.github/workflows/sign-modules-on-approval.yml, .github/workflows/pr-orchestrator.yml
Adds sign-modules-on-approval triggered on approved PR reviews (same-repo only), discovers manifests, computes merge-base, runs signing in --changed-only mode, and commits/pushes updates; updates pr-orchestrator to build VERIFY_CMD as an array, compute TARGET_BRANCH, and append --require-signature only when target is main.
Pre-commit hook & wrapper
scripts/pre-commit-verify-modules-signature.sh, .pre-commit-config.yaml
Introduces a shell wrapper that runs verify-modules-signature.py --payload-from-filesystem --enforce-version-bump, computes target branch (local or GITHUB_BASE_REF), and appends --require-signature only for main; pre-commit hook entry switched to call this wrapper.
Review-gate filtering
scripts/pre_commit_code_review.py, tests/unit/scripts/test_pre_commit_code_review.py
Updates _is_review_gate_path to explicitly exclude openspec/changes/*.md from the specfact review gate and adjusts unit test expectations accordingly.
Workflow & pre-commit tests
tests/unit/workflows/test_pr_orchestrator_signing.py, tests/unit/workflows/test_sign_modules_on_approval.py, tests/unit/test_pre_commit_verify_modules_signature_script.py, tests/unit/test_pre_commit_quality_parity.py
Adds tests asserting pr-orchestrator VERIFY_CMD array-building and TARGET_BRANCH guard, sign-on-approval job wiring (triggers, same-repo guard, checkout, Python 3.12, manifest discovery, merge-base fetch, signing flags, secrets), pre-commit hook entry, and wrapper script branch-policy behavior.
Pre-commit config & quality docs
.pre-commit-config.yaml, docs/agent-rules/50-quality-gates-and-review.md
Switches verify-module-signatures hook to the new shell wrapper and updates documentation to describe branch-aware --require-signature behavior.
OpenSpec docs, TDD & tasks
openspec/changes/marketplace-06-ci-module-signing/*, openspec/specs/modules-pre-commit-quality-parity/spec.md, openspec/config.yaml
Adds TDD evidence, design/proposal/spec/task updates documenting branch-aware enforcement, new workflow, merge-base-based changed selection, and completed checklist entries.

Sequence Diagram(s)

sequenceDiagram
    actor Reviewer
    participant GitHub as GitHub Actions
    participant Checkout as Checkout
    participant Runner as Runner (Actions)
    participant Python as Python 3.12
    participant Discover as Manifest Discovery
    participant Sign as sign-modules.py
    participant Git as Git Commit/Push
    participant Summary as Job Summary

    Reviewer->>GitHub: Submit approved review (base: dev or main)
    GitHub->>GitHub: Trigger sign-modules-on-approval
    GitHub->>Checkout: Checkout PR head commit
    Checkout->>Runner: Start job on runner
    Runner->>Python: Setup Python & deps
    Python->>Discover: Find `packages/**/module-package.yaml`
    Discover->>Sign: Invoke `scripts/sign-modules.py --changed-only --bump-version patch --payload-from-filesystem --base-ref "$MERGE_BASE"`
    Sign->>Sign: Sign/bump manifests if applicable
    alt Changes detected under packages/
        Sign->>Git: Commit changes & push to `HEAD:${PR_HEAD_REF}`
        Git->>Summary: Write `COMMIT_CHANGED: true` and `MANIFESTS_COUNT:`
    else No changes
        Sign->>Summary: Write `COMMIT_CHANGED: false` and `MANIFESTS_COUNT:`
    end
    Summary->>GitHub: Update job summary
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels

openspec

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.43% 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 Title follows Conventional Commits style with 'feat(ci):' prefix and clearly summarizes the main changes: branch-aware verification and signing-on-approval workflow.
Description check ✅ Passed Description covers key objectives (branch-aware verification, new signing workflow, tests, pre-commit gate), includes issue references, and aligns with the template structure despite not filling all optional sections.
Linked Issues check ✅ Passed Changes fully implement #185 requirements: branch-aware verify logic in pr-orchestrator, new sign-modules-on-approval workflow with manifest discovery, workflow tests, OpenSpec specs, and pre-commit gate adjustments.
Out of Scope Changes check ✅ Passed All changes align with marketplace-06 objectives: workflow updates, signing scripts, tests, documentation, and OpenSpec records directly support CI signing and branch-aware verification requirements.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/marketplace-06-ci-module-signing

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

@djm81 djm81 self-assigned this Apr 14, 2026
@djm81 djm81 added enhancement New feature or request dependencies Pull requests that update a dependency file architecture Architecture-related topic module Specfact Module related topic marketplace Specfact Marketplace related topic labels Apr 14, 2026
@djm81 djm81 moved this from Todo to In Progress in SpecFact CLI Apr 14, 2026
@djm81 djm81 linked an issue Apr 14, 2026 that may be closed by this pull request
@djm81 djm81 linked an issue Apr 14, 2026 that may be closed by this pull request
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: 81116d2b3e

ℹ️ 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 .github/workflows/sign-modules-on-approval.yml
Comment thread .github/workflows/sign-modules-on-approval.yml Outdated
Copy link
Copy Markdown

@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: 5

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

Inline comments:
In @.github/workflows/sign-modules-on-approval.yml:
- Around line 50-55: The "Discover module manifests" step currently uses mapfile
to populate the MANIFESTS array but never exports its result, so either remove
this informational step if it's unnecessary noise, or modify it to export the
discovered count for downstream summary use: capture the length of MANIFESTS
(from the mapfile call) and write it to GITHUB_OUTPUT (or set-output) under a
clear key like manifests_count so later steps can consume it; reference the
MANIFESTS array, the mapfile invocation, and the step name "Discover module
manifests" when making the change.
- Around line 35-38: The workflow currently checks out the PR commit using
actions/checkout@v4 with ref: ${{ github.event.pull_request.head.sha }}, which
can diverge from the branch targeted by the subsequent push
(HEAD:${PR_HEAD_REF}); change the checkout to use the branch ref (${{
github.event.pull_request.head.ref }}) so you get the latest branch tip, or if
you prefer to keep the SHA, add a pre-push sync step that runs git fetch origin
"${PR_HEAD_REF}" and git pull --rebase origin "${PR_HEAD_REF}" (or equivalent)
before the commit/push to ensure a fast-forward; adjust the action configuration
and the step sequence that references PR_HEAD_REF and HEAD:${PR_HEAD_REF}
accordingly.

In `@openspec/changes/marketplace-06-ci-module-signing/tasks.md`:
- Around line 40-45: Task 4.5 in the marketplace-06 CI tasks incorrectly
recommends using the --allow-same-version flag while the actual workflow
sign-modules-on-approval.yml enforces version bumps; update the task text to
remove or caveat the --allow-same-version suggestion and instead state that the
workflow enforces version increments (or mention the alternative “or use
--changed-only --base-ref \"$BASE_REF\"” path), keeping the note about failing
immediately if SPECFACT_MODULE_PRIVATE_SIGN_KEY or
SPECFACT_MODULE_PRIVATE_SIGN_KEY_PASSPHRASE is empty; reference the task label
“4.5” and the flag name “--allow-same-version” so the change is easy to find.

In `@tests/unit/workflows/test_pr_orchestrator_signing.py`:
- Around line 19-24: The test currently checks substrings but not that the
--require-signature append is inside the main-branch conditional; update
tests/unit/workflows/test_pr_orchestrator_signing.py to assert the full
conditional head 'if [ "$TARGET_BRANCH" = "main" ]; then' (or equivalent exact
block opener) is present, keep the existing assertion for
'VERIFY_CMD+=(--require-signature)', and add a sequence check by locating the
index of the TARGET_BRANCH check string and the index of
'VERIFY_CMD+=(--require-signature)' in the workflow string and asserting the
branch check index is before the require-signature index so the append is
guarded by the main-branch condition.

In `@tests/unit/workflows/test_sign_modules_on_approval.py`:
- Around line 41-49: Update the test_sign_modules_on_approval_sign_and_secrets
test to also assert that the guard step for secrets is present and enforces
failure: check that the workflow string (workflow) contains the guard step title
"Guard signing secrets", contains the shell check for missing
SPECFACT_MODULE_PRIVATE_SIGN_KEY (e.g. '[ -z
"${SPECFACT_MODULE_PRIVATE_SIGN_KEY:-}" ]') and that the guard includes an "exit
1" on failure; this ensures the guard step (not just env vars) is validated by
the test.
🪄 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: ce850a30-c760-42c9-b026-d659aecd33c9

📥 Commits

Reviewing files that changed from the base of the PR and between 4f48732 and 81116d2.

📒 Files selected for processing (8)
  • .github/workflows/pr-orchestrator.yml
  • .github/workflows/sign-modules-on-approval.yml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • scripts/pre_commit_code_review.py
  • tests/unit/scripts/test_pre_commit_code_review.py
  • tests/unit/workflows/test_pr_orchestrator_signing.py
  • tests/unit/workflows/test_sign_modules_on_approval.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). (3)
  • GitHub Check: quality (3.12)
  • GitHub Check: quality (3.11)
  • GitHub Check: quality (3.13)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{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:

  • scripts/pre_commit_code_review.py
  • tests/unit/scripts/test_pre_commit_code_review.py
  • tests/unit/workflows/test_pr_orchestrator_signing.py
  • tests/unit/workflows/test_sign_modules_on_approval.py
scripts/**/*.py

⚙️ CodeRabbit configuration file

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

Files:

  • scripts/pre_commit_code_review.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/scripts/test_pre_commit_code_review.py
  • tests/unit/workflows/test_pr_orchestrator_signing.py
  • tests/unit/workflows/test_sign_modules_on_approval.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/marketplace-06-ci-module-signing/tasks.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
.github/workflows/**

⚙️ CodeRabbit configuration file

.github/workflows/**: CI: secrets, hatch/verify-modules-signature gates, contract-test alignment, action versions.

Files:

  • .github/workflows/pr-orchestrator.yml
  • .github/workflows/sign-modules-on-approval.yml
🧠 Learnings (13)
📓 Common learnings
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:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Enforce module signatures and version bumps when signed module assets or manifests are affected
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json

Applied to files:

  • scripts/pre_commit_code_review.py
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Treat the clean-code compliance gate as mandatory: the review surface enforces `naming`, `kiss`, `yagni`, `dry`, and `solid` categories and blocks regressions

Applied to files:

  • scripts/pre_commit_code_review.py
📚 Learning: 2026-04-13T10:38:29.379Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics

Applied to files:

  • scripts/pre_commit_code_review.py
  • tests/unit/scripts/test_pre_commit_code_review.py
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • .github/workflows/sign-modules-on-approval.yml
📚 Learning: 2026-04-13T10:38:29.379Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: Applies to **/*.{js,ts,tsx,jsx,py,java,cs,go,rb,php,cpp,c,h} : Preserve the clean-code compliance gate and its category references (naming, kiss, yagni, dry, and solid)

Applied to files:

  • scripts/pre_commit_code_review.py
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Fix SpecFact code review findings, including warnings, unless a rare explicit exception is documented

Applied to files:

  • scripts/pre_commit_code_review.py
📚 Learning: 2026-04-02T21:49:11.371Z
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:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • .github/workflows/pr-orchestrator.yml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • tests/unit/workflows/test_pr_orchestrator_signing.py
  • .github/workflows/sign-modules-on-approval.yml
  • tests/unit/workflows/test_sign_modules_on_approval.py
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • .github/workflows/pr-orchestrator.yml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • .github/workflows/sign-modules-on-approval.yml
  • tests/unit/workflows/test_sign_modules_on_approval.py
📚 Learning: 2026-04-13T10:38:15.842Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.842Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Require public GitHub metadata completeness before implementation when linked issue workflow applies: parent, labels, project assignment, blockers, and blocked-by relationships

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Enforce module signatures and version bumps when signed module assets or manifests are affected

Applied to files:

  • .github/workflows/pr-orchestrator.yml
🪛 LanguageTool
openspec/changes/marketplace-06-ci-module-signing/tasks.md

[uncategorized] ~21-~21: The official name of this software platform is spelled with a capital “H”.
Context: ...t verify by target branch - [x] 3.1 In .github/workflows/pr-orchestrator.yml, in the ...

(GITHUB)


[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ...job, extract the target branch fromgithub.event.pull_request.base.ref` (PR events...

(GITHUB)


[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ....pull_request.base.ref(PR events) andgithub.ref` (push events). - [x] 3.2 For eve...

(GITHUB)


[uncategorized] ~32-~32: The official name of this software platform is spelled with a capital “H”.
Context: ...dules-on-approval.yml - [x] 4.1 Create .github/workflows/sign-modules-on-approval.yml...

(GITHUB)


[uncategorized] ~34-~34: The official name of this software platform is spelled with a capital “H”.
Context: ...bmitted]. - [x] 4.2 Add job condition: if: github.event.review.state == 'approved' && (gi...

(GITHUB)


[uncategorized] ~40-~40: The official name of this software platform is spelled with a capital “H”.
Context: ...). - [x] 4.5 Add signing step: compute BASE_REF="origin/${{ github.event.pull_request.base.ref }}"`; for...

(GITHUB)

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

nold-ai/specfact-cli

  • .github/workflows/pr-orchestrator.yml — contains verify-module-signatures job referenced by tests and docs; tests assert presence and conditional VERIFY_CMD logic. [::nold-ai/specfact-cli::.github/workflows/pr-orchestrator.yml]
  • .github/workflows/sign-modules.yml — existing signing workflow; new sign-on-approval workflow in PR will be analogous. [::nold-ai/specfact-cli::.github/workflows/sign-modules.yml]
  • scripts/sign-modules.py — signing implementation used by CI and docs; referenced by multiple docs and scripts (publish-module.py, sign-module.sh, docs). Changes to workflow flags/args (e.g., --changed-only, --base-ref, --payload-from-filesystem, --bump-version, --require-signature) must match this script's CLI. [::nold-ai/specfact-cli::scripts/sign-modules.py]
  • scripts/verify-modules-signature.py — verifier script invoked by pr-orchestrator verify step (rg matched references to verify-module-signatures job invoking this script). Ensure pr-orchestrator changes still build the invocation args compatible with this script. [::nold-ai/specfact-cli::scripts/verify-modules-signature.py]
  • scripts/publish-module.py — calls scripts/sign-modules.py; CI signing/push behavior that updates manifests may interact with publishing flows. [::nold-ai/specfact-cli::scripts/publish-module.py]
  • scripts/pre_commit_code_review.py — present and heavily tested; PR changes exclude openspec/changes/*.md from review gate — tests updated accordingly (tests/unit/scripts/test_pre_commit_code_review.py). Verify altered path filtering aligns with other tests/consumers. [::nold-ai/specfact-cli::scripts/pre_commit_code_review.py]
  • tests/unit/workflows/* — multiple tests reference verify-module-signatures and sign-modules workflows (e.g., tests/unit/workflows/test_trustworthy_green_checks.py, tests/unit/workflows/test_pr_orchestrator_signing.py, tests/unit/workflows/test_sign_modules_on_approval.py). These tests assert workflow contents and flags; they must be kept in sync with the YAML changes. [::nold-ai/specfact-cli::tests/unit/workflows/]
  • docs/guides/module-signing-and-key-rotation.md and docs/module-system/module-marketplace.md — document invocation patterns for scripts/sign-modules.py and CI usage; updates to workflow arg behavior (signature requirement conditional on target branch) should be reflected in docs if necessary. [::nold-ai/specfact-cli::docs/guides/module-signing-and-key-rotation.md]

Conclusion: The PR touches workflow invocation arguments and adds a signing-on-approval workflow that will call scripts/sign-modules.py. Relevant consumers and contract points found: scripts/sign-modules.py, scripts/verify-modules-signature.py, scripts/publish-module.py, pre_commit_code_review.py, multiple workflow tests, and documentation pages. Reviewers should verify the new workflow and pr-orchestrator argument construction remain compatible with scripts/sign-modules.py and verify-modules-signature.py CLI expectations, and that unit tests/tests/workflows reflect the updated YAML.

🔇 Additional comments (7)
.github/workflows/pr-orchestrator.yml (1)

82-106: LGTM on branch-aware signature enforcement logic.

The VERIFY_CMD array construction cleanly separates the conditional --require-signature flag for main versus dev branches. This aligns well with the trust model documented in the linked issue: signatures enforced at the main boundary, checksum-only integrity for dev-targeting PRs.

The script invocation matches the scripts/verify-modules-signature.py argparse definition (context snippet 2 from relevant code snippets), where --require-signature is a store_true optional flag.

.github/workflows/sign-modules-on-approval.yml (2)

56-66: Script invocation correctly matches sign-modules.py CLI contract.

The flags --changed-only, --base-ref, --bump-version patch, and --payload-from-filesystem align with the argparse definition in scripts/sign-modules.py (lines 346-395 in linked repo context). The combination triggers the intended flow: filter changed modules, auto-bump patch version if unchanged, enforce version bump, and sign with filesystem payload.


67-81: LGTM on commit-back logic.

The step properly:

  • Sets bot identity for attribution
  • Uses git status --porcelain -- packages/ to detect actual changes
  • Stages only modified tracked files with git add -u
  • Includes [skip ci] to prevent infinite workflow loops
  • Outputs changed=true/false for downstream summary
tests/unit/scripts/test_pre_commit_code_review.py (1)

37-51: LGTM on test update for OpenSpec Markdown exclusion.

The test correctly verifies that openspec/changes/**/*.md files (including tasks.md and proposal.md) are now filtered out, leaving only paths under valid review-gate prefixes like tests/. This aligns with the scripts/pre_commit_code_review.py change that prevents false positives when the review CLI attempts Python analysis on Markdown docs.

scripts/pre_commit_code_review.py (1)

56-58: LGTM on Markdown exclusion from review gate.

The exclusion correctly filters openspec/changes/**/*.md files before the prefix matching at Line 65. The case-insensitive .lower().endswith(".md") handles mixed-case extensions. The comment documents the rationale: SpecFact CLI treats these as Python and emits noise.

Note: openspec/changes/ remains in the prefixes tuple (Line 65), which still allows non-Markdown files under that path to participate in the gate if needed.

openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md (1)

1-48: LGTM on TDD evidence documentation.

The document follows the expected spec -> tests -> failing -> code -> passing order. The Green verification section properly records pytest, hatch run lint, yaml-lint, and actionlint results. The pre-commit note explains the Markdown exclusion rationale clearly.

tests/unit/workflows/test_sign_modules_on_approval.py (1)

52-58: LGTM on commit/push/summary assertions.

The test properly validates:

  • Bot identity (github-actions[bot])
  • Commit message format with [skip ci]
  • Push target pattern (HEAD:${PR_HEAD_REF})
  • Summary output markers

Comment thread .github/workflows/sign-modules-on-approval.yml
Comment thread .github/workflows/sign-modules-on-approval.yml
Comment thread openspec/changes/marketplace-06-ci-module-signing/tasks.md Outdated
Comment thread tests/unit/workflows/test_pr_orchestrator_signing.py Outdated
Comment thread tests/unit/workflows/test_sign_modules_on_approval.py
@djm81
Copy link
Copy Markdown
Contributor Author

djm81 commented Apr 14, 2026

@cursor review this PR

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 14, 2026

Skipping Bugbot: Bugbot is disabled for this repository. Visit the Bugbot dashboard to update your settings.

…tures)

- Add scripts/pre-commit-verify-modules-signature.sh: --require-signature on
  main / GITHUB_REF_NAME=main only; always --payload-from-filesystem
  --enforce-version-bump.
- Point .pre-commit-config.yaml verify hook at the wrapper; update
  modules-pre-commit-quality-parity spec, ci-integration delta, openspec
  config context, and agent quality-gates doc.
- Tests for wrapper content and hook entry.

Block 2 skipped locally: specfact code review requires installed bundles
(specfact-codebase); verify via hatch run lint + targeted pytest.

Made-with: Cursor
@djm81
Copy link
Copy Markdown
Contributor Author

djm81 commented Apr 14, 2026

@cursor review this PR, I enabled it.

@djm81
Copy link
Copy Markdown
Contributor Author

djm81 commented Apr 14, 2026

@cursor @BugBot review this PR

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 14, 2026

Bugbot-style review (what I verified and changed)

I treated the PR thread as a review checklist and validated it against scripts/sign-modules.py (git diff <ref> -- <module> for --changed-only). The serious items were:

  1. Fork PRs — Pushing HEAD:${PR_HEAD_REF} only works when the head ref lives in this repo. The job already gates on github.event.pull_request.head.repo.full_name == github.repository (kept).
  2. Change scope — Comparing only to origin/<base> can include base-branch changes when the PR branch is behind. Using MERGE_BASE="$(git merge-base HEAD "origin/${PR_BASE_REF}")" and passing that to --base-ref scopes signing to this PR’s delta (kept, with git fetch … --no-tags from the upstream fix).
  3. Checkout vs push — Checkout uses github.event.pull_request.head.ref so the working tree matches the branch you push (kept).
  4. CodeRabbit / tests — Tightened workflow structure tests: main-branch guard ordering in pr-orchestrator, and for sign-modules-on-approval: secret guard, merge-base + fetch (--no-tags), and the discover step output used in the summary.

openspec/.../tasks.md and TDD_EVIDENCE.md are aligned with the implementation.

Verification: hatch run contract-test — 555 passed.

Git: Rebased on the latest remote branch, pushed feature/marketplace-06-ci-module-signing, and updated PR #188 against dev.

Note: Fork PRs no longer run this job; maintainers still need another path (e.g. manual sign or workflow_dispatch) if you want signing for forks. Say if you want that documented in the OpenSpec spec.

Open in Web Open in Cursor 

djm81 and others added 2 commits April 14, 2026 18:43
- Export manifests_count from discover step; show in job summary.
- Checkout PR head.ref; fetch base and use merge-base for --changed-only.
- Restrict job to same-repo PRs (fork signing not supported with GITHUB_TOKEN).
- Tighten workflow tests and tasks/spec text; Codex P1 items resolved.

Made-with: Cursor
- Run only for same-repo PRs so push targets the PR branch
- Checkout head.ref for branch tip; use merge-base for --changed-only
- Strengthen workflow tests; align OpenSpec tasks and TDD evidence

Co-authored-by: Dom <djm81@users.noreply.github.com>
Copy link
Copy Markdown

@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: 4

🤖 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/marketplace-06-ci-module-signing/TDD_EVIDENCE.md`:
- Around line 5-7: Update TDD_EVIDENCE.md to include the actual Red-state
failing output for the missing workflow: run the failing test command (e.g.,
pytest tests/unit/workflows/test_sign_modules_on_approval.py or the CI job that
referenced sign-modules-on-approval.yml), capture the console output or a
concise excerpt with a timestamp, and insert that block immediately before the
Green-run evidence; reference the specific artifacts in the narrative
(sign-modules-on-approval.yml,
tests/unit/workflows/test_sign_modules_on_approval.py, and pr-orchestrator.yml)
so the TDD chain shows spec -> tests -> failing evidence -> code -> passing
evidence in order.

In `@openspec/specs/modules-pre-commit-quality-parity/spec.md`:
- Around line 10-13: Add a blank line after the heading "#### Scenario:
Signature verification hook is configured" so the subsequent list starts on a
separate paragraph, fixing markdownlint MD022; edit the spec.md content around
the "Scenario: Signature verification hook is configured" heading to insert one
empty line before the first list item ("- **WHEN** a developer installs...") so
the heading and list are correctly separated.

In `@scripts/pre-commit-verify-modules-signature.sh`:
- Around line 9-13: The branch-detection fallback uses GITHUB_REF_NAME (the PR
head) which is incorrect for PR base/target checks; update the logic that sets
_require_signature (currently comparing "$_branch" and "${GITHUB_REF_NAME:-}")
to instead check "${GITHUB_BASE_REF:-}" so that in Actions PR events the base
branch (target) is used; ensure the variables referenced remain _branch and
_require_signature and only replace the fallback env var name from
GITHUB_REF_NAME to GITHUB_BASE_REF.

In `@tests/unit/test_pre_commit_verify_modules_signature_script.py`:
- Around line 11-16: The test currently only checks for substrings; strengthen
it to verify the conditional behavior by asserting that "--require-signature" is
present only inside the main-branch conditional and not in the default path:
update the test that sets or inspects the rendered script/text (variable text)
to use a regex or substring checks to confirm that the sequence '== "main"' (or
the surrounding if/branch header) is followed within that branch body by
"--require-signature", and also add an assertion that the default/else branch
(or the script outside that if) does NOT contain "--require-signature";
reference the existing assertions for "GITHUB_REF_NAME" and '== "main"' and the
"--require-signature" token in your new checks to locate where to add the
stronger assertions.
🪄 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: 57b355f3-28fd-408a-98eb-a34eee722a72

📥 Commits

Reviewing files that changed from the base of the PR and between 81116d2 and b386cb3.

📒 Files selected for processing (12)
  • .pre-commit-config.yaml
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/design.md
  • openspec/changes/marketplace-06-ci-module-signing/proposal.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • openspec/config.yaml
  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • scripts/pre-commit-verify-modules-signature.sh
  • tests/unit/test_pre_commit_quality_parity.py
  • tests/unit/test_pre_commit_verify_modules_signature_script.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). (3)
  • GitHub Check: quality (3.11)
  • GitHub Check: quality (3.13)
  • GitHub Check: quality (3.12)
🧰 Additional context used
📓 Path-based instructions (5)
docs/agent-rules/**/*.md

📄 CodeRabbit inference engine (.cursorrules)

Load docs/agent-rules/INDEX.md and canonical rule files selected by its applicability matrix

Files:

  • docs/agent-rules/50-quality-gates-and-review.md
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/agent-rules/50-quality-gates-and-review.md
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/marketplace-06-ci-module-signing/design.md
  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/proposal.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
**/*.{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/test_pre_commit_verify_modules_signature_script.py
  • tests/unit/test_pre_commit_quality_parity.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/test_pre_commit_verify_modules_signature_script.py
  • tests/unit/test_pre_commit_quality_parity.py
🧠 Learnings (15)
📓 Common learnings
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:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Enforce module signatures and version bumps when signed module assets or manifests are affected
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.842Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Treat the clean-code compliance gate as mandatory: the review surface enforces `naming`, `kiss`, `yagni`, `dry`, and `solid` categories and blocks regressions
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature

Applied to files:

  • .pre-commit-config.yaml
  • openspec/config.yaml
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/changes/marketplace-06-ci-module-signing/design.md
  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • scripts/pre-commit-verify-modules-signature.sh
  • openspec/changes/marketplace-06-ci-module-signing/proposal.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-02T21:49:11.371Z
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:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.

Applied to files:

  • .pre-commit-config.yaml
  • openspec/config.yaml
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/changes/marketplace-06-ci-module-signing/design.md
  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • scripts/pre-commit-verify-modules-signature.sh
  • openspec/changes/marketplace-06-ci-module-signing/proposal.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Enforce module signatures and version bumps when signed module assets or manifests are affected

Applied to files:

  • .pre-commit-config.yaml
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/changes/marketplace-06-ci-module-signing/design.md
  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • scripts/pre-commit-verify-modules-signature.sh
  • openspec/changes/marketplace-06-ci-module-signing/proposal.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:29.379Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics

Applied to files:

  • openspec/config.yaml
  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/proposal.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:15.842Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.842Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`

Applied to files:

  • openspec/config.yaml
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json

Applied to files:

  • openspec/config.yaml
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/

Applied to files:

  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Run the required verification and quality gates for the touched scope before finalization

Applied to files:

  • openspec/config.yaml
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:29.379Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: Treat canonical rule docs (docs/agent-rules/INDEX.md) as the source of truth for worktree policy, OpenSpec gating, GitHub completeness checks, TDD order, quality gates, versioning, and documentation rules

Applied to files:

  • docs/agent-rules/50-quality-gates-and-review.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Full governance rules live in docs/agent-rules/; do not treat this file (GitHub Copilot Instructions) as a complete standalone handbook

Applied to files:

  • docs/agent-rules/50-quality-gates-and-review.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Treat the clean-code compliance gate as mandatory: the review surface enforces `naming`, `kiss`, `yagni`, `dry`, and `solid` categories and blocks regressions

Applied to files:

  • docs/agent-rules/50-quality-gates-and-review.md
📚 Learning: 2026-04-13T10:38:29.379Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: Applies to **/*.{js,ts,tsx,jsx,py,java,cs,go,rb,php,cpp,c,h} : Preserve the clean-code compliance gate and its category references (naming, kiss, yagni, dry, and solid)

Applied to files:

  • docs/agent-rules/50-quality-gates-and-review.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Do not implement from the `dev` or `main` checkout by default

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/design.md
🪛 LanguageTool
openspec/changes/marketplace-06-ci-module-signing/tasks.md

[uncategorized] ~21-~21: The official name of this software platform is spelled with a capital “H”.
Context: ...t verify by target branch - [x] 3.1 In .github/workflows/pr-orchestrator.yml, in the ...

(GITHUB)


[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ...job, extract the target branch fromgithub.event.pull_request.base.ref` (PR events...

(GITHUB)


[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ....pull_request.base.ref(PR events) andgithub.ref` (push events). - [x] 3.2 For eve...

(GITHUB)


[uncategorized] ~35-~35: The official name of this software platform is spelled with a capital “H”.
Context: ...dules-on-approval.yml - [x] 4.1 Create .github/workflows/sign-modules-on-approval.yml...

(GITHUB)


[uncategorized] ~37-~37: The official name of this software platform is spelled with a capital “H”.
Context: ...bmitted]. - [x] 4.2 Add job condition: if: github.event.review.state == 'approved' && (gi...

(GITHUB)


[uncategorized] ~43-~43: The official name of this software platform is spelled with a capital “H”.
Context: ...). - [x] 4.5 Add signing step: compute BASE_REF="origin/${{ github.event.pull_request.base.ref }}"`; for...

(GITHUB)

🪛 markdownlint-cli2 (0.22.0)
openspec/specs/modules-pre-commit-quality-parity/spec.md

[warning] 10-10: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

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

Findings for nold-ai/specfact-cli:

  • scripts/sign-modules.py — CLI exposes changed-only, base-ref, bump-version, payload-from-filesystem, passphrase handling; used by workflows/publish and publish-module.py. [::nold-ai/specfact-cli::scripts/sign-modules.py]

  • scripts/verify-modules-signature.py — verifier expects flags including --payload-from-filesystem, --enforce-version-bump and supports --require-signature. Workflows invoke it with those flags. [::nold-ai/specfact-cli::scripts/verify-modules-signature.py]

  • .github/workflows/pr-orchestrator.yml — contains verify-module-signatures invocation that includes --require-signature and --payload-from-filesystem in existing lines. Tests in repo assert conditional VERIFY_CMD logic and presence of VERIFY_CMD+=(--require-signature). [::nold-ai/specfact-cli::.github/workflows/pr-orchestrator.yml]

  • .github/workflows/sign-modules.yml — existing signing workflow invoking scripts/sign-modules.py and scripts/verify-modules-signature.py; contains examples of using --payload-from-filesystem and --version-check-base. [::nold-ai/specfact-cli::.github/workflows/sign-modules.yml]

  • scripts/pre_commit_code_review.py — present and heavily tested; test suite references it. PR’s change to exclude openspec/changes/*.md will affect this module and its tests. [::nold-ai/specfact-cli::scripts/pre_commit_code_review.py]

  • Tests and docs that reference these tools:

    • tests/unit/specfact_cli/registry/test_signing_artifacts.py — checks presence/usage of sign/verify scripts and workflow invocations (search hits asserting verify script exists and includes --require-signature). [::nold-ai/specfact-cli::tests/unit/specfact_cli/registry/test_signing_artifacts.py]
    • docs/guides/module-signing-and-key-rotation.md and other docs reference verify/sign command forms; ensure documentation matches new branch-aware behavior. [::nold-ai/specfact-cli::docs/guides/module-signing-and-key-rotation.md]

Implication summary:

  • The workflows and pre-commit wrapper introduced by the PR must remain compatible with the CLI flags already implemented by scripts/sign-modules.py and scripts/verify-modules-signature.py — those scripts do expose the flags referenced by the workflows.
  • Updating pr-orchestrator to conditionally append --require-signature must align with test assertions that look for VERIFY_CMD+=(--require-signature) and with any documentation/tests that assume always-present --require-signature (several tests/docs check for it).
  • Changes to scripts/pre_commit_code_review.py path filtering will impact its unit tests (tests/unit/scripts/test_pre_commit_code_review.py) and should be kept in sync.
🔇 Additional comments (6)
.pre-commit-config.yaml (1)

9-9: Good alignment with branch-aware signing policy.

Switching the hook entry to the wrapper keeps local verification behavior consistent with CI boundary rules (main enforces signature requirement).

tests/unit/test_pre_commit_quality_parity.py (1)

88-103: Nice parity guard for pre-commit wiring.

This test cleanly enforces that verify-module-signatures resolves through the branch-aware wrapper, which helps keep local and CI policy in sync.

openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md (1)

38-53: Spec update is consistent with the new branch-boundary trust model.

The added requirement and scenarios clearly encode main vs non-main verification behavior and align with the CI-signing flow described in this PR.

scripts/pre-commit-verify-modules-signature.sh (1)

15-20: Good verifier invocation baseline and exit-path handling.

Always including payload/version-bump checks and using exec here is solid.

openspec/specs/modules-pre-commit-quality-parity/spec.md (1)

8-16: Policy wording update is clear and operationally aligned.

The requirement/scenario updates capture the intended pre-commit parity behavior well.

openspec/changes/marketplace-06-ci-module-signing/proposal.md (1)

19-21: Proposal-to-spec parity looks tight across workflow, hook, and impact sections.

These updates keep the modules/core signing contract and docs surface aligned for this change set.

Also applies to: 40-42, 47-47, 53-54

Comment thread openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md Outdated
Comment thread openspec/specs/modules-pre-commit-quality-parity/spec.md
Comment thread scripts/pre-commit-verify-modules-signature.sh
Comment thread tests/unit/test_pre_commit_verify_modules_signature_script.py Outdated
Copy link
Copy Markdown

@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 `@tests/unit/workflows/test_sign_modules_on_approval.py`:
- Around line 14-22: The test function
test_sign_modules_on_approval_trigger_and_job_filter currently checks triggers
and filters but misses assertions for concurrency and permissions; update the
test (in test_sign_modules_on_approval_trigger_and_job_filter) to assert that
the rendered workflow string stored in workflow contains "concurrency:" and
"cancel-in-progress: true" and also contains "permissions:" and "contents:
write" so the workflow enforces a concurrency group and grants contents write
permission.
🪄 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: a43ac1dc-3978-4d80-bbc0-833ec3072224

📥 Commits

Reviewing files that changed from the base of the PR and between b386cb3 and 9b9ecf9.

📒 Files selected for processing (6)
  • .github/workflows/sign-modules-on-approval.yml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-module-signing-on-approval/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • tests/unit/workflows/test_pr_orchestrator_signing.py
  • tests/unit/workflows/test_sign_modules_on_approval.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). (3)
  • GitHub Check: quality (3.13)
  • GitHub Check: quality (3.12)
  • GitHub Check: quality (3.11)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{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/workflows/test_pr_orchestrator_signing.py
  • tests/unit/workflows/test_sign_modules_on_approval.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/workflows/test_pr_orchestrator_signing.py
  • tests/unit/workflows/test_sign_modules_on_approval.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/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-module-signing-on-approval/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
.github/workflows/**

⚙️ CodeRabbit configuration file

.github/workflows/**: CI: secrets, hatch/verify-modules-signature gates, contract-test alignment, action versions.

Files:

  • .github/workflows/sign-modules-on-approval.yml
🧠 Learnings (10)
📓 Common learnings
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:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Enforce module signatures and version bumps when signed module assets or manifests are affected
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.842Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json
📚 Learning: 2026-04-02T21:49:11.371Z
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:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.

Applied to files:

  • tests/unit/workflows/test_pr_orchestrator_signing.py
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • .github/workflows/sign-modules-on-approval.yml
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-module-signing-on-approval/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • tests/unit/workflows/test_sign_modules_on_approval.py
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:29.379Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-module-signing-on-approval/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:15.842Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.842Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • .github/workflows/sign-modules-on-approval.yml
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-module-signing-on-approval/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Enforce module signatures and version bumps when signed module assets or manifests are affected

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • .github/workflows/sign-modules-on-approval.yml
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-module-signing-on-approval/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Require public GitHub metadata completeness before implementation when linked issue workflow applies: parent, labels, project assignment, blockers, and blocked-by relationships

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
🪛 LanguageTool
openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md

[uncategorized] ~33-~33: The official name of this software platform is spelled with a capital “H”.
Context: ...l) - Same-repo PRs only: job if adds `github.event.pull_request.head.repo.full_name ...

(GITHUB)

openspec/changes/marketplace-06-ci-module-signing/tasks.md

[uncategorized] ~21-~21: The official name of this software platform is spelled with a capital “H”.
Context: ...t verify by target branch - [x] 3.1 In .github/workflows/pr-orchestrator.yml, in the ...

(GITHUB)


[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ...job, extract the target branch fromgithub.event.pull_request.base.ref` (PR events...

(GITHUB)


[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ....pull_request.base.ref(PR events) andgithub.ref` (push events). - [x] 3.2 For eve...

(GITHUB)


[uncategorized] ~35-~35: The official name of this software platform is spelled with a capital “H”.
Context: ...dules-on-approval.yml - [x] 4.1 Create .github/workflows/sign-modules-on-approval.yml...

(GITHUB)


[uncategorized] ~37-~37: The official name of this software platform is spelled with a capital “H”.
Context: ...roved review, base dev or main, and `github.event.pull_request.head.repo.full_name ...

(GITHUB)

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

nold-ai/specfact-cli

  • scripts/verify-modules-signature.py — verifier implementation that supports flags used by workflows (e.g. --payload-from-filesystem, --enforce-version-bump, --require-signature, --version-check-base). [::nold-ai/specfact-cli::scripts/verify-modules-signature.py]

  • scripts/sign-modules.py — signer implementation supporting --changed-only, --base-ref, --bump-version, --payload-from-filesystem and key/passphrase env vars referenced by new workflow. [::nold-ai/specfact-cli::scripts/sign-modules.py]

  • .github/workflows/pr-orchestrator.yml — existing verify step invokes verifier with --require-signature (and version-check-base when BASE_REF set). Tests and PR changes will need to align with this file’s conditional VERIFY_CMD behavior. [::nold-ai/specfact-cli::.github/workflows/pr-orchestrator.yml]

  • .github/workflows/sign-modules.yml — existing signing workflow invokes sign-modules and verifier; contains verifier calls that include --require-signature and optionally --version-check-base. New sign-on-approval workflow in modules repo should match expectations here (flags, fetch/merge-base semantics). [::nold-ai/specfact-cli::.github/workflows/sign-modules.yml]

  • tests/unit/specfact_cli/registry/test_signing_artifacts.py — unit tests assert presence of scripts and workflows and specifically check for "verify-modules-signature.py --require-signature" in workflow/test content; these tests will be sensitive to the PR’s change that makes --require-signature conditional. [::nold-ai/specfact-cli::tests/unit/specfact_cli/registry/test_signing_artifacts.py]

  • tests/unit/workflows/test_trustworthy_green_checks.py — references SIGN_WORKFLOW path (.github/workflows/sign-modules.yml) and inspects jobs; related workflow changes may affect these tests. [::nold-ai/specfact-cli::tests/unit/workflows/test_trustworthy_green_checks.py]

  • docs (multiple) — docs/guides/module-signing-and-key-rotation.md, docs/reference/module-security.md, docs/module-system/module-marketplace.md, docs/guides/publishing-modules.md, docs/agent-rules/50-quality-gates-and-review.md all reference verifier/signing commands and the expectation of --require-signature; documentation should be reviewed to ensure wording matches branch-aware behavior. [::nold-ai/specfact-cli::docs/guides/module-signing-and-key-rotation.md] [::nold-ai/specfact-cli::docs/reference/module-security.md] [::nold-ai/specfact-cli::docs/module-system/module-marketplace.md] [::nold-ai/specfact-cli::docs/guides/publishing-modules.md] [::nold-ai/specfact-cli::docs/agent-rules/50-quality-gates-and-review.md]

Implication summary:

  • The core CLI repo already exposes the required signer/verifier flags; workflows and docs/tests in this repo assert always-present --require-signature in places — those tests/docs will need updating or are already covered by paired PR changes to expect conditional/appended --require-signature behavior. [::nold-ai/specfact-cli::]
🔇 Additional comments (11)
openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md (2)

5-7: Red-state evidence still incomplete.

The TDD evidence acknowledges the Red phase wasn't captured. While the implicit failure (missing file causing test failure) is understood, capturing actual failing output strengthens the audit trail per the TDD order guideline.


9-44: Green-state evidence is thorough.

The verification commands cover workflow tests, contract tests, linting, YAML validation, actionlint, and the SpecFact code review gate. The PR review follow-up notes at Lines 31–35 helpfully document the rationale for same-repo gating and merge-base computation.

openspec/changes/marketplace-06-ci-module-signing/specs/ci-module-signing-on-approval/spec.md (1)

16-17: Spec accurately reflects merge-base and fork-exclusion implementation.

The specification changes align with the workflow implementation:

  • Merge-base logic at Lines 16–17 and 26–27 matches the workflow's git merge-base HEAD "origin/${PR_BASE_REF}" computation (see .github/workflows/sign-modules-on-approval.yml:64).
  • Fork exclusion scenario at Lines 43–48 matches the job condition github.event.pull_request.head.repo.full_name == github.repository.

This ensures the spec serves as a reliable contract for the signing boundary between bundled modules and CI infrastructure.

Also applies to: 26-27, 43-48

tests/unit/workflows/test_pr_orchestrator_signing.py (1)

19-23: Branch-guard sequencing assertion addresses prior feedback.

The sequence check at Line 23 (workflow.index(branch_guard) < workflow.index(require_append)) ensures --require-signature is guarded by the main branch conditional. This directly addresses the prior review suggestion about validating the conditional block structure.

.github/workflows/sign-modules-on-approval.yml (3)

1-27: Workflow structure follows security and CI best practices.

Key security measures are well-implemented:

  • Same-repo guard (Line 20) prevents unauthorized fork pushes
  • Concurrency group (Lines 8–10) prevents race conditions on same PR
  • permissions: contents: write (Lines 12–13) is appropriately minimal
  • Secrets are guarded early (Lines 28–34) with clear error messaging

This maintains the trust model where signatures are enforced at main while feature branches rely on CI signing.


65-69: Signing flags align with core repo script interface.

The invocation matches the sign-modules.py argument parser in the linked nold-ai/specfact-cli repository:

  • --changed-only + --base-ref "$MERGE_BASE" for PR-scoped manifest selection
  • --bump-version patch for auto-incrementing unchanged versions
  • --payload-from-filesystem for checksum consistency with install verification

This maintains contract alignment between the modules repo CI and the core CLI signing implementation.


82-82: git add -u -- packages/ is appropriate here.

The signing workflow discovers existing module-package.yaml files and updates their integrity field and version (if bumped). Since sign-modules.py only modifies existing manifests and never creates new ones, git add -u correctly stages the tracked file modifications without including untracked files.

openspec/changes/marketplace-06-ci-module-signing/tasks.md (2)

45-50: Task 4.5 correctly documents the signing step implementation.

The task now accurately describes:

  • Merge-base computation for PR-scoped deltas
  • --changed-only --base-ref "$MERGE_BASE" --bump-version patch --payload-from-filesystem
  • Explicit note that --allow-same-version is not used

This addresses the prior review feedback about the discrepancy between task documentation and actual implementation.


29-31: Pre-commit wrapper task aligns with implementation.

Task 3.5 correctly documents the scripts/pre-commit-verify-modules-signature.sh wrapper that conditionally applies --require-signature based on branch (main via git rev-parse or GITHUB_REF_NAME). This maintains parity between local pre-commit hooks and CI verification gates.

tests/unit/workflows/test_sign_modules_on_approval.py (2)

45-61: Secret guard assertions address prior review feedback.

Lines 47–49 now explicitly verify:

  • The guard step exists ("Guard signing secrets")
  • The empty-check pattern ('[ -z "${SPECFACT_MODULE_PRIVATE_SIGN_KEY:-}" ]')
  • The failure exit ("exit 1")

This ensures the guard step (not just env vars) is validated, addressing the prior suggestion.


9-11: Helper function reduces duplication across tests.

The _workflow_text() helper cleanly encapsulates the file read, and REPO_ROOT calculation is consistent with test_pr_orchestrator_signing.py. Good pattern for workflow contract tests.

Comment thread tests/unit/workflows/test_sign_modules_on_approval.py
…t GITHUB_BASE_REF

- Extend test_sign_modules_on_approval_trigger_and_job_filter for concurrency
  group + cancel-in-progress and contents: write.
- Use GITHUB_BASE_REF (PR target) in pre-commit-verify-modules-signature.sh;
  update specs, TDD evidence, and script tests accordingly.

Made-with: Cursor
Copy link
Copy Markdown

@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: 4

🤖 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/marketplace-06-ci-module-signing/specs/ci-integration/spec.md`:
- Around line 38-53: This change introduces a cross-repo contract requiring the
pre-commit hook (verify-modules-signature.py) to mirror the CI job behavior
(verify-module-signatures) around the --require-signature flag and branch
detection; before merging, coordinate and wait for the paired core-repo change
nold-ai/specfact-cli#500 to land, then update this spec to reference the new
core behavior and adjust any workflow/test/docs that rely on
GITHUB_BASE_REF/main detection and adapter-boundary semantics so
verify-modules-signature.py, the CI job verify-module-signatures, and related
docs/tests remain consistent.

In `@openspec/changes/marketplace-06-ci-module-signing/tasks.md`:
- Around line 72-73: Update the checklist item "6.2 Link the PR to the GitHub
issue..." to require explicit parity validation in the paired repo
(nold-ai/specfact-cli) before marking done: require the specfact-cli PR link
plus a confirmation that its CI/workflows/tests/docs have been updated and
passed (parity validation status), and require the PR body to state the parity
check passed (e.g., "parity: confirmed") before closing the marketplace/core PR
so module signature policy and shared workflow semantics cannot drift.

In `@tests/unit/workflows/test_sign_modules_on_approval.py`:
- Around line 51-65: The test is missing an explicit assertion that the
passphrase-empty shell guard is present; add an assertion mirroring the
private-key guard such as asserting the string '[ -z
"${SPECFACT_MODULE_PRIVATE_SIGN_KEY_PASSPHRASE:-}" ]' exists in the generated
workflow (in the test_sign_modules_on_approval.py assertions alongside the
existing SPECFACT_MODULE_PRIVATE_SIGN_KEY guard and the "exit 1" check) so the
fail-fast behavior for the passphrase is validated.
- Around line 14-27: The test_sign_modules_on_approval_trigger_and_job_filter
test currently uses loose token checks; update it to assert exact trigger and
filter blocks returned by _workflow_text() to enforce the approval-only
contract: check for the full pull_request trigger block including types:
[submitted], the exact conditional "if: github.event.review.state == 'approved'
&& (github.event.pull_request.base.ref == 'dev' ||
github.event.pull_request.base.ref == 'main')" (or equivalent exact string used
in the workflow), the repo equality
"github.event.pull_request.head.repo.full_name == github.repository", and exact
concurrency/permissions lines ("concurrency:\n  cancel-in-progress: true" and
"permissions:\n  contents: write") instead of token-level checks; locate these
assertions in test_sign_modules_on_approval_trigger_and_job_filter and replace
the loose contains assertions with equality/substring assertions that match the
full expected snippets produced by _workflow_text().
🪄 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: 63ae8aef-c994-4acd-ba91-c05c0ac2039d

📥 Commits

Reviewing files that changed from the base of the PR and between 9b9ecf9 and f513a39.

📒 Files selected for processing (10)
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/design.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
  • openspec/config.yaml
  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • scripts/pre-commit-verify-modules-signature.sh
  • tests/unit/test_pre_commit_verify_modules_signature_script.py
  • tests/unit/workflows/test_sign_modules_on_approval.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). (3)
  • GitHub Check: quality (3.13)
  • GitHub Check: quality (3.12)
  • GitHub Check: quality (3.11)
🧰 Additional context used
📓 Path-based instructions (5)
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/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/design.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
docs/agent-rules/**/*.md

📄 CodeRabbit inference engine (.cursorrules)

Load docs/agent-rules/INDEX.md and canonical rule files selected by its applicability matrix

Files:

  • docs/agent-rules/50-quality-gates-and-review.md
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/agent-rules/50-quality-gates-and-review.md
**/*.{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/test_pre_commit_verify_modules_signature_script.py
  • tests/unit/workflows/test_sign_modules_on_approval.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/test_pre_commit_verify_modules_signature_script.py
  • tests/unit/workflows/test_sign_modules_on_approval.py
🧠 Learnings (15)
📓 Common learnings
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:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Enforce module signatures and version bumps when signed module assets or manifests are affected
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.842Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json
📚 Learning: 2026-04-02T21:49:11.371Z
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:11.371Z
Learning: In nold-ai/specfact-cli-modules, module tarball signatures (registry/signatures/*.tar.sig) are generated by the `publish-modules` GitHub Actions runner during the publish workflow, not committed locally to the branch. Missing signature files should NOT be flagged as a pre-merge blocker in PRs.

Applied to files:

  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/design.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • scripts/pre-commit-verify-modules-signature.sh
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • tests/unit/workflows/test_sign_modules_on_approval.py
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Enforce module signatures and version bumps when signed module assets or manifests are affected

Applied to files:

  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/design.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • scripts/pre-commit-verify-modules-signature.sh
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Signed module or manifest changes require version-bump review and verify-modules-signature

Applied to files:

  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/design.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • scripts/pre-commit-verify-modules-signature.sh
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:29.379Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics

Applied to files:

  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:15.842Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .cursorrules:0-0
Timestamp: 2026-04-13T10:38:15.842Z
Learning: Adhere to worktree policy, OpenSpec gating, GitHub hierarchy-cache refresh, TDD order, quality gates, versioning, and documentation rules as defined in `docs/agent-rules/`

Applied to files:

  • openspec/specs/modules-pre-commit-quality-parity/spec.md
  • openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md
  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Do not implement from the `dev` or `main` checkout by default

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/design.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Detect repository root, active branch, and worktree state before proceeding with implementation

Applied to files:

  • scripts/pre-commit-verify-modules-signature.sh
📚 Learning: 2026-04-13T10:38:29.379Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-13T10:38:29.379Z
Learning: Treat canonical rule docs (docs/agent-rules/INDEX.md) as the source of truth for worktree policy, OpenSpec gating, GitHub completeness checks, TDD order, quality gates, versioning, and documentation rules

Applied to files:

  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Full governance rules live in docs/agent-rules/; do not treat this file (GitHub Copilot Instructions) as a complete standalone handbook

Applied to files:

  • docs/agent-rules/50-quality-gates-and-review.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: This repository enforces the clean-code review gate through hatch run specfact code review run --json --out .specfact/code-review.json

Applied to files:

  • docs/agent-rules/50-quality-gates-and-review.md
  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
📚 Learning: 2026-04-13T10:38:22.837Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-13T10:38:22.837Z
Learning: Work belongs on feature/*, bugfix/*, hotfix/*, or chore/* branches, normally in a worktree rooted under ../specfact-cli-modules-worktrees/

Applied to files:

  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Run the required verification and quality gates for the touched scope before finalization

Applied to files:

  • openspec/config.yaml
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Perform `spec -> tests -> failing evidence -> code -> passing evidence` in that order for behavior changes

Applied to files:

  • openspec/config.yaml
  • openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md
  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
📚 Learning: 2026-04-13T10:38:43.524Z
Learnt from: CR
Repo: nold-ai/specfact-cli-modules PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-13T10:38:43.524Z
Learning: Require public GitHub metadata completeness before implementation when linked issue workflow applies: parent, labels, project assignment, blockers, and blocked-by relationships

Applied to files:

  • openspec/changes/marketplace-06-ci-module-signing/tasks.md
🪛 LanguageTool
openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md

[uncategorized] ~4-~4: The official name of this software platform is spelled with a capital “H”.
Context: ...ow tests → Red evidence → implement .github/workflows/sign-modules-on-approval.yml...

(GITHUB)


[uncategorized] ~8-~8: The official name of this software platform is spelled with a capital “H”.
Context: ...t_sign_modules_on_approval.py(expects.github/workflows/sign-modules-on-approval.yml`...

(GITHUB)


[uncategorized] ~62-~62: The official name of this software platform is spelled with a capital “H”.
Context: ...l) - Same-repo PRs only: job if adds `github.event.pull_request.head.repo.full_name ...

(GITHUB)

openspec/changes/marketplace-06-ci-module-signing/tasks.md

[uncategorized] ~21-~21: The official name of this software platform is spelled with a capital “H”.
Context: ...t verify by target branch - [x] 3.1 In .github/workflows/pr-orchestrator.yml, in the ...

(GITHUB)


[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ...job, extract the target branch fromgithub.event.pull_request.base.ref` (PR events...

(GITHUB)


[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ....pull_request.base.ref(PR events) andgithub.ref` (push events). - [x] 3.2 For eve...

(GITHUB)


[uncategorized] ~36-~36: The official name of this software platform is spelled with a capital “H”.
Context: ...dules-on-approval.yml - [x] 4.1 Create .github/workflows/sign-modules-on-approval.yml...

(GITHUB)


[uncategorized] ~38-~38: The official name of this software platform is spelled with a capital “H”.
Context: ...roved review, base dev or main, and `github.event.pull_request.head.repo.full_name ...

(GITHUB)

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

Findings for nold-ai/specfact-cli

  • Workflow that currently invokes verifier with always-present --require-signature:

    • .github/workflows/pr-orchestrator.yml — Verify Module Signatures step: runs python scripts/verify-modules-signature.py --require-signature ... [::nold-ai/specfact-cli::.github/workflows/pr-orchestrator.yml: Verify bundled module checksums and signatures step]
  • Separate workflow also assumes --require-signature is always used:

    • .github/workflows/Module Signature Hardening.yml — Verify bundled module signatures step uses --require-signature [::nold-ai/specfact-cli::.github/workflows/Module Signature Hardening.yml: Verify bundled module signatures step]
    • .github/workflows/sign-modules.yml — contains conditional invocations that include --require-signature in multiple branches (lines referencing --version-check-base and fallback) [::nold-ai/specfact-cli::.github/workflows/sign-modules.yml]
  • Tests that assert workflow/scripts include a literal "--require-signature" (will be sensitive to making the flag conditional):

    • tests/unit/specfact_cli/registry/test_signing_artifacts.py — asserts presence of "verify-modules-signature.py --require-signature" in workflow content [::nold-ai/specfact-cli::tests/unit/specfact_cli/registry/test_signing_artifacts.py:~508]
    • tests/unit/workflows/test_trustworthy_green_checks.py — references SIGN_MODULES = .github/workflows/sign-modules.yml and inspects sign workflow jobs (may assume current behavior) [::nold-ai/specfact-cli::tests/unit/workflows/test_trustworthy_green_checks.py:15,163]
  • Scripts and docs referencing always-required signature behavior (may need wording updates to reflect branch-aware policy):

    • scripts/pre-commit-smart-checks.sh — runs hatch run ./scripts/verify-modules-signature.py --require-signature --enforce-version-bump [::nold-ai/specfact-cli::scripts/pre-commit-smart-checks.sh]
    • scripts/setup-git-hooks.sh — documents hatch run ./scripts/verify-modules-signature.py --require-signature [::nold-ai/specfact-cli::scripts/setup-git-hooks.sh]
    • docs and openspec entries with multiple references to hatch run ./scripts/verify-modules-signature.py --require-signature (e.g., docs/guides/module-signing-and-key-rotation.md, openspec/specs/*) [::nold-ai/specfact-cli::docs/guides/module-signing-and-key-rotation.md] [::nold-ai/specfact-cli::openspec/**]
  • Signer/verifier implementations support the flags used by the new workflows:

    • scripts/verify-modules-signature.py — supports --payload-from-filesystem, --enforce-version-bump, --require-signature, --version-check-base [::nold-ai/specfact-cli::scripts/verify-modules-signature.py]
    • scripts/sign-modules.py — supports --changed-only, --base-ref, --bump-version, --payload-from-filesystem [::nold-ai/specfact-cli::scripts/sign-modules.py]

Implication: Tests and documentation in this repo expect literal --require-signature usage; making the flag conditional (as in the modules-repo PR) will require updating tests/docs/workflow assertions here (or ensuring workflows are updated in this repo to match branch-aware behavior). Also, existing workflows in this repo still invoke --require-signature unconditionally and may need alignment with the branch-aware wrapper and sign-on-approval workflow introduced in the PR under review.

🔇 Additional comments (9)
scripts/pre-commit-verify-modules-signature.sh (1)

9-23: Branch-aware signature gate wiring looks correct.

The wrapper cleanly mirrors CI policy: checksum/version-bump verification always runs, and --require-signature is injected only when target branch resolves to main.

openspec/specs/modules-pre-commit-quality-parity/spec.md (1)

8-16: Spec update is consistent with implemented signing trust boundaries.

The requirement/scenario wording correctly captures checksum+version enforcement on all branches and signature enforcement at the main boundary.

openspec/config.yaml (1)

32-35: Quality-gate context is accurately synchronized with the new pre-commit flow.

The ordering and main-boundary signature rule are documented clearly and match the workflow intent.

docs/agent-rules/50-quality-gates-and-review.md (1)

46-54: Rule documentation now matches the enforced policy.

Good update: the quality gate and pre-commit sections now describe conditional signature enforcement at the main boundary instead of unconditional enforcement.

openspec/changes/marketplace-06-ci-module-signing/design.md (1)

16-19: Design deltas are coherent with the implemented branch-aware trust model.

The wrapper behavior and non-goal clarification correctly preserve dev-branch flow while keeping signature enforcement at the main boundary.

Also applies to: 33-34

tests/unit/test_pre_commit_verify_modules_signature_script.py (1)

20-27: Nice hardening of policy-contract coverage.

The test now verifies --require-signature is scoped to the true branch and absent from the false path, which is the critical behavior contract.

openspec/changes/marketplace-06-ci-module-signing/TDD_EVIDENCE.md (1)

12-36: Red-state evidence is now concrete and auditable.

Including the failing command/output excerpt before green runs makes the TDD chain verifiable for this workflow behavior change.

openspec/changes/marketplace-06-ci-module-signing/tasks.md (1)

3-71: Checklist progression matches the implemented CI/signing design.

The completed items align with the branch-aware verify/signing flow and test evidence expectations.

tests/unit/workflows/test_sign_modules_on_approval.py (1)

29-47: Coverage for checkout/setup, discovery outputs, and write-back summary looks solid.

These assertions capture the critical CI behavior for signing execution and reporting.

Also applies to: 68-76

Comment on lines +38 to +53
### Requirement: pre-commit verify mirrors pr-orchestrator signature policy

The repository pre-commit hook that runs `verify-modules-signature.py` SHALL apply the same branch rule as the `verify-module-signatures` CI job: omit `--require-signature` unless the integration target is `main` (local branch `main`, or `GITHUB_BASE_REF=main` on pull request events in Actions).

#### Scenario: Commit on a feature branch without a signing key

- **WHEN** a developer commits on a branch other than `main`
- **AND** manifests satisfy checksum and version-bump policy but lack a valid signature
- **THEN** the pre-commit signature hook SHALL pass (no `--require-signature`)
- **AND** the developer SHALL remain unblocked until a `main`-targeting flow enforces signatures in CI

#### Scenario: Commit on main requires signatures

- **WHEN** a developer commits on branch `main`
- **AND** any `packages/*/module-package.yaml` lacks a valid signature under `--require-signature`
- **THEN** the pre-commit signature hook SHALL fail
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Coordinate merge timing with the paired core-repo policy change.

This requirement defines a cross-repo contract (“pre-commit/CI mirror policy”). Before rollout, confirm nold-ai/specfact-cli#500 lands with its related workflow/test/docs updates so adapter-boundary semantics don’t drift between modules and core.

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

In
`@openspec/changes/marketplace-06-ci-module-signing/specs/ci-integration/spec.md`
around lines 38 - 53, This change introduces a cross-repo contract requiring the
pre-commit hook (verify-modules-signature.py) to mirror the CI job behavior
(verify-module-signatures) around the --require-signature flag and branch
detection; before merging, coordinate and wait for the paired core-repo change
nold-ai/specfact-cli#500 to land, then update this spec to reference the new
core behavior and adjust any workflow/test/docs that rely on
GITHUB_BASE_REF/main detection and adapter-boundary semantics so
verify-modules-signature.py, the CI job verify-module-signatures, and related
docs/tests remain consistent.

Comment on lines +72 to +73
- [x] 6.2 Link the PR to the GitHub issue created in 1.2 and to the paired specfact-cli PR.
*(Closes #185 in PR body; link specfact-cli PR manually when it exists.)*
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make paired-core parity an explicit done-criterion before closing.

Line 72–73 is marked done, but it still frames the paired specfact-cli link as manual/future. For a trust-model contract change, this should explicitly require parity validation status in nold-ai/specfact-cli (workflows/tests/docs), otherwise modules/core can drift on signature policy.

🛠️ Suggested task-text adjustment
-- [x] 6.2 Link the PR to the GitHub issue created in 1.2 and to the paired specfact-cli PR.
-  *(Closes `#185` in PR body; link specfact-cli PR manually when it exists.)*
+- [x] 6.2 Link the PR to the GitHub issue created in 1.2 and to the paired specfact-cli PR,
+  and record parity status for branch-aware signature policy in core workflows/tests/docs.
+  *(Closes `#185` in PR body; paired core PR: `#500`.)*

Based on learnings: “When a change is paired with work in specfact-cli, review the paired public change artifacts there before widening scope or redefining shared workflow semantics.”

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

In `@openspec/changes/marketplace-06-ci-module-signing/tasks.md` around lines 72 -
73, Update the checklist item "6.2 Link the PR to the GitHub issue..." to
require explicit parity validation in the paired repo (nold-ai/specfact-cli)
before marking done: require the specfact-cli PR link plus a confirmation that
its CI/workflows/tests/docs have been updated and passed (parity validation
status), and require the PR body to state the parity check passed (e.g.,
"parity: confirmed") before closing the marketplace/core PR so module signature
policy and shared workflow semantics cannot drift.

Comment on lines +14 to +27
def test_sign_modules_on_approval_trigger_and_job_filter() -> None:
workflow = _workflow_text()
assert "pull_request_review:" in workflow
assert "types:" in workflow
assert "submitted" in workflow
assert "github.event.review.state == 'approved'" in workflow
assert "github.event.pull_request.base.ref == 'dev'" in workflow
assert "github.event.pull_request.base.ref == 'main'" in workflow
assert "github.event.pull_request.head.repo.full_name == github.repository" in workflow
assert "concurrency:" in workflow
assert "cancel-in-progress: true" in workflow
assert "permissions:" in workflow
assert "contents: write" in workflow

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Harden trigger/filter assertions to enforce exact workflow contract.

Current checks are token-level ("types:", "submitted"), so the test can still pass if extra review types or broader conditions are introduced. Tighten this to exact contract strings for the approval gate.

🧪 Suggested assertion tightening
-    assert "types:" in workflow
-    assert "submitted" in workflow
+    assert "types: [submitted]" in workflow
+    assert "github.event.review.state == 'approved'" in workflow
+    assert "(github.event.pull_request.base.ref == 'dev' || github.event.pull_request.base.ref == 'main')" in workflow

As per coding guidelines: “tests/**/*.py: Contract-first and integration tests... Ensure changes to adapters or bridges have targeted coverage.”

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

In `@tests/unit/workflows/test_sign_modules_on_approval.py` around lines 14 - 27,
The test_sign_modules_on_approval_trigger_and_job_filter test currently uses
loose token checks; update it to assert exact trigger and filter blocks returned
by _workflow_text() to enforce the approval-only contract: check for the full
pull_request trigger block including types: [submitted], the exact conditional
"if: github.event.review.state == 'approved' &&
(github.event.pull_request.base.ref == 'dev' ||
github.event.pull_request.base.ref == 'main')" (or equivalent exact string used
in the workflow), the repo equality
"github.event.pull_request.head.repo.full_name == github.repository", and exact
concurrency/permissions lines ("concurrency:\n  cancel-in-progress: true" and
"permissions:\n  contents: write") instead of token-level checks; locate these
assertions in test_sign_modules_on_approval_trigger_and_job_filter and replace
the loose contains assertions with equality/substring assertions that match the
full expected snippets produced by _workflow_text().

Comment on lines +51 to +65
assert "Guard signing secrets" in workflow
assert '[ -z "${SPECFACT_MODULE_PRIVATE_SIGN_KEY:-}" ]' in workflow
assert "exit 1" in workflow
assert "MERGE_BASE=" in workflow
assert "git merge-base HEAD" in workflow
assert 'git fetch origin "${PR_BASE_REF}"' in workflow
assert "--no-tags" in workflow
assert "scripts/sign-modules.py" in workflow
assert "--changed-only" in workflow
assert "--base-ref" in workflow
assert '"$MERGE_BASE"' in workflow
assert "--bump-version patch" in workflow
assert "--payload-from-filesystem" in workflow
assert "SPECFACT_MODULE_PRIVATE_SIGN_KEY" in workflow
assert "SPECFACT_MODULE_PRIVATE_SIGN_KEY_PASSPHRASE" in workflow
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add an explicit assertion for passphrase-empty guard behavior.

The test validates key-empty guard logic, but it does not explicitly assert the passphrase-empty shell guard expression. Presence of the variable name alone is weaker than asserting the fail-fast check.

🔐 Suggested assertion addition
     assert '[ -z "${SPECFACT_MODULE_PRIVATE_SIGN_KEY:-}" ]' in workflow
+    assert '[ -z "${SPECFACT_MODULE_PRIVATE_SIGN_KEY_PASSPHRASE:-}" ]' in workflow
     assert "exit 1" in workflow

As per coding guidelines: “tests/**/*.py: Contract-first and integration tests... Ensure changes to adapters or bridges have targeted coverage.”

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

In `@tests/unit/workflows/test_sign_modules_on_approval.py` around lines 51 - 65,
The test is missing an explicit assertion that the passphrase-empty shell guard
is present; add an assertion mirroring the private-key guard such as asserting
the string '[ -z "${SPECFACT_MODULE_PRIVATE_SIGN_KEY_PASSPHRASE:-}" ]' exists in
the generated workflow (in the test_sign_modules_on_approval.py assertions
alongside the existing SPECFACT_MODULE_PRIVATE_SIGN_KEY guard and the "exit 1"
check) so the fail-fast behavior for the passphrase is validated.

@djm81 djm81 merged commit f9d13c6 into dev Apr 14, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

architecture Architecture-related topic dependencies Pull requests that update a dependency file enhancement New feature or request marketplace Specfact Marketplace related topic module Specfact Module related topic

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Change] CI-Driven Module Signing On PR Approval

2 participants