-
Notifications
You must be signed in to change notification settings - Fork 3
feat: v0.2 enhancements — LSP, multi-base diffs, directory overrides, analytics #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 22 commits
f89496b
c9a8a2a
c188b79
c41517f
8c936db
5c219f0
0c9d09f
d3e4d3a
8aaa6f0
bdac0d3
583d4ec
ccf0f41
8325454
fdd81d1
a53d5fa
31170b8
804b4ce
4b39685
d8a69f3
b8e2532
7ebce05
4cb1876
fb13941
3dd5155
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,7 @@ | ||
| # Protect repository settings | ||
| /.github/settings.yml @EffortlessSteven | ||
|
|
||
| # Conveyor templates and CI — maintain governance discipline | ||
| /.github/ISSUE_TEMPLATE/ @EffortlessSteven | ||
| /.github/PULL_REQUEST_TEMPLATE* @EffortlessSteven | ||
| /.github/workflows/ @EffortlessSteven |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| blank_issues_enabled: false | ||
| contact_links: | ||
| - name: Documentation | ||
| url: https://github.com/EffortlessMetrics/diffguard/blob/main/README.md | ||
| about: Check the README before opening an issue |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| name: Bug Report | ||
| description: Report a bug in diffguard (enters conveyor at Gate: Framed) | ||
| labels: ["gate:framed", "bug"] | ||
| body: | ||
| - type: markdown | ||
| attributes: | ||
| value: | | ||
| ## Gate: Framed — Bug Report | ||
| Bug reports enter the conveyor at Framed. Fill in the reproduction steps | ||
| and expected vs actual behavior to frame the issue. | ||
|
|
||
| - type: textarea | ||
| id: behavior | ||
| attributes: | ||
| label: Actual behavior | ||
| description: What happened? | ||
| validations: | ||
| required: true | ||
|
|
||
| - type: textarea | ||
| id: expected | ||
| attributes: | ||
| label: Expected behavior | ||
| description: What should have happened? | ||
| validations: | ||
| required: true | ||
|
|
||
| - type: textarea | ||
| id: reproduce | ||
| attributes: | ||
| label: Steps to reproduce | ||
| description: Minimal steps to trigger the bug. | ||
| placeholder: | | ||
| 1. Run `diffguard check --base main --head HEAD` | ||
| 2. ... | ||
| validations: | ||
| required: true | ||
|
|
||
| - type: input | ||
| id: version | ||
| attributes: | ||
| label: diffguard version | ||
| placeholder: "Run: cargo run -p diffguard -- --version" | ||
| validations: | ||
| required: true | ||
|
|
||
| - type: textarea | ||
| id: scope | ||
| attributes: | ||
| label: Scope | ||
| description: What's the blast radius? Which crate(s) are affected? | ||
| placeholder: | | ||
| In scope: | ||
| - Fix the root cause in ... | ||
|
|
||
| Out of scope: | ||
| - Refactoring unrelated code | ||
| validations: | ||
| required: true | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,76 @@ | ||||||
| name: Feature or Improvement | ||||||
| description: Propose a change to diffguard (enters conveyor at Gate: Framed) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # Check if the file exists and examine its content
cat -n .github/ISSUE_TEMPLATE/gate-framed.ymlRepository: EffortlessMetrics/diffguard Length of output: 2673 🏁 Script executed: # Validate the current YAML syntax to see if there's an actual parsing issue
python3 << 'EOF'
import yaml
# Test the original unquoted version
original_yaml = """description: Propose a change to diffguard (enters conveyor at Gate: Framed)"""
# Test the proposed quoted version
proposed_yaml = """description: "Propose a change to diffguard (enters conveyor at Gate: Framed)"""
print("=== Original YAML ===")
try:
result = yaml.safe_load(original_yaml)
print(f"Parsed successfully: {result}")
print(f"Type: {type(result)}, Value: {repr(result)}")
except yaml.YAMLError as e:
print(f"YAML Parse Error: {e}")
print("\n=== Proposed YAML ===")
try:
result = yaml.safe_load(proposed_yaml)
print(f"Parsed successfully: {result}")
print(f"Type: {type(result)}, Value: {repr(result)}")
except yaml.YAMLError as e:
print(f"YAML Parse Error: {e}")
EOFRepository: EffortlessMetrics/diffguard Length of output: 634 🏁 Script executed: python3 << 'EOF'
import yaml
# Test the complete YAML file as it currently exists (unquoted)
current_yaml = """name: Feature or Improvement
description: Propose a change to diffguard (enters conveyor at Gate: Framed)
labels: ["gate:framed"]"""
# Test with the proposed fix (quoted)
proposed_yaml = """name: Feature or Improvement
description: "Propose a change to diffguard (enters conveyor at Gate: Framed)"
labels: ["gate:framed"]"""
print("=== Current YAML (Unquoted) ===")
try:
result = yaml.safe_load(current_yaml)
print(f"Parsed successfully!")
print(f"Description value: {repr(result.get('description'))}")
except yaml.YAMLError as e:
print(f"YAML Parse Error: {e}")
print("\n=== Proposed YAML (Quoted) ===")
try:
result = yaml.safe_load(proposed_yaml)
print(f"Parsed successfully!")
print(f"Description value: {repr(result.get('description'))}")
except yaml.YAMLError as e:
print(f"YAML Parse Error: {e}")
EOFRepository: EffortlessMetrics/diffguard Length of output: 432 Quote the Line 2 contains an unquoted scalar with Proposed fix-description: Propose a change to diffguard (enters conveyor at Gate: Framed)
+description: "Propose a change to diffguard (enters conveyor at Gate: Framed)"📝 Committable suggestion
Suggested change
🧰 Tools🪛 YAMLlint (1.38.0)[error] 2-2: syntax error: mapping values are not allowed here (syntax) 🤖 Prompt for AI Agents |
||||||
| labels: ["gate:framed"] | ||||||
| body: | ||||||
| - type: markdown | ||||||
| attributes: | ||||||
| value: | | ||||||
| ## Gate: Framed | ||||||
| Every change starts here. Fill in the scope section to frame the problem. | ||||||
| A branch should not be created until this issue is triaged and labeled `gate:verified`. | ||||||
|
|
||||||
| - type: textarea | ||||||
| id: problem | ||||||
| attributes: | ||||||
| label: Problem | ||||||
| description: What's wrong or missing? Be specific about the current behavior and why it's insufficient. | ||||||
| placeholder: "Describe the problem with enough detail that someone unfamiliar can understand it." | ||||||
| validations: | ||||||
| required: true | ||||||
|
|
||||||
| - type: textarea | ||||||
| id: scope | ||||||
| attributes: | ||||||
| label: Scope | ||||||
| description: | | ||||||
| Bound the change. What is in scope and what is explicitly out of scope? | ||||||
| This prevents scope creep during implementation. | ||||||
| placeholder: | | ||||||
| In scope: | ||||||
| - ... | ||||||
|
|
||||||
| Out of scope: | ||||||
| - ... | ||||||
| validations: | ||||||
| required: true | ||||||
|
|
||||||
| - type: textarea | ||||||
| id: acceptance | ||||||
| attributes: | ||||||
| label: Acceptance Criteria | ||||||
| description: How do we know this is done? Be concrete — tests, behavior, output format. | ||||||
| placeholder: | | ||||||
| - [ ] ... | ||||||
| - [ ] ... | ||||||
| validations: | ||||||
| required: true | ||||||
|
|
||||||
| - type: dropdown | ||||||
| id: crate | ||||||
| attributes: | ||||||
| label: Affected crate(s) | ||||||
| options: | ||||||
| - diffguard (CLI) | ||||||
| - diffguard-core | ||||||
| - diffguard-domain | ||||||
| - diffguard-diff | ||||||
| - diffguard-types | ||||||
| - diffguard-analytics | ||||||
| - diffguard-lsp | ||||||
| - diffguard-testkit | ||||||
| - xtask | ||||||
| - Multiple / workspace | ||||||
| validations: | ||||||
| required: true | ||||||
|
|
||||||
| - type: dropdown | ||||||
| id: gate | ||||||
| attributes: | ||||||
| label: Starting gate | ||||||
| description: Where does this issue enter the conveyor? Most start at Framed. | ||||||
| options: | ||||||
| - "Framed (default)" | ||||||
| - "Verified (research already done)" | ||||||
| - "Designed (spec/tests already exist)" | ||||||
| validations: | ||||||
| required: true | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| ## Linked Issue | ||
|
|
||
| <!-- Link the issue this PR addresses. Use "Closes #N" for auto-close. --> | ||
|
|
||
| ## Description | ||
|
|
||
| <!-- What does this PR do and why? --> | ||
|
|
||
| ## Checklist | ||
|
|
||
| - [ ] Tests added or updated | ||
| - [ ] `cargo test --workspace` passes | ||
| - [ ] `cargo clippy --workspace --all-targets -- -D warnings` passes | ||
| - [ ] `cargo fmt --check` passes | ||
| - [ ] Scope matches the linked issue (no unrelated changes) | ||
|
|
||
| ## Test plan | ||
|
|
||
| <!-- How was this tested? --> | ||
|
|
||
| ## Breaking changes | ||
|
|
||
| <!-- Describe any breaking changes and migration path. Delete if none. --> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| ## Linked Issue | ||
|
|
||
| Closes #<!-- issue number --> | ||
|
|
||
| ## Gate: Designed | ||
|
|
||
| <!-- Check each box as you complete it. A reviewer should verify these. --> | ||
|
|
||
| ### Scope verification | ||
| - [ ] Scope matches the linked issue | ||
| - [ ] No out-of-scope changes included | ||
| - [ ] Affected crates listed in issue are accurate | ||
|
|
||
| ### Design | ||
| - [ ] Approach documented (inline comments, ADR, or PR description above) | ||
| - [ ] Architecture constraints respected (domain crates stay I/O-free) | ||
| - [ ] Public API changes are intentional and minimal | ||
|
|
||
| ### Gate: Proven | ||
| - [ ] Tests added or updated for the change | ||
| - [ ] `cargo test --workspace` passes | ||
| - [ ] `cargo clippy --workspace --all-targets -- -D warnings` passes | ||
| - [ ] `cargo fmt --check` passes | ||
| - [ ] Snapshot tests updated (if applicable) | ||
|
|
||
| ### Gate: Hardened | ||
| - [ ] No TODO/FIXME left in changed code | ||
| - [ ] Error messages are actionable | ||
| - [ ] No breaking changes to exit codes, receipt schema, or CLI flags (unless intentional and documented) | ||
| - [ ] Mutation testing considered for critical paths | ||
|
|
||
| ## Description | ||
|
|
||
| <!-- What does this PR do and why? Link to any design decisions. --> | ||
|
|
||
| ## Test plan | ||
|
|
||
| <!-- How was this tested? Include commands, expected output, or screenshots. --> | ||
|
|
||
| ## Breaking changes | ||
|
|
||
| <!-- If any, describe them and the migration path. Delete section if none. --> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,15 +5,85 @@ on: | |
| push: | ||
| branches: [ main ] | ||
|
|
||
| env: | ||
| CARGO_TERM_COLOR: always | ||
|
|
||
| jobs: | ||
| test: | ||
| fmt: | ||
| name: Format | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: dtolnay/rust-toolchain@stable | ||
| with: | ||
| components: rustfmt | ||
| - run: cargo fmt --check | ||
|
|
||
| clippy: | ||
| name: Clippy | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: dtolnay/rust-toolchain@stable | ||
| with: | ||
| components: rustfmt, clippy | ||
| components: clippy | ||
| - uses: Swatinem/rust-cache@v2 | ||
| - run: cargo clippy --workspace --all-targets -- -D warnings | ||
|
|
||
| test: | ||
| name: Test | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: dtolnay/rust-toolchain@stable | ||
| - uses: Swatinem/rust-cache@v2 | ||
| - run: cargo test --workspace --exclude xtask | ||
|
|
||
| - name: ci | ||
| run: cargo run -p xtask -- ci | ||
| xtask: | ||
| name: xtask ci | ||
| runs-on: ubuntu-latest | ||
| if: false # disabled until #6 is fixed | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: dtolnay/rust-toolchain@stable | ||
| - uses: Swatinem/rust-cache@v2 | ||
| - run: cargo run -p xtask -- ci | ||
|
Comment on lines
+40
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n -C2 'cargo test --workspace --exclude xtask|cargo run -p xtask -- ci' .github/workflows
rg -n -C4 'fn ci\(\)|conform::run_conformance' xtask/src/main.rs
sed -n '21,27p' .github/settings.ymlRepository: EffortlessMetrics/diffguard Length of output: 1398 The protected The 🧰 Tools🪛 actionlint (1.7.12)[error] 45-45: constant expression "false" in condition. remove the if: section (if-cond) 🤖 Prompt for AI Agents |
||
|
|
||
| # Gate validation: issue linkage | ||
| gate-linked: | ||
| name: "Gate: Issue linked" | ||
| runs-on: ubuntu-latest | ||
| if: github.event_name == 'pull_request' | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Check PR body references an issue | ||
| run: | | ||
| BODY="${{ github.event.pull_request.body }}" | ||
| if echo "$BODY" | grep -qiE '(closes|fixes|resolves)\s+#[0-9]+'; then | ||
| echo "✅ PR references an issue" | ||
| else | ||
| echo "❌ PR does not reference an issue" | ||
| echo "" | ||
| echo "Add 'Closes #N' to the PR body to link your issue." | ||
| exit 1 | ||
|
Comment on lines
+59
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n -C2 'github\.event\.pull_request\.body|github\.head_ref' .github/workflows/ci.ymlRepository: EffortlessMetrics/diffguard Length of output: 602 🏁 Script executed: cat -n .github/workflows/ci.ymlRepository: EffortlessMetrics/diffguard Length of output: 3196 🏁 Script executed: rg -n '\$\{\{\s*(github\.)' .github/workflows/ci.yml | head -20Repository: EffortlessMetrics/diffguard Length of output: 173 Use environment variables to pass GitHub context data to shell scripts. Lines 61 and 80 directly interpolate Proposed fix gate-linked:
name: "Gate: Issue linked"
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- name: Check PR body references an issue
+ env:
+ PR_BODY: ${{ github.event.pull_request.body || '' }}
run: |
- BODY="${{ github.event.pull_request.body }}"
- if echo "$BODY" | grep -qiE '(closes|fixes|resolves)\s+#[0-9]+'; then
+ if printf '%s' "$PR_BODY" | grep -qiE '(closes|fixes|resolves)[[:space:]]+#[0-9]+'; then
echo "✅ PR references an issue"
else
echo "❌ PR does not reference an issue"
echo ""
echo "Add 'Closes `#N`' to the PR body to link your issue."
exit 1
fi
gate-branch:
name: "Gate: Branch convention"
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- name: Check branch name follows convention
+ env:
+ HEAD_REF: ${{ github.head_ref }}
run: |
- BRANCH="${{ github.head_ref }}"
- if echo "$BRANCH" | grep -qE '^(feat|fix|chore|docs|refactor|test)/[0-9]+-'; then
- echo "✅ Branch '$BRANCH' follows convention"
+ if printf '%s' "$HEAD_REF" | grep -qE '^(feat|fix|chore|docs|refactor|test)/[0-9]+-'; then
+ echo "✅ Branch '$HEAD_REF' follows convention"
else
- echo "⚠️ Branch '$BRANCH' doesn't follow naming convention"
+ echo "⚠️ Branch '$HEAD_REF' doesn't follow naming convention"
echo "Expected: <type>/<issue-number>-<slug>"
echo "Examples: feat/11-fix-include-recursion, fix/12-defaults-merge"
echo ""
echo "This is a warning, not a failure."
fi🧰 Tools🪛 actionlint (1.7.12)[error] 60-60: "github.event.pull_request.body" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/reference/security/secure-use#good-practices-for-mitigating-script-injection-attacks for more details (expression) 🤖 Prompt for AI Agents |
||
| fi | ||
|
|
||
| # Gate validation: branch naming | ||
| gate-branch: | ||
| name: "Gate: Branch convention" | ||
| runs-on: ubuntu-latest | ||
| if: github.event_name == 'pull_request' | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Check branch name follows convention | ||
| run: | | ||
| BRANCH="${{ github.head_ref }}" | ||
| if echo "$BRANCH" | grep -qE '^(feat|fix|chore|docs|refactor|test)/[0-9]+-'; then | ||
| echo "✅ Branch '$BRANCH' follows convention" | ||
| else | ||
| echo "⚠️ Branch '$BRANCH' doesn't follow naming convention" | ||
| echo "Expected: <type>/<issue-number>-<slug>" | ||
| echo "Examples: feat/11-fix-include-recursion, fix/12-defaults-merge" | ||
| echo "" | ||
| echo "This is a warning, not a failure." | ||
| fi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: EffortlessMetrics/diffguard
Length of output: 108
🏁 Script executed:
# Read the file to verify the current state cat -n .github/ISSUE_TEMPLATE/gate-bug.ymlRepository: EffortlessMetrics/diffguard
Length of output: 1925
🏁 Script executed:
Repository: EffortlessMetrics/diffguard
Length of output: 427
Quote the
descriptionvalue to prevent YAML parse failure.Line 2 contains
Gate: Framedin a plain scalar, which triggers a YAML mapping value parsing error. The issue form will not function without this fix.Proposed fix
📝 Committable suggestion
🧰 Tools
🪛 YAMLlint (1.38.0)
[error] 2-2: syntax error: mapping values are not allowed here
(syntax)
🤖 Prompt for AI Agents