@dalzoubi/dev-agents-sync 3.0.3 → 3.0.4
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.
package/README.md
CHANGED
|
@@ -113,7 +113,7 @@ The CLI seeds a blank steering scaffold under `.claude/steering/` — `decisions
|
|
|
113
113
|
|
|
114
114
|
### Hook scripts (managed)
|
|
115
115
|
|
|
116
|
-
`init` and `update` install the toolkit's hook scripts as marker-managed, lockfile-tracked executable files: `.claude/hooks/` for Claude and `.codex/hooks/` for Codex. Most are **warning** hooks: they print one line to stderr and always exit 0.
|
|
116
|
+
`init` and `update` install the toolkit's hook scripts as marker-managed, lockfile-tracked executable files: `.claude/hooks/` for Claude and `.codex/hooks/` for Codex. Most are **warning** hooks: they print one line to stderr and always exit 0. Four are **blocking** hooks that can deny a tool call outright. Claude registrations are merged into `.claude/settings.json`; Codex registrations ship as managed `.codex/hooks.json` plus `.codex/hook-adapter.mjs`.
|
|
117
117
|
|
|
118
118
|
| Script | Event | Matcher | Mode | What it does |
|
|
119
119
|
|---|---|---|---|---|
|
|
@@ -121,6 +121,7 @@ The CLI seeds a blank steering scaffold under `.claude/steering/` — `decisions
|
|
|
121
121
|
| `managed-file-guard.sh` | `PostToolUse` | `Edit\|Write` | warning | Guards managed files against unexpected edits. |
|
|
122
122
|
| `uncommitted-check.sh` | `Stop` | `.*` | warning | Flags uncommitted work when a session ends. |
|
|
123
123
|
| `force-push-guard.sh` | `PreToolUse` | `Bash` | **blocking** | Denies `git push` carrying `--force` / `-f` / `--force-with-lease` at `main` or `master` (by explicit refspec, or by the checked-out branch when the push names no ref). Force-pushing a feature branch, and a plain push to `main`, both pass. |
|
|
124
|
+
| `direct-push-guard.sh` | `PreToolUse` | `Bash` | **blocking** | Denies ANY `git push` — force or not — at `main`, `master`, or `develop` (by explicit refspec, or by the checked-out branch when the push names no ref). Pushing a feature branch passes; open a pull request instead. |
|
|
124
125
|
| `spec-approval-gate.sh` | `PreToolUse` | `Edit\|Write` | **blocking** | Denies an edit that sets a spec to `Status: Approved` while an unresolved clarification marker — a bare bracketed `NEEDS CLARIFICATION` token — remains in prose. Occurrences inside code spans or fenced blocks are documentation and never match. |
|
|
125
126
|
| `handoff-state-guard.sh` | `PreToolUse` | `Write` | **blocking** | Denies a write to `.claude/state/*.json` whose `handoff.status`, `from_agent`, or `to_agent` is outside the vocabulary `.claude/rules/handoff.md` defines. |
|
|
126
127
|
| `spec-drift-warn.sh` | `PostToolUse` | `Edit\|Write` | warning | After an edit to `spec.md` / `design.md` / `tasks.md` under `docs/specs/`, warns when that folder's `spec.md` has already moved past `Draft`. Draft folders stay silent. |
|
|
@@ -137,6 +138,7 @@ A blocking hook runs on `PreToolUse`, where exiting 2 denies the tool call and t
|
|
|
137
138
|
| Code | Raised by | Example message |
|
|
138
139
|
|---|---|---|
|
|
139
140
|
| `EHOOK_FORCE_PUSH` | `force-push-guard.sh` | `blocked: EHOOK_FORCE_PUSH — force-push to protected branch 'main' — push without a force flag or open a pull request; to override, set DEV_AGENTS_HOOKS_BYPASS=force-push-guard` |
|
|
141
|
+
| `EHOOK_DIRECT_PUSH` | `direct-push-guard.sh` | `blocked: EHOOK_DIRECT_PUSH — direct push to protected branch 'main' — open a pull request instead; to override, set DEV_AGENTS_HOOKS_BYPASS=direct-push-guard` |
|
|
140
142
|
| `EHOOK_SPEC_APPROVAL` | `spec-approval-gate.sh` | `blocked: EHOOK_SPEC_APPROVAL — <path> sets Status: Approved while an unresolved clarification marker (a bare bracketed NEEDS CLARIFICATION token) remains in prose — resolve it via /define-analyze or /define before approving; to override, set DEV_AGENTS_HOOKS_BYPASS=spec-approval-gate` |
|
|
141
143
|
| `EHOOK_HANDOFF_STATE` | `handoff-state-guard.sh` | `blocked: EHOOK_HANDOFF_STATE — handoff.status "done" is outside the status enum — fix the value in the state file before writing, or re-run with DEV_AGENTS_HOOKS_BYPASS=handoff-state-guard` |
|
|
142
144
|
|
package/package.json
CHANGED
package/src/hook-manifest.mjs
CHANGED
|
@@ -9,6 +9,7 @@ export const HOOK_MANIFEST = Object.freeze([
|
|
|
9
9
|
{ event: 'PostToolUse', matcher: 'Edit|Write', file: 'managed-file-guard.sh' },
|
|
10
10
|
{ event: 'Stop', matcher: '.*', file: 'uncommitted-check.sh' },
|
|
11
11
|
{ event: 'PreToolUse', matcher: 'Bash', file: 'force-push-guard.sh' },
|
|
12
|
+
{ event: 'PreToolUse', matcher: 'Bash', file: 'direct-push-guard.sh' },
|
|
12
13
|
{ event: 'PreToolUse', matcher: 'Edit|Write', file: 'spec-approval-gate.sh' },
|
|
13
14
|
{ event: 'PreToolUse', matcher: 'Write', file: 'handoff-state-guard.sh' },
|
|
14
15
|
{ event: 'PostToolUse', matcher: 'Edit|Write', file: 'spec-drift-warn.sh' },
|
package/src/settings.mjs
CHANGED
|
@@ -496,4 +496,9 @@ export const RETIRED_HOOK_SCRIPTS = [
|
|
|
496
496
|
// or by a future regression, and pruning it is always correct since that form
|
|
497
497
|
// is never in DEFAULT_HOOK_SCRIPTS.
|
|
498
498
|
{ event: 'Stop', matcher: '.*', command: '.claude/hooks/ui-verification-reminder.sh' },
|
|
499
|
+
// direct-push-guard.sh ships only in the `bash …` form — same reasoning as
|
|
500
|
+
// ui-verification-reminder.sh above: it never shipped bare, but the
|
|
501
|
+
// bare-path form is pruned defensively so a hand-edit or regression can't
|
|
502
|
+
// register it live alongside the real one.
|
|
503
|
+
{ event: 'PreToolUse', matcher: 'Bash', command: '.claude/hooks/direct-push-guard.sh' },
|
|
499
504
|
];
|
|
@@ -295,10 +295,10 @@ describe('W2 — init and update install and wire every registered hook', () =>
|
|
|
295
295
|
}
|
|
296
296
|
});
|
|
297
297
|
|
|
298
|
-
it('W2d:
|
|
299
|
-
// force-push-guard and pre-pr-preflight share
|
|
300
|
-
// identity is the COMMAND, so
|
|
301
|
-
// event+matcher would silently drop one.
|
|
298
|
+
it('W2d: all three Bash PreToolUse hooks are wired (a shared event+matcher is not deduped)', async () => {
|
|
299
|
+
// force-push-guard, direct-push-guard, and pre-pr-preflight all share
|
|
300
|
+
// PreToolUse/Bash. Merge identity is the COMMAND, so all three must
|
|
301
|
+
// survive — collapsing on event+matcher would silently drop one.
|
|
302
302
|
await runInit(consumerDir, {
|
|
303
303
|
targets: ['claude'],
|
|
304
304
|
fetcher: makeFixtureFetcher(),
|
|
@@ -312,10 +312,11 @@ describe('W2 — init and update install and wire every registered hook', () =>
|
|
|
312
312
|
assert.deepEqual(
|
|
313
313
|
commands,
|
|
314
314
|
[
|
|
315
|
+
expectedCommand('.claude/hooks/direct-push-guard.sh'),
|
|
315
316
|
expectedCommand('.claude/hooks/force-push-guard.sh'),
|
|
316
317
|
expectedCommand('.claude/hooks/pre-pr-preflight.sh'),
|
|
317
318
|
],
|
|
318
|
-
'
|
|
319
|
+
'all three PreToolUse/Bash hooks must be wired independently',
|
|
319
320
|
);
|
|
320
321
|
});
|
|
321
322
|
|