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
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.21.0",
"version": "1.22.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
99 changes: 97 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,99 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.22.0] - 2026-05-29

### Added

- **Cure 4b cross-cutting PreToolUse hooks (DOJ-4571).** Three generalized
hooks distributed via the toolkit so every consumer repo inherits
cross-cutting defenses, parametrized via a per-repo opt-in config file at
`.claude/config/cross-cutting-hooks.json`. File absence → all three hooks
no-op (full backward compatibility). Hooks live in
`hooks/cross-cutting/` alongside the existing manifest-driven rules:

- `pre-write-no-cleartext-secret-in-config.sh` — blocks Write/Edit/
MultiEdit of JSON/YAML/TOML/env config files that introduce
`${...KEY|SECRET|TOKEN|PASSWORD|...}` placeholders without the
cure-shape `_FILE` / `_PATH` suffix. Generalized from DOJ-4554's
openclaw.json-specific version (PR #266 in
`dojo-agent-openclaw-plugin`).
- `pre-write-cross-repo-schema-ownership.sh` — blocks new SQL
migrations for tables not owned by this repo, per a config-driven
`owned_tables` allowlist + `migration_paths` glob. Empty allowlist
blocks every migration in the configured paths (the gateway pattern,
where the repo has no migration pipeline). Generalized from
DOJ-4554's `pre-write-plugin-side-migration.sh`.
- `pre-write-version-bump-discipline.sh` — blocks multi-step version
bumps on any pinned dependency by delegating to a per-repo validator
script. Each entry in the `version_bumps` array names a file
pattern, version-extraction regex, and validator script. Old version
is read from the git HEAD blob; new version from the proposed
content; both via bash native `=~` matching (avoids sed-delimiter
clashes with regexes containing `/`).

- **Per-surface `defer_to_local_hook` flag (belt-and-braces).** Repos
that already have a tighter Cure 4a hook for one of these surfaces
(currently only `dojo-agent-openclaw-plugin`) set
`defer_to_local_hook: true` on the matching config block. The 4b hook
emits an info-stderr and fail-opens; the 4a hook owns enforcement.
Lets the config block stay live (visible, documented, ready for the
day 4a is retired) without firing the looser 4b version.

- **Schema:** `schemas/cross-cutting-hooks.schema.json` (JSON Schema for
editor autocomplete + CI validation).

- **Bypass markers:** three comment leaders accepted (`#`, `//`, `--`)
so the marker fits whichever syntax the target file uses. Trailing
terminator class extended to include backslash so JSON-serialized
embedded newlines (`marker\n...`) don't break detection.

- **Tests:** `hooks/cross-cutting/tests/test-cross-cutting.sh` — 23
hermetic fixtures (≥7 per hook) spinning up isolated git repos per
case; wired into `npm run test-hooks` after the manifest-rules block.
Total runner now reports 248/248 passing.

- **Docs:** `hooks/cross-cutting/README.md` — opt-in walkthrough,
surface semantics, bypass markers, belt-and-braces with local 4a
hooks, three-layer rollback (per-surface disable /
`CLAUDE_DISABLE_PLUGIN_HOOKS` / plugin pin), fail-open invariants.

### Changed

- `hooks/hooks.json` description updated to surface the new
`hooks/cross-cutting/` directory alongside `hooks/rules/` and
`hooks/atomic/`.
- `hooks/hooks.json` PreToolUse `Write|Edit|MultiEdit|NotebookEdit`
block now registers the 3 cross-cutting scripts AFTER `pre-edit.sh`
and alongside `hooks/atomic/pre-atomic.sh` (manifest-driven rules run
first; atomic-design and cross-cutting hooks layer on as siblings).
- `package.json` `files[]` adds `schemas/` and `references/` so the
JSON Schemas and example configs ship in the npm package (also
benefits `schemas/atomic-design-rules.schema.json` and
`references/atomic-design-rules.example.json` from 1.21.0).

### Notes

- Originally targeted `1.20.0` (per the parallel-version note in 1.21.0);
PR #28 landed first as 1.21.0, so this rebases onto 1.22.0 to preserve
monotonic ordering. No semantic content change vs. the originally
proposed 1.20.0.
- Two review fixes from PR #32 (dojo-code-reviewer): replaced GNU-only
`sed ... //I` with explicit bracket-class spelling (BSD sed
compatibility on macOS); switched HIGH_IMPACT_RE / CURE_RE from
quad-backslash escaping to single-quote-plus-interpolation convention.
- Consumer-repo opt-in (config files in `dojo-os` and
`dojo-agent-openclaw-plugin`) lands in sibling PRs after `1.22.0`
publishes. Per DOJ-4571 belt-and-braces decision,
`dojo-agent-openclaw-plugin` keeps its existing 4a hooks AND opts in
with `defer_to_local_hook: true` on all three surfaces; `dojo-os`
opts in with the 4b hooks owning enforcement.
- Refs: DOJ-4571 (this work), DOJ-4554 (Cure 4a foundation), DOJ-4064
(4-cure thesis), DOJ-4524 (the persistence-freeze incident the
schema-ownership hook prevents), DOJ-4208 (the cleartext-key incident
the cleartext-secret hook prevents), DOJ-4061 (the gateway-version-bump
chain the version-bump hook prevents).

## [1.21.0] - 2026-05-29

### Added
Expand Down Expand Up @@ -53,8 +146,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2026-05-14 audit (pathways, launchpad, community, projects, marketplace,
hackathons, events, agent, dojo-score, plus platform as the shared pillar).
The example only enumerates a subset; consumers configure their own list.
- **Parallel-version coordination:** version `1.20.0` is claimed by the
DOJ-4571 Cure 4b cross-repo hooks PR. This release follows as `1.21.0`.
- **Parallel-version coordination:** version `1.20.0` was originally
reserved for the DOJ-4571 Cure 4b cross-repo hooks PR. PR #28
(this release) landed first as `1.21.0`; DOJ-4571 followed as
`1.22.0` to preserve monotonic ordering. See `[1.22.0]` above.

## [1.19.0] - 2026-05-26

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# make-no-mistakes

**Version: 1.21.0** · [CHANGELOG](./CHANGELOG.md) · [Marketplace](https://github.com/DojoCodingLabs/make-no-mistakes-toolkit)
**Version: 1.22.0** · [CHANGELOG](./CHANGELOG.md) · [Marketplace](https://github.com/DojoCodingLabs/make-no-mistakes-toolkit)

The disciplined dev lifecycle — implement issues, review PRs, sync releases, test E2E, and manage sessions. One plugin to make no mistakes.

Expand Down
203 changes: 203 additions & 0 deletions hooks/cross-cutting/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# Cross-cutting PreToolUse hooks — Cure 4b (DOJ-4571)

These hooks ship as part of the `make-no-mistakes` toolkit and apply to
every repo that installs the plugin. They are **opt-in per repo** via a
single config file at the consumer-repo root.

| File | Purpose | Surface | Source |
|------|---------|---------|--------|
| `pre-write-no-cleartext-secret-in-config.sh` | Block `${...KEY/SECRET/TOKEN/PASSWORD/...}` placeholders in any JSON/YAML/TOML/env config file that the runtime would substitute to disk in cleartext. | `cleartext_secrets` | Generalized from DOJ-4554 hook of the same family in `dojo-agent-openclaw-plugin`. |
| `pre-write-cross-repo-schema-ownership.sh` | Block new SQL migrations for tables this repo does not own. | `schema_ownership` | Generalized from DOJ-4554 `pre-write-plugin-side-migration.sh`. |
| `pre-write-version-bump-discipline.sh` | Block multi-step version bumps in pinned dependencies by delegating to a per-repo validator script. | `version_bumps` | Generalized from DOJ-4554 `pre-write-openclaw-version-bump-discipline.sh`. |

## Opt-in

Create `.claude/config/cross-cutting-hooks.json` at your repo root. File
absence → all three hooks no-op. Minimal opt-in:

```json
{
"$schema": "https://raw.githubusercontent.com/DojoCodingLabs/make-no-mistakes-toolkit/main/schemas/cross-cutting-hooks.schema.json",
"version": 1,
"cleartext_secrets": { "enabled": true }
}
```

Full example (every surface enabled, every override demonstrated):

```json
{
"$schema": "https://raw.githubusercontent.com/DojoCodingLabs/make-no-mistakes-toolkit/main/schemas/cross-cutting-hooks.schema.json",
"version": 1,
"cleartext_secrets": {
"enabled": true,
"defer_to_local_hook": false,
"extra_block_patterns": ["MY_CUSTOM_TOKEN"],
"extra_cure_suffixes": ["_REF", "_VOLUME"]
},
"schema_ownership": {
"enabled": true,
"defer_to_local_hook": false,
"owned_tables": ["chat_sessions", "chat_messages"],
"migration_paths": ["supabase/migrations"]
},
"version_bumps": [
{
"file_pattern": "Dockerfile",
"version_regex": "openclaw/releases/download/(v[0-9]+\\.[0-9]+\\.[0-9]+)/",
"validator_script": "scripts/check-openclaw-version-bump.sh",
"validator_args": [],
"defer_to_local_hook": false
}
]
}
```

JSON Schema for editor autocomplete + CI validation:
[`schemas/cross-cutting-hooks.schema.json`](../../schemas/cross-cutting-hooks.schema.json).

## How each hook works

### `cleartext_secrets`

Triggers on `Write|Edit|MultiEdit` of any file ending in `.json`,
`.jsonc`, `.yaml`, `.yml`, `.toml`, `.env`, or starting with `.env.`.

Built-in blocked tails (case-sensitive, after optional `[A-Z_]*` prefix
and before optional `[A-Z0-9_]*` suffix):

- `SERVICE_ROLE`
- `JWT_SECRET`
- `PRIVATE_KEY`
- `CLIENT_SECRET`
- `ADMIN_TOKEN`
- `PASSWORD`
- `ENCRYPTION_KEY`
- `SIGNING_SECRET`

Built-in cure-shape suffixes (placeholders ending in these PASS):

- `_FILE`
- `_PATH`

Use `extra_block_patterns` and `extra_cure_suffixes` to extend both
sets. The hook only ADDS to built-ins — there is no removal API; use
the bypass marker for one-off overrides.

### `schema_ownership`

Triggers on `Write` only (`Edit`/`MultiEdit` on existing migrations is
allowed — typical for cleanup/annotation of historical artifacts).
Fires only when `FILE_PATH` lives under one of `migration_paths`
(default `["supabase/migrations"]`) AND ends in `.sql`.

Behavior depends on `owned_tables`:

- `[]` → blocks every match (the gateway pattern: no migrations belong
in this repo at all)
- `["table_a", ...]` → extracts `CREATE/ALTER/DROP/RENAME TABLE <name>`
identifiers from the proposed content and blocks if any referenced
name is not in the allowlist

Conservative SQL parsing: only the four statement types above. Migrations
that only define functions, views, policies, or data are allowed (the
ownership check has no signal to act on).

### `version_bumps`

Triggers on `Write|Edit|MultiEdit` of any file whose basename matches a
configured `file_pattern`. For each match:

1. Extract `OLD_VERSION` from the git HEAD blob via the configured
`version_regex` (single capture group).
2. Extract `NEW_VERSION` from the proposed content via the same regex.
3. If both extract, differ, and the `validator_script` is executable,
invoke `<validator_script> <OLD_VERSION> <NEW_VERSION> [extra_args]`.
4. Validator exit codes:
- `0` → pass
- `2` → block (the validator's stderr is shown above the hook's block message)
- any other → warn + fail-open (defense in depth, never block on validator infrastructure)

If `OLD_VERSION` cannot be extracted (e.g. file is new), the hook passes
silently — the rule applies to BUMPS, not introductions.

## Bypass markers

Each hook honors a kebab-case bypass marker matching its surface. Add
the marker as a comment near the offending content:

- `# hook-bypass: cross-cutting-cleartext-secret`
- `# hook-bypass: cross-cutting-schema-ownership`
- `# hook-bypass: cross-cutting-version-bump`

Three comment leaders are accepted so the marker fits whichever syntax
the target file uses:

| Leader | Used in |
|--------|---------|
| `#` | Bash / YAML / TOML / Python (SQL also accepts this) |
| `//` | JSON-with-comments / JS / TS / C-family |
| `--` | SQL / Haskell / Lua |

## Belt-and-braces with local 4a hooks

If your repo already has a tighter `.claude/hooks/`-level 4a hook for
one of these surfaces (the canonical case is
`dojo-agent-openclaw-plugin`), set `defer_to_local_hook: true` on the
matching config block. The 4b hook logs an info-stderr and fail-opens;
the 4a hook owns enforcement. This lets the config block stay live
(visible, documented, ready for the day 4a is retired) without firing
the looser 4b version.

Default `false` → both hooks fire. They produce the same verdict by
construction (4b generalizes 4a) so double-blocks are harmless; the
only user-visible artifact is two stderr blocks instead of one.

## Disabling

Three layers, least to most invasive:

1. **Per surface.** Set `enabled: false` (or omit the key) in the
per-repo config.
2. **All toolkit hooks for the current shell.** Set
`CLAUDE_DISABLE_PLUGIN_HOOKS=1` in your environment.
3. **Plugin pin.** Pin the consumer repo to the pre-Cure-4b toolkit
version (`1.19.0`) in your plugin install command.

A full rollback (delete the config file) is also valid — the hooks
no-op without their config.

## Fail-open invariants

Every hook exits 0 (pass) silently when any of these are true:

- `CLAUDE_DISABLE_PLUGIN_HOOKS=1`
- `jq` not on PATH
- Hook input JSON malformed
- Config file missing
- Config file present but unsupported `version`
- Per-surface `enabled` is false
- Per-surface `defer_to_local_hook` is true (with an info-stderr line)
- `version_bumps`: validator script missing/non-executable

This matches the existing toolkit hook posture (defense in depth, never
a single point of failure).

## Tests

See `hooks/cross-cutting/tests/test-cross-cutting.sh` — invoked by
`npm run test-hooks` alongside the manifest-driven `rules.json` tests.
Coverage: ≥5 fixtures per hook (block on positive, pass on negative,
no-op when disabled, no-op when config missing, bypass marker honored).

## Reference

- DOJ-4571 — this work (Cure 4b)
- DOJ-4554 — Cure 4a foundation in `dojo-agent-openclaw-plugin`
- DOJ-4524 — 15-day persistence-freeze incident that motivated the
schema-ownership hook
- DOJ-4208 — service-role key cleartext-leak incident that motivated
the cleartext-secret hook
- DOJ-4061 — gateway version-bump fix-forward chain that motivated
the version-bump hook
- DOJ-4064 — 4-cure thesis
Loading
Loading