@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. Three 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`.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dalzoubi/dev-agents-sync",
3
- "version": "3.0.3",
3
+ "version": "3.0.4",
4
4
  "type": "module",
5
5
  "description": "CLI that syncs managed dev-agent workflows into Claude Code, Cursor, Copilot, and Codex projects.",
6
6
  "license": "UNLICENSED",
@@ -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: the two Bash PreToolUse hooks are both wired (a shared event+matcher is not deduped)', async () => {
299
- // force-push-guard and pre-pr-preflight share PreToolUse/Bash. Merge
300
- // identity is the COMMAND, so both must survive — collapsing on
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
- 'both PreToolUse/Bash hooks must be wired independently',
319
+ 'all three PreToolUse/Bash hooks must be wired independently',
319
320
  );
320
321
  });
321
322