forgecraft-mcp 1.3.2 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/artifacts/commit-hooks.d.ts +1 -1
  2. package/dist/artifacts/commit-hooks.d.ts.map +1 -1
  3. package/dist/artifacts/commit-hooks.js +2 -0
  4. package/dist/artifacts/commit-hooks.js.map +1 -1
  5. package/dist/cli/commands.d.ts +35 -1
  6. package/dist/cli/commands.d.ts.map +1 -1
  7. package/dist/cli/commands.js +109 -2
  8. package/dist/cli/commands.js.map +1 -1
  9. package/dist/cli/help.d.ts.map +1 -1
  10. package/dist/cli/help.js +7 -0
  11. package/dist/cli/help.js.map +1 -1
  12. package/dist/cli.d.ts.map +1 -1
  13. package/dist/cli.js +10 -1
  14. package/dist/cli.js.map +1 -1
  15. package/dist/shared/result-utils.d.ts +27 -0
  16. package/dist/shared/result-utils.d.ts.map +1 -0
  17. package/dist/shared/result-utils.js +41 -0
  18. package/dist/shared/result-utils.js.map +1 -0
  19. package/dist/tools/close-cycle-helpers.d.ts +21 -2
  20. package/dist/tools/close-cycle-helpers.d.ts.map +1 -1
  21. package/dist/tools/close-cycle-helpers.js +66 -10
  22. package/dist/tools/close-cycle-helpers.js.map +1 -1
  23. package/dist/tools/close-cycle.d.ts +2 -2
  24. package/dist/tools/close-cycle.d.ts.map +1 -1
  25. package/dist/tools/close-cycle.js +1 -1
  26. package/dist/tools/close-cycle.js.map +1 -1
  27. package/dist/tools/consolidate-status.d.ts +81 -0
  28. package/dist/tools/consolidate-status.d.ts.map +1 -0
  29. package/dist/tools/consolidate-status.js +251 -0
  30. package/dist/tools/consolidate-status.js.map +1 -0
  31. package/dist/tools/forgecraft-dispatch.d.ts.map +1 -1
  32. package/dist/tools/forgecraft-dispatch.js +10 -0
  33. package/dist/tools/forgecraft-dispatch.js.map +1 -1
  34. package/dist/tools/forgecraft-router.d.ts +8 -0
  35. package/dist/tools/forgecraft-router.d.ts.map +1 -1
  36. package/dist/tools/forgecraft-router.js +21 -1
  37. package/dist/tools/forgecraft-router.js.map +1 -1
  38. package/dist/tools/forgecraft-schema-params.d.ts +4 -4
  39. package/dist/tools/forgecraft-schema.d.ts +5 -5
  40. package/dist/tools/forgecraft-schema.d.ts.map +1 -1
  41. package/dist/tools/forgecraft-schema.js +3 -0
  42. package/dist/tools/forgecraft-schema.js.map +1 -1
  43. package/dist/tools/gate-violations.d.ts +59 -0
  44. package/dist/tools/gate-violations.d.ts.map +1 -0
  45. package/dist/tools/gate-violations.js +152 -0
  46. package/dist/tools/gate-violations.js.map +1 -0
  47. package/dist/tools/generate-session-prompt.d.ts +3 -3
  48. package/dist/tools/generate-session-prompt.d.ts.map +1 -1
  49. package/dist/tools/generate-session-prompt.js +57 -15
  50. package/dist/tools/generate-session-prompt.js.map +1 -1
  51. package/dist/tools/roadmap-builder.d.ts.map +1 -1
  52. package/dist/tools/roadmap-builder.js +19 -9
  53. package/dist/tools/roadmap-builder.js.map +1 -1
  54. package/dist/tools/session-prompt-builders.d.ts.map +1 -1
  55. package/dist/tools/session-prompt-builders.js +34 -10
  56. package/dist/tools/session-prompt-builders.js.map +1 -1
  57. package/package.json +1 -1
  58. package/templates/universal/hooks.yaml +212 -20
@@ -1 +1 @@
1
- {"version":3,"file":"session-prompt-builders.d.ts","sourceRoot":"","sources":["../../src/tools/session-prompt-builders.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAWxD,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAID,8DAA8D;AAC9D,eAAO,MAAM,sBAAsB,kDAAkD,CAAC;AAWtF;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAU3E;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA2B/D;AAID;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CA2BrE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAQtE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,eAAe,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CASvF;AAID;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CA6B3D"}
1
+ {"version":3,"file":"session-prompt-builders.d.ts","sourceRoot":"","sources":["../../src/tools/session-prompt-builders.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAWxD,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAID,8DAA8D;AAC9D,eAAO,MAAM,sBAAsB,kDACc,CAAC;AAelD;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAY3E;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAqC/D;AAID;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAyCrE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAQtE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,eAAe,EAAE,MAAM,GACtB,aAAa,GAAG,IAAI,CActB;AAID;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAuC3D"}
@@ -13,8 +13,12 @@ import { buildContextLoadBlock, buildTddGateSection, buildContextRetrievalSectio
13
13
  /** Primary-use text shown for the forgecraft server entry. */
14
14
  export const FORGECRAFT_PRIMARY_USE = "check_cascade, generate_session_prompt, audit";
15
15
  const CONSTITUTION_PATHS = [
16
- "CLAUDE.md", "AGENTS.md", ".github/copilot-instructions.md",
17
- ".cursor/rules", ".windsurfrules", ".clinerules",
16
+ "CLAUDE.md",
17
+ "AGENTS.md",
18
+ ".github/copilot-instructions.md",
19
+ ".cursor/rules",
20
+ ".windsurfrules",
21
+ ".clinerules",
18
22
  ];
19
23
  const ADR_DIRS = ["docs/adrs", "docs/adr"];
20
24
  // ── MCP Tools Section ────────────────────────────────────────────────
@@ -34,7 +38,9 @@ export function loadMcpServerDescriptions() {
34
38
  for (const server of parsed.servers ?? [])
35
39
  map.set(server.name, server);
36
40
  }
37
- catch { /* Return empty map */ }
41
+ catch {
42
+ /* Return empty map */
43
+ }
38
44
  return map;
39
45
  }
40
46
  /**
@@ -66,7 +72,9 @@ export function buildMcpToolsSection(projectDir) {
66
72
  : (descriptions.get(name)?.description ?? "MCP server");
67
73
  lines.push(`- **${name}** — ${primaryUse}`);
68
74
  }
69
- return `## Active MCP Tools\n\nThese tools are available in this session. Use them:\n` + lines.join("\n") + "\n\n";
75
+ return (`## Active MCP Tools\n\nThese tools are available in this session. Use them:\n` +
76
+ lines.join("\n") +
77
+ "\n\n");
70
78
  }
71
79
  // ── Artifact Discovery ───────────────────────────────────────────────
72
80
  /**
@@ -97,8 +105,17 @@ export function discoverArtifacts(projectDir) {
97
105
  existsSync(join(projectDir, "docs/UseCases.md"));
98
106
  const activeGateDir = join(projectDir, ".forgecraft/gates/project/active");
99
107
  const activeGateCount = existsSync(activeGateDir)
100
- ? readdirSync(activeGateDir).filter((f) => f.endsWith(".yaml")).length : 0;
101
- return { constitutionPath, statusExists, adrCount, adrDir, diagramsExist, useCasesExist, activeGateCount };
108
+ ? readdirSync(activeGateDir).filter((f) => f.endsWith(".yaml")).length
109
+ : 0;
110
+ return {
111
+ constitutionPath,
112
+ statusExists,
113
+ adrCount,
114
+ adrDir,
115
+ diagramsExist,
116
+ useCasesExist,
117
+ activeGateCount,
118
+ };
102
119
  }
103
120
  /**
104
121
  * Extract the last meaningful section of Status.md for context.
@@ -141,7 +158,12 @@ export function buildRoadmapItemAmbiguity(itemDescription) {
141
158
  field: "roadmap_item",
142
159
  understood_as: `Interpreting '${itemDescription}' as its most common literal meaning`,
143
160
  understood_example: `I scoped the session prompt to: ${itemDescription} (minimal implementation)`,
144
- alternatives: [{ label: "If broader scope intended", action: `Include related concerns: error handling, integration tests, ADR for architectural decisions` }],
161
+ alternatives: [
162
+ {
163
+ label: "If broader scope intended",
164
+ action: `Include related concerns: error handling, integration tests, ADR for architectural decisions`,
165
+ },
166
+ ],
145
167
  resolution_hint: `Pass a more specific item_description, e.g. 'Add JWT authentication with email/password login, bcrypt hashing, and a /auth/refresh endpoint'`,
146
168
  };
147
169
  }
@@ -153,15 +175,17 @@ export function buildRoadmapItemAmbiguity(itemDescription) {
153
175
  * @returns Complete, ready-to-paste session prompt
154
176
  */
155
177
  export function buildPrompt(input) {
156
- const { projectDir, itemDescription, sessionType, scopeNote, acceptanceCriteria, artifacts, statusSummary } = input;
178
+ const { projectDir, itemDescription, sessionType, scopeNote, acceptanceCriteria, artifacts, statusSummary, } = input;
157
179
  const contextLoadBlock = buildContextLoadBlock(artifacts);
158
- const scopeBlock = scopeNote ? `\n## Out of Scope\nDo NOT touch: ${scopeNote}\n` : "";
180
+ const scopeBlock = scopeNote
181
+ ? `\n## Out of Scope\nDo NOT touch: ${scopeNote}\n`
182
+ : "";
159
183
  const criteriaLines = acceptanceCriteria.map((c) => `- [ ] ${c}`).join("\n");
160
184
  const conventionalType = sessionType === "fix" ? "fix" : sessionType;
161
185
  let prompt = `# Session Prompt — Bound\n\n> Generated by ForgeCraft \`generate_session_prompt\`. Load context, then issue this prompt.\n\n---\n\n`;
162
186
  prompt += `## Context Load Order\n\nLoad these artifacts **before** issuing the implementation prompt:\n\n${contextLoadBlock}\n`;
163
187
  if (statusSummary) {
164
- prompt += `## Current State (from Status.md)\n\n\`\`\`\n${statusSummary}\n\`\`\`\n\n`;
188
+ prompt += statusSummary + "\n\n";
165
189
  }
166
190
  prompt += `---\n\n## Implementation Prompt\n\n*(Paste everything below this line to the AI assistant)*\n\n---\n\n`;
167
191
  prompt += `### Task\n\n${itemDescription}\n\n`;
@@ -1 +1 @@
1
- {"version":3,"file":"session-prompt-builders.js","sourceRoot":"","sources":["../../src/tools/session-prompt-builders.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-prompt-builders.js","sourceRoot":"","sources":["../../src/tools/session-prompt-builders.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forgecraft-mcp",
3
- "version": "1.3.2",
3
+ "version": "1.4.0",
4
4
  "mcpName": "io.github.jghiringhelli/forgecraft",
5
5
  "description": "CLI + MCP sentinel for engineering standards — SOLID, testing, architecture, CI/CD — auto-tailored to your stack. Minimal MCP footprint (~200 tokens) via CLI-first design.",
6
6
  "type": "module",
@@ -90,6 +90,10 @@ hooks:
90
90
  echo "$STAGED" | grep '\.py$' | xargs -r isort --quiet 2>/dev/null
91
91
  # TypeScript/JavaScript
92
92
  echo "$STAGED" | grep '\.\(ts\|tsx\|js\|jsx\)$' | xargs -r npx prettier --write 2>/dev/null
93
+ # Rust
94
+ if echo "$STAGED" | grep -q '\.rs$' && [ -f "Cargo.toml" ]; then
95
+ cargo fmt 2>/dev/null
96
+ fi
93
97
  # Re-stage formatted files
94
98
  echo "$STAGED" | xargs -r git add
95
99
 
@@ -99,6 +103,20 @@ hooks:
99
103
  filename: pre-commit-secrets.sh
100
104
  script: |
101
105
  #!/bin/bash
106
+ _fc_write_violation() {
107
+ local hook_name="$1" severity="${2:-error}" message="$3"
108
+ local repo_root
109
+ repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || return 0
110
+ local dir="$repo_root/.forgecraft"
111
+ mkdir -p "$dir" 2>/dev/null || return 0
112
+ local ts
113
+ ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || printf "unknown")"
114
+ local esc_msg
115
+ esc_msg="$(printf '%s' "$message" | sed 's/\\/\\\\/g; s/"/\\"/g')"
116
+ printf '{"hook":"%s","severity":"%s","message":"%s","timestamp":"%s"}\n' \
117
+ "$hook_name" "$severity" "$esc_msg" "$ts" \
118
+ >> "$dir/gate-violations.jsonl" 2>/dev/null || true
119
+ }
102
120
  PATTERNS=(
103
121
  'AKIA[0-9A-Z]{16}'
104
122
  'password\s*=\s*["\x27][^"\x27]+'
@@ -111,6 +129,7 @@ hooks:
111
129
  for pattern in "${PATTERNS[@]}"; do
112
130
  if grep -qE "$pattern" "$file" 2>/dev/null; then
113
131
  echo "❌ Potential secret found in $file matching pattern"
132
+ _fc_write_violation "pre-commit-secrets" "error" "Potential secrets detected in staged files — review output above"
114
133
  exit 1
115
134
  fi
116
135
  done
@@ -122,6 +141,20 @@ hooks:
122
141
  filename: pre-commit-compile.sh
123
142
  script: |
124
143
  #!/bin/bash
144
+ _fc_write_violation() {
145
+ local hook_name="$1" severity="${2:-error}" message="$3"
146
+ local repo_root
147
+ repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || return 0
148
+ local dir="$repo_root/.forgecraft"
149
+ mkdir -p "$dir" 2>/dev/null || return 0
150
+ local ts
151
+ ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || printf "unknown")"
152
+ local esc_msg
153
+ esc_msg="$(printf '%s' "$message" | sed 's/\\/\\\\/g; s/"/\\"/g')"
154
+ printf '{"hook":"%s","severity":"%s","message":"%s","timestamp":"%s"}\n' \
155
+ "$hook_name" "$severity" "$esc_msg" "$ts" \
156
+ >> "$dir/gate-violations.jsonl" 2>/dev/null || true
157
+ }
125
158
  echo "🔨 Running build check..."
126
159
  if [ -f "pyproject.toml" ] || [ -f "setup.py" ] || [ -f "requirements.txt" ]; then
127
160
  STAGED_PY=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$')
@@ -130,6 +163,7 @@ hooks:
130
163
  python -m py_compile "$file" 2>&1
131
164
  if [ $? -ne 0 ]; then
132
165
  echo "❌ Syntax error in $file"
166
+ _fc_write_violation "pre-commit-compile" "error" "TypeScript compilation failed — run tsc --noEmit to see errors"
133
167
  exit 1
134
168
  fi
135
169
  done
@@ -140,12 +174,62 @@ hooks:
140
174
  npx tsc --noEmit 2>&1
141
175
  if [ $? -ne 0 ]; then
142
176
  echo "❌ TypeScript compilation failed."
177
+ _fc_write_violation "pre-commit-compile" "error" "TypeScript compilation failed — run tsc --noEmit to see errors"
143
178
  exit 1
144
179
  fi
145
180
  echo " ✅ TypeScript compilation OK"
146
181
  fi
182
+ if [ -f "Cargo.toml" ]; then
183
+ STAGED_RS=$(git diff --cached --name-only --diff-filter=ACM | grep '\.rs$')
184
+ if [ -n "$STAGED_RS" ]; then
185
+ cargo check --quiet 2>&1
186
+ if [ $? -ne 0 ]; then
187
+ echo "❌ Rust cargo check failed."
188
+ _fc_write_violation "pre-commit-compile" "error" "Rust cargo check failed — run cargo check to see errors"
189
+ exit 1
190
+ fi
191
+ echo " ✅ Rust cargo check OK"
192
+ fi
193
+ fi
147
194
  echo "🔨 Build check passed"
148
195
 
196
+ - name: cargo-clippy
197
+ trigger: pre-commit
198
+ description: "Run cargo clippy on Rust projects — catches bugs, style issues, and common mistakes beyond cargo check"
199
+ filename: pre-commit-clippy.sh
200
+ script: |
201
+ #!/bin/bash
202
+ _fc_write_violation() {
203
+ local hook_name="$1" severity="${2:-error}" message="$3"
204
+ local repo_root
205
+ repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || return 0
206
+ local dir="$repo_root/.forgecraft"
207
+ mkdir -p "$dir" 2>/dev/null || return 0
208
+ local ts
209
+ ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || printf "unknown")"
210
+ local esc_msg
211
+ esc_msg="$(printf '%s' "$message" | sed 's/\\/\\\\/g; s/"/\\"/g')"
212
+ printf '{"hook":"%s","severity":"%s","message":"%s","timestamp":"%s"}\n' \
213
+ "$hook_name" "$severity" "$esc_msg" "$ts" \
214
+ >> "$dir/gate-violations.jsonl" 2>/dev/null || true
215
+ }
216
+ if [ ! -f "Cargo.toml" ]; then
217
+ exit 0
218
+ fi
219
+ STAGED_RS=$(git diff --cached --name-only --diff-filter=ACM | grep '\.rs$')
220
+ if [ -z "$STAGED_RS" ]; then
221
+ exit 0
222
+ fi
223
+ echo "🦀 Running cargo clippy..."
224
+ cargo clippy --all-targets --all-features 2>&1
225
+ if [ $? -ne 0 ]; then
226
+ echo "❌ cargo clippy failed — fix lint errors before committing."
227
+ echo " Run: cargo clippy --all-targets --all-features"
228
+ _fc_write_violation "pre-commit-clippy" "error" "Cargo clippy violations found — run cargo clippy to see details"
229
+ exit 1
230
+ fi
231
+ echo " ✅ cargo clippy passed"
232
+
149
233
  - name: tdd-phase-gate
150
234
  trigger: pre-commit
151
235
  description: "RED gate: test-only commits must have failing tests; warn on implementation without tests"
@@ -180,6 +264,8 @@ hooks:
180
264
  elif grep -q '"jest"' package.json 2>/dev/null; then
181
265
  RUN_CMD="npx jest --passWithNoTests"
182
266
  fi
267
+ elif [ -f "Cargo.toml" ]; then
268
+ RUN_CMD="cargo test"
183
269
  elif [ -f "pytest.ini" ] || [ -f "pyproject.toml" ] || [ -f "setup.py" ]; then
184
270
  RUN_CMD="python -m pytest"
185
271
  fi
@@ -270,6 +356,14 @@ hooks:
270
356
  echo " ✅ Python tests passed"
271
357
  fi
272
358
  fi
359
+ if [ -f "Cargo.toml" ]; then
360
+ cargo test --quiet 2>&1
361
+ if [ $? -ne 0 ]; then
362
+ echo "❌ Rust tests failed."
363
+ exit 1
364
+ fi
365
+ echo " ✅ Rust tests passed"
366
+ fi
273
367
  echo "🧪 All tests passed"
274
368
 
275
369
  - name: coverage-gate
@@ -278,6 +372,20 @@ hooks:
278
372
  filename: pre-commit-coverage.sh
279
373
  script: |
280
374
  #!/bin/bash
375
+ _fc_write_violation() {
376
+ local hook_name="$1" severity="${2:-error}" message="$3"
377
+ local repo_root
378
+ repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || return 0
379
+ local dir="$repo_root/.forgecraft"
380
+ mkdir -p "$dir" 2>/dev/null || return 0
381
+ local ts
382
+ ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || printf "unknown")"
383
+ local esc_msg
384
+ esc_msg="$(printf '%s' "$message" | sed 's/\\/\\\\/g; s/"/\\"/g')"
385
+ printf '{"hook":"%s","severity":"%s","message":"%s","timestamp":"%s"}\n' \
386
+ "$hook_name" "$severity" "$esc_msg" "$ts" \
387
+ >> "$dir/gate-violations.jsonl" 2>/dev/null || true
388
+ }
281
389
  # ──────────────────────────────────────────────────────────────────────
282
390
  # Pre-Commit Hook: Coverage Gate
283
391
  #
@@ -317,8 +425,30 @@ hooks:
317
425
  # ── Run coverage ───────────────────────────────────────────────────────
318
426
  echo "📊 Running coverage gate (src/ files staged)..."
319
427
 
320
- if [ ! -f "package.json" ]; then
321
- echo " ⚠️ No package.json found — skipping coverage check."
428
+ if [ ! -f "package.json" ] && [ ! -f "pyproject.toml" ] && [ ! -f "setup.py" ]; then
429
+ if [ -f "Cargo.toml" ]; then
430
+ # Rust: run tests; use cargo-tarpaulin for coverage if available
431
+ if command -v cargo-tarpaulin &> /dev/null; then
432
+ cargo tarpaulin --out Stdout --fail-under {{coverage_minimum | default: 80}} 2>&1
433
+ if [ $? -ne 0 ]; then
434
+ echo "❌ Coverage gate failed — below {{coverage_minimum | default: 80}}%."
435
+ echo " Run: cargo tarpaulin --out Html"
436
+ _fc_write_violation "pre-commit-coverage" "error" "Coverage gate failed — run npm test --coverage to see report"
437
+ exit 1
438
+ fi
439
+ echo " ✅ Rust coverage gate passed"
440
+ else
441
+ cargo test --quiet 2>&1
442
+ if [ $? -ne 0 ]; then
443
+ echo "❌ Rust tests failed."
444
+ _fc_write_violation "pre-commit-coverage" "error" "Coverage gate failed — run npm test --coverage to see report"
445
+ exit 1
446
+ fi
447
+ echo " ✅ Rust tests passed (install cargo-tarpaulin for coverage enforcement)"
448
+ fi
449
+ else
450
+ echo " ⚠️ No supported build system found — skipping coverage check."
451
+ fi
322
452
  exit 0
323
453
  fi
324
454
 
@@ -332,6 +462,7 @@ hooks:
332
462
  echo "❌ Coverage gate failed — thresholds not met."
333
463
  echo " Run 'npx vitest run --coverage' locally to see the full report."
334
464
  echo " Add tests until coverage meets the configured minimums."
465
+ _fc_write_violation "pre-commit-coverage" "error" "Coverage gate failed — run npm test --coverage to see report"
335
466
  exit 1
336
467
  fi
337
468
  echo " ✅ Coverage gate passed"
@@ -345,17 +476,19 @@ hooks:
345
476
  --silent 2>&1
346
477
  if [ $? -ne 0 ]; then
347
478
  echo "❌ Coverage gate failed — thresholds not met."
479
+ _fc_write_violation "pre-commit-coverage" "error" "Coverage gate failed — run npm test --coverage to see report"
348
480
  exit 1
349
481
  fi
350
482
  echo " ✅ Coverage gate passed"
351
483
  exit 0
352
484
  fi
353
485
 
354
- if [ -f "pyproject.toml" ] || [ -f "setup.py" ]; then
486
+ if [ -f "pyproject.toml" ]|| [ -f "setup.py" ]; then
355
487
  if command -v pytest &> /dev/null; then
356
488
  pytest --tb=no --quiet --cov=src --cov-fail-under={{coverage_minimum | default: 80}} 2>&1
357
489
  if [ $? -ne 0 ]; then
358
490
  echo "❌ Coverage gate failed — below {{coverage_minimum | default: 80}}%."
491
+ _fc_write_violation "pre-commit-coverage" "error" "Coverage gate failed — run npm test --coverage to see report"
359
492
  exit 1
360
493
  fi
361
494
  echo " ✅ Coverage gate passed"
@@ -376,8 +509,22 @@ hooks:
376
509
  - .env vs .env.example drift (warns on missing variables)
377
510
  script: |
378
511
  #!/bin/bash
512
+ _fc_write_violation() {
513
+ local hook_name="$1" severity="${2:-error}" message="$3"
514
+ local repo_root
515
+ repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || return 0
516
+ local dir="$repo_root/.forgecraft"
517
+ mkdir -p "$dir" 2>/dev/null || return 0
518
+ local ts
519
+ ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || printf "unknown")"
520
+ local esc_msg
521
+ esc_msg="$(printf '%s' "$message" | sed 's/\\/\\\\/g; s/"/\\"/g')"
522
+ printf '{"hook":"%s","severity":"%s","message":"%s","timestamp":"%s"}\n' \
523
+ "$hook_name" "$severity" "$esc_msg" "$ts" \
524
+ >> "$dir/gate-violations.jsonl" 2>/dev/null || true
525
+ }
379
526
  STAGED=$(git diff --cached --name-only --diff-filter=ACM)
380
- SOURCE_FILES=$(echo "$STAGED" | grep -E '\.(py|ts|tsx|js|jsx)$' | grep -vE '(test_|\.test\.|\.spec\.|__tests__|tests/|fixtures/|mock|conftest)')
527
+ SOURCE_FILES=$(echo "$STAGED" | grep -E '\.(py|ts|tsx|js|jsx|rs)$' | grep -vE '(test_|\.test\.|\.spec\.|__tests__|tests/|fixtures/|mock|conftest|_test\.rs)')
381
528
  if [ -z "$SOURCE_FILES" ]; then exit 0; fi
382
529
  VIOLATIONS=0
383
530
  WARNINGS=0
@@ -443,10 +590,39 @@ hooks:
443
590
  echo " ⚠️ $file — $LINE_COUNT lines (max {{max_file_length | default: 300}})"
444
591
  WARNINGS=$((WARNINGS + 1))
445
592
  fi
446
- done
593
+ # Rust-specific anti-patterns
594
+ if echo "$file" | grep -q '\.rs$'; then
595
+ if ! is_excepted "rust/unwrap" "$file"; then
596
+ if grep -nE '\.unwrap\(\)' "$file" > /tmp/violations 2>/dev/null; then
597
+ if [ -s /tmp/violations ]; then
598
+ echo " ⚠️ $file — .unwrap() in production code — use ? or explicit error handling"
599
+ WARNINGS=$((WARNINGS + 1))
600
+ fi
601
+ fi
602
+ fi
603
+ if grep -nE '\btodo!\(|\bunimplemented!\(' "$file" > /tmp/violations 2>/dev/null; then
604
+ if [ -s /tmp/violations ]; then
605
+ echo " ❌ $file — todo!/unimplemented! in production code"
606
+ VIOLATIONS=$((VIOLATIONS + 1))
607
+ fi
608
+ fi
609
+ if grep -nE '^[[:space:]]*#\[allow\(dead_code\)\]' "$file" > /tmp/violations 2>/dev/null; then
610
+ if [ -s /tmp/violations ]; then
611
+ echo " ⚠️ $file — #[allow(dead_code)] suppression — delete orphaned code instead"
612
+ WARNINGS=$((WARNINGS + 1))
613
+ fi
614
+ fi
615
+ if grep -nE '^[[:space:]]*unsafe[[:space:]]*\{' "$file" > /tmp/violations 2>/dev/null; then
616
+ if [ -s /tmp/violations ]; then
617
+ echo " ⚠️ $file — unsafe block present — requires explicit justification comment"
618
+ WARNINGS=$((WARNINGS + 1))
619
+ fi
620
+ fi
621
+ fi
447
622
  rm -f /tmp/violations
448
623
  if [ $VIOLATIONS -gt 0 ]; then
449
624
  echo "❌ $VIOLATIONS violation(s) found — commit blocked."
625
+ _fc_write_violation "pre-commit-anti-patterns" "error" "Anti-patterns detected in staged files — see output above"
450
626
  exit 1
451
627
  fi
452
628
  if [ $WARNINGS -gt 0 ]; then
@@ -462,26 +638,42 @@ hooks:
462
638
  #!/bin/bash
463
639
  MAX_LENGTH={{max_function_length | default: 50}}
464
640
  STAGED=$(git diff --cached --name-only --diff-filter=ACM)
465
- SOURCE_FILES=$(echo "$STAGED" | grep -E '\.(ts|tsx|js|jsx)$' | grep -vE '(\.test\.|\.spec\.|__tests__|tests/)')
641
+ SOURCE_FILES=$(echo "$STAGED" | grep -E '\.(ts|tsx|js|jsx|rs)$' | grep -vE '(\.test\.|\.spec\.|__tests__|tests/|_test\.rs)')
466
642
  if [ -z "$SOURCE_FILES" ]; then exit 0; fi
467
643
  WARNINGS=0
468
644
  for file in $SOURCE_FILES; do
469
- # Heuristic: find function/method declarations and count lines to next declaration or closing brace
470
- awk -v max="$MAX_LENGTH" -v fname="$file" '
471
- /^[[:space:]]*(export )?(async )?(function |const [a-zA-Z]+ = (async )?\(|[a-zA-Z]+\(.*\) \{|[a-zA-Z]+\(.*\): )/ {
472
- if (start > 0 && NR - start > max) {
473
- printf " ⚠️ %s:%d — function starting here is %d lines (max %d)\n", fname, start, NR - start, max
474
- warnings++
645
+ # Heuristic: find function/method declarations and count lines to next declaration
646
+ if echo "$file" | grep -q '\.rs$'; then
647
+ awk -v max="$MAX_LENGTH" -v fname="$file" '
648
+ /^[[:space:]]*(pub )?(async )?fn [a-zA-Z_]/ {
649
+ if (start > 0 && NR - start > max) {
650
+ printf " ⚠️ %s:%d — fn starting here is %d lines (max %d)\n", fname, start, NR - start, max
651
+ }
652
+ start = NR
475
653
  }
476
- start = NR
477
- }
478
- END {
479
- if (start > 0 && NR - start > max) {
480
- printf " ⚠️ %s:%d — function starting here is %d lines (max %d)\n", fname, start, NR - start, max
481
- warnings++
654
+ END {
655
+ if (start > 0 && NR - start > max) {
656
+ printf " ⚠️ %s:%d — fn starting here is %d lines (max %d)\n", fname, start, NR - start, max
657
+ }
482
658
  }
483
- }
484
- ' "$file"
659
+ ' "$file"
660
+ else
661
+ awk -v max="$MAX_LENGTH" -v fname="$file" '
662
+ /^[[:space:]]*(export )?(async )?(function |const [a-zA-Z]+ = (async )?\(|[a-zA-Z]+\(.*\) \{|[a-zA-Z]+\(.*\): )/ {
663
+ if (start > 0 && NR - start > max) {
664
+ printf " ⚠️ %s:%d — function starting here is %d lines (max %d)\n", fname, start, NR - start, max
665
+ warnings++
666
+ }
667
+ start = NR
668
+ }
669
+ END {
670
+ if (start > 0 && NR - start > max) {
671
+ printf " ⚠️ %s:%d — function starting here is %d lines (max %d)\n", fname, start, NR - start, max
672
+ warnings++
673
+ }
674
+ }
675
+ ' "$file"
676
+ fi
485
677
  WARNINGS=$((WARNINGS + $?))
486
678
  done
487
679
  # Warning only — does not block commit since bash heuristics aren't perfect