Skip to content

fix: address all Copilot feedback from PR #1236#1237

Closed
jpoley wants to merge 8 commits into
mainfrom
fix/pr-1236-copilot-fixes
Closed

fix: address all Copilot feedback from PR #1236#1237
jpoley wants to merge 8 commits into
mainfrom
fix/pr-1236-copilot-fixes

Conversation

@jpoley

@jpoley jpoley commented Apr 5, 2026

Copy link
Copy Markdown
Owner

Summary

Rebased from closed PR #1236 (feat/all-issues-combined) with all Copilot review feedback addressed:

Closes #1221 #1222 #1223 #1224 #1225 #1226

Test plan

  • uv run ruff check . — all checks passed
  • uv run ruff format --check . — all files formatted
  • uv run pytest tests/ -x -q — 3535 passed, 42 skipped, 0 failures

🤖 Generated with Claude Code

jpoley and others added 8 commits April 3, 2026 11:23
Implements flowspec doctor command that checks environment setup and
surfaces configuration problems with clear fix instructions.

Checks performed:
- flowspec CLI version
- Python version compatibility (requires 3.11+)
- Required tools installed (backlog.md, beads)
- Workflow configuration present and valid
- Agent files using correct naming convention (dot notation)
- Constitution file present

Features:
- Color-coded output (✅ pass, ⚠️ warn, ❌ fail)
- Suggested fix commands for each issue
- --verbose flag for detailed diagnostics
- --fix flag stub for future auto-fix functionality

Closes #1221

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Implement GPG commit signing for Flowspec agents:

1. Created src/flowspec_cli/signing.py:
   - generate_agent_key(): Generate 4096-bit RSA GPG key for agents
   - configure_git_signing(): Set user.signingkey and commit.gpgsign=true
   - get_key_fingerprint(): Return stored fingerprint from keyring
   - key_exists(): Check if key already exists
   - delete_agent_key(): Support key rotation

2. Added CLI subcommands via src/flowspec_cli/gpg_cli.py:
   - flowspec gpg setup: Generate key and configure git signing
   - flowspec gpg status: Show key and signing configuration status
   - flowspec gpg rotate: Delete old key and generate new one

3. Integrated fingerprint into telemetry output:
   - flowspec telemetry status shows GPG fingerprint when signing is active
   - Provides audit trail of agent commit signatures

4. Documentation in docs/guides/gpg-signing.md:
   - Key management best practices
   - Key rotation workflow and schedule recommendations
   - Troubleshooting guide
   - GitHub/GitLab integration instructions

5. Comprehensive test coverage in tests/test_signing.py:
   - Key generation, configuration, retrieval, and deletion
   - Error handling and edge cases
   - Git command integration tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Extract fingerprint from key-creation status output ([GNUPG:] KEY_CREATED)
instead of post-hoc --list-keys lookup, which could match the wrong key
if multiple keys share the same email. Addresses remaining Copilot
feedback from PR #1236.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: jason poley <jason.poley@gmail.com>
Copilot AI review requested due to automatic review settings April 5, 2026 21:24
@github-actions github-actions Bot added documentation Improvements or additions to documentation config github source tests labels Apr 5, 2026
@github-actions

github-actions Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

🟢 Security Scan Results (Advisory)

Note: Security scanning is advisory and does not block PR merges.

  • Total Findings: 11
  • Critical: 0
  • High: 0

No critical or high severity issues found.

How to remediate
# View detailed scan results
gh run download 24010794072 -n security-scan-results-ffbd7f667f38dfd1f3882d795784efab0f464dd0

# Triage findings with AI assistance
specify security triage

# Generate fix suggestions
specify security fix

# Apply fixes and re-scan
flowspec security scan

See the Security tab for detailed findings.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR rebases and refactors the “doctor” diagnostics and agent GPG signing work from PR #1236, aiming to incorporate prior review feedback (notably around safer GPG fingerprint extraction and improved checks/tests).

Changes:

  • Adds a GPG signing implementation (signing.py) plus a Typer sub-app for flowspec gpg ... management commands.
  • Adds a doctor health-check implementation and unit tests.
  • Adds end-user documentation for agent GPG signing.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/flowspec_cli/signing.py Implements GPG key generation/storage and git signing configuration helpers.
src/flowspec_cli/gpg_cli.py Defines Typer gpg subcommands (setup/status/rotate) around the signing helpers.
src/flowspec_cli/doctor.py Implements environment checks (version/tools/config/agents/constitution) and formatted output.
tests/test_signing.py Unit tests for signing helper behavior and command execution errors.
tests/test_doctor.py Unit tests for doctor checks and run_all_checks().
docs/guides/gpg-signing.md User guide describing how to set up and use agent commit signing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +175 to +177
# Verify the secret key is still present in the GPG keyring
_, _, returncode = _run_gpg_command(["--list-secret-keys", GPG_KEY_EMAIL])
if returncode != 0:

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

configure_git_signing() verifies secret-key presence by listing keys for GPG_KEY_EMAIL, but then configures git with the stored fingerprint. If the stored fingerprint key was deleted (or multiple secret keys share the email), this check can pass while git is configured with a non-existent key, causing signing failures. Verify secret key existence by the stored fingerprint (e.g., gpg --list-secret-keys <fingerprint> / parse --with-colons for the fingerprint) instead of by email.

Suggested change
# Verify the secret key is still present in the GPG keyring
_, _, returncode = _run_gpg_command(["--list-secret-keys", GPG_KEY_EMAIL])
if returncode != 0:
# Verify the exact secret key fingerprint is still present in the GPG keyring
stdout, _, returncode = _run_gpg_command(
["--list-secret-keys", "--with-colons", fingerprint]
)
fingerprint_found = any(
line.startswith("fpr:") and line.split(":")[9] == fingerprint
for line in stdout.splitlines()
)
if returncode != 0 or not fingerprint_found:

Copilot uses AI. Check for mistakes.
Comment on lines +236 to +241
stdout, stderr, returncode = _run_gpg_command(
["--list-keys", "--with-colons", fingerprint]
)

if returncode != 0:
return None

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

get_key_info() assigns stderr from _run_gpg_command() but never uses it. With Ruff's default rules (F841), this is a lint failure. Rename it to _ or incorporate stderr into the non-zero return handling.

Copilot uses AI. Check for mistakes.
Comment on lines +264 to +315
def check_agent_files() -> CheckResult:
"""Check if agent files use correct naming convention.

Only checks .github/agents/ for flow.*.agent.md vs flow-*.agent.md patterns.
Note: .claude/agents/ intentionally uses hyphens and is not checked.

Returns:
CheckResult indicating agent file naming status
"""
project_root = Path.cwd()
github_agents_dir = project_root / ".github" / "agents"

old_convention_files = []

if github_agents_dir.exists():
for agent_file in github_agents_dir.glob("*.md"):
stem = agent_file.stem
# Skip README and underscore-prefixed files
if stem.startswith("_") or agent_file.name == "README.md":
continue
# Hyphenated names are old convention; dot-separated are new
if "-" in stem:
old_convention_files.append(str(agent_file.relative_to(project_root)))

if old_convention_files:
return CheckResult(
name="Agent file naming",
status=CheckStatus.WARN,
message=f"{len(old_convention_files)} files using old hyphen naming",
fix_command="Run: flowspec upgrade-repo",
details={"files": old_convention_files},
)

# Check if there are any agent files at all in .github/agents/
has_agents = github_agents_dir.exists() and any(
f.suffix == ".md"
for f in github_agents_dir.glob("*.md")
if not f.name.startswith("_") and f.name != "README.md"
)

if not has_agents:
return CheckResult(
name="Agent file naming",
status=CheckStatus.WARN,
message="No agent files found in .github/agents/",
)

return CheckResult(
name="Agent file naming",
status=CheckStatus.PASS,
message="Using flow. prefix convention",
)

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

check_agent_files() currently treats any .md filename without a hyphen as compliant, which would incorrectly PASS files like backend.engineer.md even though the stated convention is flow.*.agent.md in .github/agents/. Consider explicitly validating the expected pattern (starts with flow. and ends with .agent.md) and WARN/FAIL on other non-special files.

Copilot uses AI. Check for mistakes.
Comment thread tests/test_doctor.py
Comment on lines +22 to +28
def test_returns_version(self):
"""Should return current flowspec version."""
result = check_flowspec_version()
assert result.name == "flowspec CLI"
assert result.status == CheckStatus.PASS
assert "v" in result.message or result.message == "unknown"

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

These tests call check_flowspec_version() / run_all_checks() without mocking the PyPI httpx.get request, which can introduce network dependency and slow/flaky CI (5s timeout per call when offline). Patch flowspec_cli.doctor.httpx.get (or check_flowspec_version internals) to return a deterministic response in tests.

Copilot uses AI. Check for mistakes.
Comment thread tests/test_doctor.py
Comment on lines +214 to +225
def test_skips_special_files(self, tmp_path, monkeypatch):
"""Should skip README and underscore-prefixed files."""
monkeypatch.chdir(tmp_path)
agents_dir = tmp_path / ".github" / "agents"
agents_dir.mkdir(parents=True)
(agents_dir / "README.md").write_text("# README")
(agents_dir / "_template.md").write_text("# Template")
(agents_dir / "backend.engineer.md").write_text("# Backend Engineer")

result = check_agent_files()
assert result.status == CheckStatus.PASS

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

The agent naming tests expect backend.engineer.md (dot-separated but not flow.*.agent.md) to PASS. This conflicts with the documented/actual .github/agents convention (flow.<phase>.agent.md) and would hide misnamed files. Adjust tests (and likely check_agent_files) to treat non-flow.*.agent.md files as WARN/FAIL unless explicitly allowed.

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +36
gpg_app = typer.Typer(
name="gpg",
help="Manage agent GPG commit signing",
add_completion=False,
)

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

gpg_app is defined here, but there’s no evidence it’s registered with the main Typer app (no app.add_typer(gpg_app, name="gpg") found in flowspec_cli/__init__.py). As-is, the documented flowspec gpg ... commands won’t be reachable from the CLI. Ensure the root CLI imports and adds this sub-app.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +4
This module provides the `flowspec doctor` command to verify that the environment
is properly configured for flowspec development.

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

The module docstring states it provides the flowspec doctor command, but there’s no Typer command/sub-app wiring visible from the main CLI (no references in flowspec_cli/__init__.py). Either add a Typer command/sub-app and register it, or adjust the wording to reflect that this is currently only a library function (run_doctor).

Suggested change
This module provides the `flowspec doctor` command to verify that the environment
is properly configured for flowspec development.
This module provides diagnostic helpers, including `run_doctor()`, to verify that
the environment is properly configured for flowspec development.

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +20
## Quick Start

### 1. Set Up GPG Signing

```bash
# Generate agent GPG key and configure git
flowspec gpg setup

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

This guide assumes flowspec gpg setup/status/rotate are available, but the PR doesn’t appear to register the gpg subcommand with the main CLI. Until gpg_app is added to the root Typer app, these documented commands will fail with “No such command”. Either wire the subcommand into the CLI or gate this guide behind the release that includes the wiring.

Copilot uses AI. Check for mistakes.
Comment on lines +162 to +174
When GPG signing is active, the agent's key fingerprint is included in telemetry output:

```bash
# View telemetry status with GPG info
flowspec telemetry status

# Output includes:
# ┌─ Telemetry Status ──────────┐
# │ Status Enabled │
# │ Events 1,234 │
# │ GPG Signing Active │
# │ GPG Fingerprint A1B2C3... │
# └──────────────────────────────┘

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

The “Telemetry Integration” section claims flowspec telemetry status will show “GPG Signing” / “GPG Fingerprint”, but the current telemetry status command doesn’t include any GPG fields (no references to signing module). Either implement the telemetry integration or update this section to avoid documenting behavior that isn’t present.

Suggested change
When GPG signing is active, the agent's key fingerprint is included in telemetry output:
```bash
# View telemetry status with GPG info
flowspec telemetry status
# Output includes:
# ┌─ Telemetry Status ──────────┐
# │ Status Enabled │
# │ Events 1,234 │
# │ GPG Signing Active │
# │ GPG Fingerprint A1B2C3... │
# └──────────────────────────────┘
GPG signing improves commit verification and auditability for agent-generated changes.
`flowspec telemetry status` does not currently display GPG signing state or key fingerprint information, so use the GPG-specific commands to inspect signing configuration:
```bash
# Check GPG signing status
flowspec gpg status
# Export the public key when needed
flowspec gpg export --public

Copilot uses AI. Check for mistakes.
@jpoley jpoley closed this Apr 5, 2026
jpoley added a commit that referenced this pull request Apr 5, 2026
- signing: verify secret key by fingerprint (not email) in configure_git_signing
- signing: fix unused stderr variable in get_key_info (Ruff F841)
- doctor: validate flow.*.agent.md pattern explicitly in check_agent_files
- doctor: update module docstring to reflect library function
- tests: mock httpx.get in doctor tests to prevent network dependency
- tests: fix agent naming tests to validate flow.*.agent.md convention
- cli: wire gpg_app and doctor command into main Typer app
- docs: remove false telemetry integration claims from GPG guide

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: jason poley <jason.poley@gmail.com>
jpoley added a commit that referenced this pull request Apr 5, 2026
Add doctor health-check command and GPG agent signing module with
CLI wiring, tests, and documentation. All Copilot review findings
from PRs #1236, #1237, and #1238 are resolved.

Doctor checks: CLI version, Python version, tool availability,
workflow config, agent file naming (flow.*.agent.md), constitution.

GPG signing: key generation via --status-fd, fingerprint validation
(40-char hex), secret key verification by fingerprint, git config,
key rotation, and keyring storage.

Closes #1221 #1222 #1223 #1224 #1225 #1226

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: jason poley <jason.poley@gmail.com>
jpoley added a commit that referenced this pull request Apr 5, 2026
…ixes

Add `flowspec doctor` health-check command and `flowspec gpg` agent
signing module, fully addressing all Copilot findings from PRs #1236,
#1237, #1238, and #1239 plus a thorough independent security review.

Key design decisions in signing module:
- Fingerprint normalization centralized in get_key_fingerprint()
  (strip, uppercase, 40-char hex validation, logging on failure)
- Key generation uses --status-fd for reliable fingerprint extraction
- Secret key verification uses exact fingerprint match (case-insensitive)
- All test mocks use realistic 40-char hex fingerprints via TEST_FP constant

Doctor module improvements:
- httpx imported at module level (coding standard compliance)
- Strict flow.<phase>.agent.md validation (rejects flow.agent.md)
- UTF-8 encoding on all file I/O
- Version check distinguishes "confirmed current" from "could not check"

Documentation quality:
- All GPG commands use fingerprint (not email) to avoid ambiguity
- Broken related-doc links replaced with anchor links
- Security note about ~/.gnupg file permissions added
- Manual deletion warns about keyring cleanup

Closes #1221 #1222 #1223 #1224 #1225 #1226

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: jason poley <jason.poley@gmail.com>
jpoley added a commit that referenced this pull request Apr 18, 2026
…ixes

Add `flowspec doctor` health-check command and `flowspec gpg` agent
signing module, fully addressing all Copilot findings from PRs #1236,
#1237, #1238, and #1239 plus a thorough independent security review.

Key design decisions in signing module:
- Fingerprint normalization centralized in get_key_fingerprint()
  (strip, uppercase, 40-char hex validation, logging on failure)
- Key generation uses --status-fd for reliable fingerprint extraction
- Secret key verification uses exact fingerprint match (case-insensitive)
- All test mocks use realistic 40-char hex fingerprints via TEST_FP constant

Doctor module improvements:
- httpx imported at module level (coding standard compliance)
- Strict flow.<phase>.agent.md validation (rejects flow.agent.md)
- UTF-8 encoding on all file I/O
- Version check distinguishes "confirmed current" from "could not check"

Documentation quality:
- All GPG commands use fingerprint (not email) to avoid ambiguity
- Broken related-doc links replaced with anchor links
- Security note about ~/.gnupg file permissions added
- Manual deletion warns about keyring cleanup

Closes #1221 #1222 #1223 #1224 #1225 #1226

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: jason poley <jason.poley@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

config documentation Improvements or additions to documentation github source tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: flowspec doctor — setup health check and diagnostics

2 participants