Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4f0a6a7
fix: tag mapping
martient Apr 7, 2026
50f7349
fix: scope detection
martient Apr 7, 2026
bd2c183
fix: tag behavior
martient Apr 7, 2026
db3f685
fix: prevent tag dry-run side effects
martient Apr 7, 2026
1ff168c
Feat agent convention enforcement (#41)
martient Jul 15, 2026
b35b003
fix(hooks): support Windows release builds
martient Aug 2, 2026
caf53e3
chore: bump version to 1.9.1
martient Aug 2, 2026
a603fea
docs(agents): add September 2026 agent compatibility audit
martient Sep 20, 2026
64f0a62
fix(cli): make agent invocations parse and fail machine-readably
martient Sep 20, 2026
c4db683
fix(cli): global flag placement, usage envelope, capability surface
martient Sep 20, 2026
2b197f0
test(agents): cover agent CLI ergonomics and update the audit
martient Sep 20, 2026
ac60b45
docs(agents): document flag placement and the invalid_usage envelope
martient Sep 20, 2026
67919bd
docs(audit): record the CLI ergonomics diagnosis and withdraw the MCP…
martient Sep 20, 2026
a331dcc
docs(agents): ban AI attribution trailers in commits and PRs
martient Sep 20, 2026
0ea82fc
fix(ai): make the Ollama provider work and stop sending an empty prompt
claude Sep 20, 2026
97c0c55
fix(ci): run checks on pull requests targeting nested branch names
claude Sep 20, 2026
30ca219
docs(agents): make AGENTS.md canonical and reach every runtime
claude Sep 20, 2026
2a4b19a
test(agents): cover the plugin manifests and skill frontmatter
claude Sep 20, 2026
ade11ef
chore(ci): modernise the generated workflow and tighten the agent gua…
claude Sep 20, 2026
d2b10dd
test: stop the tag signing test depending on ambient git config
claude Sep 20, 2026
fbb1144
test(hooks): add a behaviour matrix for the guardrail, and fix what i…
claude Sep 20, 2026
44cea1b
Merge pull request #49 from martient/claude/agent-compatibility-2026-09
martient Sep 21, 2026
b9c9389
fix(release): stop shipping binaries that report the previous version…
martient Sep 27, 2026
91440f0
chore(release): align version files with published v1.10.0
martient Sep 27, 2026
160208c
fix(docs): update vulnerable astro, starlight, and sharp dependencies…
martient Sep 27, 2026
c1b4fdf
Merge remote-tracking branch 'origin/main' into develop
martient Sep 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "personal",
"interface": {
"displayName": "Personal"
},
"plugins": [
{
"name": "committy",
"source": {
"source": "local",
"path": "./plugins/committy"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
}
]
}
1 change: 1 addition & 0 deletions .agents/skills
18 changes: 18 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://json.schemastore.org/claude-code-marketplace.json",
"name": "committy-tools",
"description": "Agent workflows and enforcement for Committy repositories.",
"owner": {
"name": "Arnaud Leherpeur",
"email": "arnaud.leherpeur@taultek.com"
},
"plugins": [
{
"name": "committy",
"source": "./plugins/committy",
"description": "Token-efficient commit, branch, release, and convention enforcement workflows.",
"category": "Development",
"tags": ["git", "conventional-commits", "agents"]
}
]
}
61 changes: 61 additions & 0 deletions .claude/hooks/block-dangerous-git.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash
# Block genuinely destructive git operations.
#
# Design notes:
# - Matches the *command*, not the raw tool input. The previous version
# grepped the whole string, so prose in a heredoc that merely named a
# command was blocked (including this file's own replacement), while
# `git push` with two spaces or `git -C . push` slipped straight through.
# - Plain `git push` is not destructive and is no longer blocked. The
# repository's own pre-push hook is the policy-backed control; this hook
# only refuses operations that destroy history or uncommitted work.
# - Degrades safely when jq is unavailable.

INPUT=$(cat)

if command -v jq >/dev/null 2>&1; then
COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty')
else
COMMAND=$(printf '%s' "$INPUT" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\(.*\)".*/\1/p')
fi

[ -z "$COMMAND" ] && exit 0

# Drop heredoc bodies, so documentation or test data that names a command is
# not mistaken for an invocation of it. A heredoc body spans lines, so this
# keeps the line that opens it and discards everything after.
#
# Exception: if the heredoc feeds an interpreter, the body IS executed, and
# dropping it would be a bypass (`bash <<EOF` / `git reset --hard` / `EOF`).
# In that case scan the whole thing.
HEREDOC_LINE=$(printf '%s' "$COMMAND" | grep -m1 '<<')
if [ -n "$HEREDOC_LINE" ] && printf '%s' "$HEREDOC_LINE" |
grep -qE '(^|[;&|[:space:]])(bash|sh|zsh|dash|ksh|python3?|perl|ruby|eval|xargs|source)([[:space:]]|$)'; then
SCRUBBED="$COMMAND"
else
SCRUBBED=$(printf '%s' "$COMMAND" | awk '/<</ { print; exit } { print }')
fi

# Only inspect commands that actually invoke git.
printf '%s' "$SCRUBBED" | grep -qE '(^|[;&|[:space:]])git([[:space:]]|$)' || exit 0

deny() {
echo "BLOCKED: '$COMMAND' looks like $1. The user has prevented you from doing this." >&2
exit 2
}

# --force rewrites remote history unconditionally; --force-with-lease is guarded.
# Checked as two independent conditions rather than one ordered regex: the flag
# may precede or follow the remote, and `push -f` leaves no space for a pattern
# that expects one before the flag.
if printf '%s' "$SCRUBBED" | grep -qE '(^|[;&|[:space:]])push([[:space:]]|$)' &&
printf '%s' "$SCRUBBED" | grep -qE '(^|[[:space:]])(--force|-f)([[:space:]]|$)'; then
printf '%s' "$SCRUBBED" | grep -q -- '--force-with-lease' || deny "an unguarded force-push"
fi

printf '%s' "$SCRUBBED" | grep -qE 'reset[[:space:]]+--hard' && deny "a hard reset (discards working-tree changes)"
printf '%s' "$SCRUBBED" | grep -qE 'clean[[:space:]]+-[a-zA-Z]*f' && deny "a forced clean (deletes untracked files)"
printf '%s' "$SCRUBBED" | grep -qE 'branch[[:space:]]+-D([[:space:]]|$)' && deny "a forced branch delete"
printf '%s' "$SCRUBBED" | grep -qE '(checkout|restore)[[:space:]]+(--[[:space:]]+)?\.([[:space:]]|$)' && deny "a bulk discard of working-tree changes"

exit 0
15 changes: 15 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous-git.sh"
}
]
}
]
}
}
6 changes: 6 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copilot instructions

See [`AGENTS.md`](../AGENTS.md) at the repository root. It is the canonical
guide for every coding agent working in this repository and applies in full:
build and verify commands, the CLI-first agent workflow, architecture, and the
commit and pull-request rules.
26 changes: 23 additions & 3 deletions .github/workflows/cargo-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,34 @@ on:
- "v[0-9]+.[0-9]+.[0-9]+-*"

jobs:
verify-version:
name: Verify Cargo.toml matches the tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- name: Compare Cargo.toml version with tag
shell: bash
run: |
VERSION=$(grep -m1 'version\s*=' Cargo.toml | cut -d'"' -f2 | cut -d"'" -f2)
TAG="$GITHUB_REF_NAME"
if [ "v$VERSION" != "$TAG" ]; then
echo "::error::Tag $TAG points at a tree whose Cargo.toml says $VERSION."
echo "The published binaries would report $VERSION to --version, and self-update would keep offering $TAG forever."
echo "Bump Cargo.toml to ${TAG#v} on the release branch, then move or recreate the tag."
exit 1
fi
echo "Cargo.toml version $VERSION matches tag $TAG"

create-release:
needs: verify-version
runs-on: ubuntu-latest
outputs:
is_prerelease: ${{ steps.release_type.outputs.is_prerelease }}
draft: ${{ steps.release_type.outputs.draft }}
changelog: ${{ steps.changelog.outputs.changelog }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down Expand Up @@ -54,7 +74,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

release:
needs: create-release
needs: [verify-version, create-release]
name: Release for ${{ matrix.target }}
runs-on: ${{ matrix.os }}

Expand Down Expand Up @@ -84,7 +104,7 @@ jobs:
asset_suffix: macos-arm64

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Get binary name and version
shell: bash
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ on:
push:
branches: [main, develop]
pull_request:
branches: ["*"]
# `**` rather than `*`: in Actions branch filters `*` does not match `/`,
# so a pull request targeting any branch with a slash in its name -- every
# stacked pull request, and anything under a `feat/` or `fix/` prefix --
# ran no checks at all.
branches: ["**"]

env:
CARGO_TERM_COLOR: always
Expand All @@ -13,7 +17,7 @@ jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Install Rust
uses: actions-rs/toolchain@v1.0.7
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/native-git-verification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ jobs:
native-git-e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Run native git Docker verification
run: ./scripts/verify_native_git_e2e.sh
Loading
Loading