Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "make-no-mistakes",
"version": "1.38.0",
"version": "1.41.0",
"description": "The disciplined dev lifecycle \u2014 implement issues, review PRs, sync releases, test E2E, manage sessions, and stash secrets via OS-native prompts. One plugin to make no mistakes.",
"owner": {
"name": "Luis Andres Pena Castillo",
Expand All @@ -11,7 +11,7 @@
{
"name": "make-no-mistakes",
"description": "Dev lifecycle orchestrator. Start with /make-no-mistakes:domain-driven-advisor \u2014 the canonical entry point that inspects your repo, asks a few plain-language questions, and routes you across the six-family audit engine (schema-drift, contract-drift, ddd, explicit-architecture, strangler, enforcement-hooks), then runs a premortem on the aggregated remediation plan. Also ships disciplined Linear issue execution with worktree isolation, PR review with Greptile gating, team release sync, E2E test generation/execution, test suite previewer, security pentesting, MoSCoW + RICE prioritization, cross-platform secret stash via OS-native GUI prompts (zenity / kdialog / osascript / Get-Credential), and session management. 37 commands, 11 auto-activating skills, 2 specialized agents.",
"version": "1.38.0",
"version": "1.41.0",
"author": {
"name": "Luis Andres Pena Castillo",
"email": "lapc506@users.noreply.github.com"
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "make-no-mistakes",
"version": "1.38.0",
"version": "1.41.0",
"description": "The disciplined dev lifecycle — implement issues, review PRs, sync releases, test E2E, manage sessions, stash secrets, and enforce manifest-driven tool-call hooks. One plugin to make no mistakes.",
"author": {
"name": "Luis Andres Pena Castillo",
Expand Down
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.41.0] - 2026-08-02

### Added
- **`block-no-verify` — the flag that had a rule about it and no rule enforcing
it.** Non-negotiable 21 names four bypasses: `--no-verify`, `--admin`,
`--force`, and merging past a check. Measured across all 40 rules: `--admin`,
`push --force` and `--force-with-lease` each had one. **`--no-verify` had
none.**

That asymmetry is worse than a plain gap. Three of the four are covered, so a
reader has every reason to assume the fourth is too — the rule reads as
enforced and is not.

Found the way these things are always found. On 2026-08-02 an agent resolving
a merge conflict ran `git commit --no-verify`, by reflex and with no
justification. It reported the violation itself, discarded the commit, redid
the merge and recommitted with hooks enabled. **Nothing stopped it, because
there was nothing to stop it** — it did not route around a guard, it walked
through a gap.

**The near-miss the rule must not get wrong**, and the reason the short form
is scoped to one subcommand: `git commit -n` IS `--no-verify`, while
`git push -n` is `--dry-run`. Same letter, opposite meaning. Blocking a
dry-run would refuse the safest command in git, and a guard that refuses
ordinary work gets bypassed — which is how a guard stops carrying
information at all. Asserted by `push-dry-run-allowed`.

**No bypass marker, deliberately** (`bypass_marker: null`), and the refusal
message says why rather than asserting it. The incident's own honest attempt
first failed with `vitest: command not found`, because a fresh worktree had
no dependencies. The fix was `bun install --frozen-lockfile`. **A hook that
cannot run is a broken toolchain, not a gate to step over** — so the message
names that command, because a refusal that leaves you stuck is a refusal that
gets worked around next time.

Six tests, all green, covering both spellings on both subcommands, the
dry-run near-miss, an ordinary commit, and a quoted mention (documenting the
flag performs no skip). Hook suite 346/346, vitest 60/60.


## [1.38.0] - 2026-07-31

### Changed
Expand Down Expand Up @@ -950,6 +990,7 @@ installed caches) but had no representation on `main`; this release lands them.
([PR #4](https://github.com/DojoCodingLabs/make-no-mistakes-toolkit/pull/4)).

[Unreleased]: https://github.com/DojoCodingLabs/make-no-mistakes-toolkit/compare/v1.38.0...HEAD
[1.41.0]: https://github.com/DojoCodingLabs/make-no-mistakes-toolkit/releases/tag/v1.41.0
[1.38.0]: https://github.com/DojoCodingLabs/make-no-mistakes-toolkit/releases/tag/v1.38.0
[1.37.0]: https://github.com/DojoCodingLabs/make-no-mistakes-toolkit/releases/tag/v1.37.0
[1.36.0]: https://github.com/DojoCodingLabs/make-no-mistakes-toolkit/releases/tag/v1.36.0
Expand Down
80 changes: 80 additions & 0 deletions hooks/rules/rules.json
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,86 @@
}
]
},
{
"id": "block-no-verify",
"description": "Block a commit or push that skips the hooks",
"applies_to": [
"Bash"
],
"match": [
{
"field": "command",
"pattern": "(git[[:space:]]+(commit|push)[^|;&]*--no-verify|git[[:space:]]+commit[^|;&]*[[:space:]]-n([[:space:]]|$))"
},
{
"field": "command",
"not_pattern": "['\\\"]--no-verify"
}
],
"action": "block",
"bypass_marker": null,
"memory_ref": "feedback_agents_never_self_authorize_documented_overrides.md",
"references": [
"dojo-os CLAUDE.md non-negotiable 21"
],
"message": "BLOCKED: this skips the hooks.\n\nThe hooks are the only thing standing between a commit and the checks it\nwas supposed to pass. Skipping them does not make a commit faster -- it\nmakes an UNVERIFIED commit indistinguishable from a verified one, and\nnothing downstream can tell them apart afterwards.\n\nNon-negotiable 21 names this flag alongside --admin and --force. Those\nthree had rules; this one did not, which is why you are reading a new\nmessage. An agent used it on 2026-08-02, reported it, and reverted it.\n\nTHE HOOKS FAILING IS NOT A REASON TO SKIP THEM. In that same incident the\nhonest attempt failed with `vitest: command not found` because a fresh\nworktree had no dependencies. The fix was:\n\n bun install --frozen-lockfile\n\nA hook that cannot run is a broken toolchain, not a gate to step over. If\nthe hooks are wrong, fix the hooks or say so -- both leave a trace, and\nthat trace is the entire point.\n\nThere is deliberately NO bypass marker. A gate whose refusal hands you the\nway around it is not a gate (DOJ-6247).\n",
"tests": [
{
"name": "commit-long-flag-blocked",
"input": {
"tool_input": {
"command": "git commit --no-verify -m 'wip'"
}
},
"expected_exit": 2
},
{
"name": "commit-short-flag-blocked",
"input": {
"tool_input": {
"command": "git commit -n -m 'wip'"
}
},
"expected_exit": 2
},
{
"name": "push-long-flag-blocked",
"input": {
"tool_input": {
"command": "git push --no-verify origin main"
}
},
"expected_exit": 2
},
{
"name": "push-dry-run-allowed",
"input": {
"tool_input": {
"command": "git push -n origin main"
}
},
"expected_exit": 0
},
{
"name": "ordinary-commit-allowed",
"input": {
"tool_input": {
"command": "git commit -m 'feat: add thing'"
}
},
"expected_exit": 0
},
{
"name": "quoted-mention-allowed",
"input": {
"tool_input": {
"command": "grep -rn '--no-verify' docs/"
}
},
"expected_exit": 0
}
]
},
{
"id": "block-git-force-push-no-lease",
"description": "Block `git push --force` / `-f` without `--force-with-lease` (overwrites collaborator pushes silently)",
Expand Down
67 changes: 67 additions & 0 deletions hooks/rules/rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,73 @@
command: 'npx playwright test # hook-bypass: playwright-headless-allowed'
expected_exit: 0

- id: block-no-verify
description: Block a commit or push that skips the hooks
applies_to: [Bash]
match:
# `git commit -n` IS --no-verify. `git push -n` is --dry-run and must NOT
# match, so the short form is scoped to commit only. Two flags, one letter,
# opposite meanings -- the same near-miss shape the force-push rule guards.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 P2 (major) — False Positive Risk on Commit Messages. The pattern matches ' -n ' or '--no-verify' regardless of whether they are inside a commit message (e.g., git commit -m "feat: support -n in client"). Since 'bypass_marker' is set to null, a developer running a completely valid commit with such a message will be blocked with no way to bypass. Consider either refining the regex to avoid matching inside quoted strings, or introducing a bypass_marker (e.g., 'no-verify-allowed') to let developers unblock themselves in case of false positives.

[pass 1]

- field: command
pattern: '(git[[:space:]]+(commit|push)[^|;&]*--no-verify|git[[:space:]]+commit[^|;&]*[[:space:]]-n([[:space:]]|$))'
# Mention is not execution. A quoted occurrence -- documenting the flag,
# grepping for it, writing a rule about it -- performs no skip.
- field: command
not_pattern: "['\\\"]--no-verify"
action: block
bypass_marker: null
memory_ref: feedback_agents_never_self_authorize_documented_overrides.md
references:
- "dojo-os CLAUDE.md non-negotiable 21"
message: |
BLOCKED: this skips the hooks.

The hooks are the only thing standing between a commit and the checks it
was supposed to pass. Skipping them does not make a commit faster -- it
makes an UNVERIFIED commit indistinguishable from a verified one, and
nothing downstream can tell them apart afterwards.

Non-negotiable 21 names this flag alongside --admin and --force. Those
three had rules; this one did not, which is why you are reading a new
message. An agent used it on 2026-08-02, reported it, and reverted it.

THE HOOKS FAILING IS NOT A REASON TO SKIP THEM. In that same incident the
honest attempt failed with `vitest: command not found` because a fresh
worktree had no dependencies. The fix was:

bun install --frozen-lockfile

A hook that cannot run is a broken toolchain, not a gate to step over. If
the hooks are wrong, fix the hooks or say so -- both leave a trace, and
that trace is the entire point.

There is deliberately NO bypass marker. A gate whose refusal hands you the
way around it is not a gate (DOJ-6247).
tests:
- name: commit-long-flag-blocked
input: { tool_input: { command: "git commit --no-verify -m 'wip'" } }
expected_exit: 2
- name: commit-short-flag-blocked
input: { tool_input: { command: "git commit -n -m 'wip'" } }
expected_exit: 2
- name: push-long-flag-blocked
input: { tool_input: { command: "git push --no-verify origin main" } }
expected_exit: 2
# THE NEAR-MISS THIS RULE MUST NOT GET WRONG. `-n` is --no-verify on
# commit and --dry-run on push: same letter, opposite meaning. Blocking a
# dry-run would refuse the safest command in git, and a guard that refuses
# ordinary work gets bypassed.
- name: push-dry-run-allowed
input: { tool_input: { command: "git push -n origin main" } }
expected_exit: 0
- name: ordinary-commit-allowed
input: { tool_input: { command: "git commit -m 'feat: add thing'" } }
expected_exit: 0
# Mention is not execution: documenting the flag performs no skip.
- name: quoted-mention-allowed
input: { tool_input: { command: "grep -rn '--no-verify' docs/" } }
expected_exit: 0

- id: block-git-force-push-no-lease
description: Block `git push --force` / `-f` without `--force-with-lease` (overwrites collaborator pushes silently)
applies_to: [Bash]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lapc506/make-no-mistakes",
"version": "1.38.0",
"version": "1.41.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 P2 (major) — Missing Version Update in README.md. The version manifests (package.json, plugin.json, marketplace.json) are bumped to 1.41.0, but README.md is not updated in this PR (still refers to 1.38.0). This violates the repo's own 'warn-version-readme-changelog-sync' rule/guideline. Please update the README.md version header to 1.41.0 to ensure consistent versioning across all surfaces.

[pass 1]

"description": "The disciplined dev lifecycle — implement issues, review PRs, sync releases, test E2E, manage sessions, stash secrets, and enforce manifest-driven tool-call hooks (no SSH+DB, no manual prod, no minified build, no secret leaks, Slack format). OpenCode + Claude Code plugin.",
"type": "module",
"main": "./dist/index.js",
Expand Down
Loading