@eventmodelers/cli 1.0.51 → 1.0.53

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventmodelers/cli",
3
- "version": "1.0.51",
3
+ "version": "1.0.53",
4
4
  "description": "Eventmodelers CLI — real-time Claude agent + skills for Claude Code, for any stack (Node, Supabase, Axon, Cratis, OpenCQRS, UmaDB, Kurrent, or modeling-only)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,7 +31,7 @@ If not tasked explicitely to change routes, ignore routes*.ts
31
31
 
32
32
  Ignore case for files and slices in prompts. "CartItems" slice is the same as "cartitems"
33
33
 
34
- Do not change files with tests unless explicitely instructed: *.test.ts
34
+ Do not change files with tests unless explicitely instructed, or the change brings the test in line with slice.json (e.g. step 4's field/spec diff): *.test.ts
35
35
 
36
36
  At the start of every session, read `.build-kit/AGENTS.md` if it exists to load accumulated project learnings.
37
37
 
@@ -62,7 +62,7 @@ specific package.
62
62
 
63
63
  Ignore case for files and slices in prompts. "CartItems" slice is the same as "cartitems".
64
64
 
65
- Do not change test files unless explicitly instructed: `src/test/java/**/*Test.java`.
65
+ Do not change test files unless explicitly instructed, or the change brings the test in line with slice.json (e.g. step 4's field/spec diff): `src/test/java/**/*Test.java`.
66
66
 
67
67
  At the start of every session, read `.build-kit/AGENTS.md` if it exists to load accumulated project
68
68
  learnings.
@@ -24,7 +24,7 @@ If not tasked explicitely to change routes, ignore routes*.ts
24
24
 
25
25
  Ignore case for files and slices in prompts. "CartItems" slice is the same as "cartitems"
26
26
 
27
- Do not change files with tests unless explicitely instructed: *.test.ts
27
+ Do not change files with tests unless explicitely instructed, or the change brings the test in line with slice.json (e.g. step 4's field/spec diff): *.test.ts
28
28
 
29
29
  At the start of every session, read `.build-kit/AGENTS.md` if it exists to load accumulated project learnings.
30
30
 
@@ -76,8 +76,10 @@ It loads every check under `.build-kit/lib/checks/` and rejects the commit if an
76
76
 
77
77
  If a commit is rejected, split it — commit the out-of-scope file separately from the slice work, or add
78
78
  the missing test/fix the field — rather than passing `--no-verify`. Run `npm run run:checks` any time
79
- you want to check staged files before committing. To add a new check, read
80
- `.build-kit/lib/checks/README.md` and drop in a file following its interface no other wiring needed.
79
+ you want to check your current work (by default this checks every uncommitted change — staged,
80
+ unstaged, and untracked; pass `-- --staged` to check only what's staged, matching what the pre-commit
81
+ hook itself checks). To add a new check, read `.build-kit/lib/checks/README.md` and drop in a file
82
+ following its interface — no other wiring needed.
81
83
 
82
84
  ## Example Slice Structure
83
85
 
@@ -2,7 +2,9 @@
2
2
  'use strict';
3
3
 
4
4
  // Runner for the slice commit-scope guard. Loads every check module from
5
- // ./checks/*.cjs and runs it against the currently staged changeset.
5
+ // ./checks/*.cjs and runs it against the currently changed files — every
6
+ // uncommitted change (staged + unstaged + untracked) by default, or just
7
+ // the staged changeset with --staged.
6
8
  //
7
9
  // Check interface (see ./checks/README.md for the full contract + a template):
8
10
  // module.exports = {
@@ -16,7 +18,8 @@
16
18
  // `run()` returns an array of violations (empty array/undefined/null = pass).
17
19
  //
18
20
  // `ctx` passed to every check:
19
- // changes [{status, path}] — staged files (git status letter + path)
21
+ // changes [{status, path}] — changed files (git status letter + path);
22
+ // all uncommitted changes by default, staged-only with --staged
20
23
  // touchesSlice true — this commit touches src/slices/{context}/{slice}/**
21
24
  // (the runner already gates on this before loading checks)
22
25
  // repoRoot absolute path to the repo root
@@ -24,7 +27,7 @@
24
27
  //
25
28
  // Zero dependencies — plain Node, so it works from git's pre-commit hook
26
29
  // (see ../../.githooks/pre-commit), from `npm run run:checks`, or from CI.
27
- // Invoked as: node .build-kit/lib/check-commit-scope.cjs
30
+ // Invoked as: node .build-kit/lib/check-commit-scope.cjs [--staged]
28
31
 
29
32
  const { execSync } = require('child_process');
30
33
  const fs = require('fs');
@@ -32,8 +35,7 @@ const path = require('path');
32
35
 
33
36
  const SLICE_PATTERN = /^src\/slices\/[^/]+\/[^/]+\//;
34
37
 
35
- function stagedChanges() {
36
- const out = execSync('git diff --cached --name-status --no-renames', { encoding: 'utf8' });
38
+ function parseNameStatus(out) {
37
39
  return out
38
40
  .split('\n')
39
41
  .filter(Boolean)
@@ -43,6 +45,21 @@ function stagedChanges() {
43
45
  });
44
46
  }
45
47
 
48
+ function stagedChanges() {
49
+ return parseNameStatus(execSync('git diff --cached --name-status --no-renames', { encoding: 'utf8' }));
50
+ }
51
+
52
+ function allChanges() {
53
+ // Working tree vs HEAD already covers both staged and unstaged edits to
54
+ // tracked files; untracked (never-`git add`ed) files need a separate call.
55
+ const tracked = parseNameStatus(execSync('git diff HEAD --name-status --no-renames', { encoding: 'utf8' }));
56
+ const untracked = execSync('git ls-files --others --exclude-standard', { encoding: 'utf8' })
57
+ .split('\n')
58
+ .filter(Boolean)
59
+ .map((p) => ({ status: 'A', path: p }));
60
+ return [...tracked, ...untracked];
61
+ }
62
+
46
63
  function loadChecks() {
47
64
  const checksDir = path.join(__dirname, 'checks');
48
65
  if (!fs.existsSync(checksDir)) return [];
@@ -68,11 +85,12 @@ function loadChecks() {
68
85
  }
69
86
 
70
87
  function main() {
88
+ const staged = process.argv.includes('--staged');
71
89
  let changes;
72
90
  try {
73
- changes = stagedChanges();
91
+ changes = staged ? stagedChanges() : allChanges();
74
92
  } catch (err) {
75
- console.error('check-commit-scope: could not read staged changes ', err.message);
93
+ console.error(`check-commit-scope: could not read ${staged ? 'staged' : 'uncommitted'} changes —`, err.message);
76
94
  process.exit(1);
77
95
  }
78
96
 
@@ -14,15 +14,38 @@ const ALLOWED_EXCEPTIONS = [
14
14
 
15
15
  const MIGRATION_PATTERN = /^migrations\/V\d+__.*\.sql$/;
16
16
 
17
+ // Captures the {context}/{slice} segment so files from two different slices
18
+ // in one commit can be told apart — SLICE_PATTERN alone only proves a path is
19
+ // *inside some* slice folder, not which one.
20
+ const SLICE_KEY_PATTERN = /^src\/slices\/([^/]+\/[^/]+)\//;
21
+
17
22
  module.exports = {
18
23
  name: 'slice-scope',
19
24
  run(ctx) {
20
25
  const violations = [];
26
+
27
+ const sliceKeys = new Set();
28
+ for (const { path: p } of ctx.changes) {
29
+ const m = p.match(SLICE_KEY_PATTERN);
30
+ if (m) sliceKeys.add(m[1]);
31
+ }
32
+ const primarySlice = [...sliceKeys].sort()[0] || null;
33
+
21
34
  for (const { path: p } of ctx.changes) {
22
- if (ctx.SLICE_PATTERN.test(p)) continue;
23
35
  if (MIGRATION_PATTERN.test(p)) continue;
24
36
  if (ALLOWED_EXCEPTIONS.some((r) => r.test(p))) continue;
25
- violations.push({ path: p, reason: 'outside src/slices/{context}/{slice}/ and not a documented exception' });
37
+
38
+ const m = p.match(SLICE_KEY_PATTERN);
39
+ if (!m) {
40
+ violations.push({ path: p, reason: 'outside src/slices/{context}/{slice}/ and not a documented exception' });
41
+ continue;
42
+ }
43
+ if (m[1] !== primarySlice) {
44
+ violations.push({
45
+ path: p,
46
+ reason: `touches slice "${m[1]}" but this commit's scope is "${primarySlice}" — split into separate commits`,
47
+ });
48
+ }
26
49
  }
27
50
  return violations;
28
51
  },
@@ -7,5 +7,5 @@ repo_root=$(git rev-parse --show-toplevel)
7
7
  script="$repo_root/.build-kit/lib/check-commit-scope.cjs"
8
8
 
9
9
  if [ -f "$script" ]; then
10
- node "$script"
10
+ node "$script" --staged
11
11
  fi
@@ -48,7 +48,7 @@ package.
48
48
 
49
49
  Ignore case for files and slices in prompts. "CartItems" slice is the same as "cartitems".
50
50
 
51
- Do not change test files unless explicitly instructed: `src/test/java/**/*Test.java`.
51
+ Do not change test files unless explicitly instructed, or the change brings the test in line with slice.json (e.g. step 4's field/spec diff): `src/test/java/**/*Test.java`.
52
52
 
53
53
  At the start of every session, read `.build-kit/AGENTS.md` if it exists to load accumulated project
54
54
  learnings.
@@ -24,7 +24,7 @@ If not tasked explicitely to change routes, ignore routes*.ts
24
24
 
25
25
  Ignore case for files and slices in prompts. "CartItems" slice is the same as "cartitems"
26
26
 
27
- Do not change files with tests unless explicitely instructed: *.test.ts
27
+ Do not change files with tests unless explicitely instructed, or the change brings the test in line with slice.json (e.g. step 4's field/spec diff): *.test.ts
28
28
 
29
29
  At the start of every session, read `.build-kit/AGENTS.md` if it exists to load accumulated project learnings.
30
30
 
@@ -80,8 +80,10 @@ and rejects the commit if any of them find a problem:
80
80
 
81
81
  If a commit is rejected, split it — commit the out-of-scope file separately from the slice work, or add
82
82
  the missing test/fix the field — rather than passing `--no-verify`. Run `npm run run:checks` any time
83
- you want to check staged files before committing. To add a new check, read
84
- `.build-kit/lib/checks/README.md` and drop in a file following its interface no other wiring needed.
83
+ you want to check your current work (by default this checks every uncommitted change — staged,
84
+ unstaged, and untracked; pass `-- --staged` to check only what's staged, matching what the pre-commit
85
+ hook itself checks). To add a new check, read `.build-kit/lib/checks/README.md` and drop in a file
86
+ following its interface — no other wiring needed.
85
87
 
86
88
  ## Example Slice Structure
87
89
 
@@ -2,7 +2,9 @@
2
2
  'use strict';
3
3
 
4
4
  // Runner for the slice commit-scope guard. Loads every check module from
5
- // ./checks/*.cjs and runs it against the currently staged changeset.
5
+ // ./checks/*.cjs and runs it against the currently changed files — every
6
+ // uncommitted change (staged + unstaged + untracked) by default, or just
7
+ // the staged changeset with --staged.
6
8
  //
7
9
  // Check interface (see ./checks/README.md for the full contract + a template):
8
10
  // module.exports = {
@@ -16,7 +18,8 @@
16
18
  // `run()` returns an array of violations (empty array/undefined/null = pass).
17
19
  //
18
20
  // `ctx` passed to every check:
19
- // changes [{status, path}] — staged files (git status letter + path)
21
+ // changes [{status, path}] — changed files (git status letter + path);
22
+ // all uncommitted changes by default, staged-only with --staged
20
23
  // touchesSlice true — this commit touches src/slices/{context}/{slice}/**
21
24
  // (the runner already gates on this before loading checks)
22
25
  // repoRoot absolute path to the repo root
@@ -24,7 +27,7 @@
24
27
  //
25
28
  // Zero dependencies — plain Node, so it works from git's pre-commit hook
26
29
  // (see ../../.githooks/pre-commit), from `npm run run:checks`, or from CI.
27
- // Invoked as: node .build-kit/lib/check-commit-scope.cjs
30
+ // Invoked as: node .build-kit/lib/check-commit-scope.cjs [--staged]
28
31
 
29
32
  const { execSync } = require('child_process');
30
33
  const fs = require('fs');
@@ -35,8 +38,7 @@ const SLICE_PATTERN = /^src\/slices\/[^/]+\/[^/]+\//;
35
38
  // of its own — still counts as "this is a slice commit" for the gate below.
36
39
  const WEBHOOK_FUNCTION_PATTERN = /^supabase\/functions\/[^/]+\/index\.ts$/;
37
40
 
38
- function stagedChanges() {
39
- const out = execSync('git diff --cached --name-status --no-renames', { encoding: 'utf8' });
41
+ function parseNameStatus(out) {
40
42
  return out
41
43
  .split('\n')
42
44
  .filter(Boolean)
@@ -46,6 +48,21 @@ function stagedChanges() {
46
48
  });
47
49
  }
48
50
 
51
+ function stagedChanges() {
52
+ return parseNameStatus(execSync('git diff --cached --name-status --no-renames', { encoding: 'utf8' }));
53
+ }
54
+
55
+ function allChanges() {
56
+ // Working tree vs HEAD already covers both staged and unstaged edits to
57
+ // tracked files; untracked (never-`git add`ed) files need a separate call.
58
+ const tracked = parseNameStatus(execSync('git diff HEAD --name-status --no-renames', { encoding: 'utf8' }));
59
+ const untracked = execSync('git ls-files --others --exclude-standard', { encoding: 'utf8' })
60
+ .split('\n')
61
+ .filter(Boolean)
62
+ .map((p) => ({ status: 'A', path: p }));
63
+ return [...tracked, ...untracked];
64
+ }
65
+
49
66
  function loadChecks() {
50
67
  const checksDir = path.join(__dirname, 'checks');
51
68
  if (!fs.existsSync(checksDir)) return [];
@@ -71,11 +88,12 @@ function loadChecks() {
71
88
  }
72
89
 
73
90
  function main() {
91
+ const staged = process.argv.includes('--staged');
74
92
  let changes;
75
93
  try {
76
- changes = stagedChanges();
94
+ changes = staged ? stagedChanges() : allChanges();
77
95
  } catch (err) {
78
- console.error('check-commit-scope: could not read staged changes ', err.message);
96
+ console.error(`check-commit-scope: could not read ${staged ? 'staged' : 'uncommitted'} changes —`, err.message);
79
97
  process.exit(1);
80
98
  }
81
99
 
@@ -18,16 +18,39 @@ const ALLOWED_EXCEPTIONS = [
18
18
 
19
19
  const MIGRATION_PATTERN = /^supabase\/migrations\/V\d+__.*\.sql$/;
20
20
 
21
+ // Captures the {context}/{slice} segment so files from two different slices
22
+ // in one commit can be told apart — SLICE_PATTERN alone only proves a path is
23
+ // *inside some* slice folder, not which one.
24
+ const SLICE_KEY_PATTERN = /^src\/slices\/([^/]+\/[^/]+)\//;
25
+
21
26
  module.exports = {
22
27
  name: 'slice-scope',
23
28
  run(ctx) {
24
29
  const violations = [];
30
+
31
+ const sliceKeys = new Set();
32
+ for (const { path: p } of ctx.changes) {
33
+ const m = p.match(SLICE_KEY_PATTERN);
34
+ if (m) sliceKeys.add(m[1]);
35
+ }
36
+ const primarySlice = [...sliceKeys].sort()[0] || null;
37
+
25
38
  for (const { path: p } of ctx.changes) {
26
- if (ctx.SLICE_PATTERN.test(p)) continue;
27
39
  if (WEBHOOK_FUNCTION_PATTERN.test(p)) continue;
28
40
  if (MIGRATION_PATTERN.test(p)) continue;
29
41
  if (ALLOWED_EXCEPTIONS.some((r) => r.test(p))) continue;
30
- violations.push({ path: p, reason: 'outside src/slices/{context}/{slice}/ and not a documented exception' });
42
+
43
+ const m = p.match(SLICE_KEY_PATTERN);
44
+ if (!m) {
45
+ violations.push({ path: p, reason: 'outside src/slices/{context}/{slice}/ and not a documented exception' });
46
+ continue;
47
+ }
48
+ if (m[1] !== primarySlice) {
49
+ violations.push({
50
+ path: p,
51
+ reason: `touches slice "${m[1]}" but this commit's scope is "${primarySlice}" — split into separate commits`,
52
+ });
53
+ }
31
54
  }
32
55
  return violations;
33
56
  },
@@ -7,5 +7,5 @@ repo_root=$(git rev-parse --show-toplevel)
7
7
  script="$repo_root/.build-kit/lib/check-commit-scope.cjs"
8
8
 
9
9
  if [ -f "$script" ]; then
10
- node "$script"
10
+ node "$script" --staged
11
11
  fi
@@ -37,7 +37,7 @@ other specific package.
37
37
 
38
38
  Ignore case for files and slices in prompts. "CartItems" slice is the same as "cartitems".
39
39
 
40
- Do not change test files unless explicitly instructed.
40
+ Do not change test files unless explicitly instructed, or the change brings the test in line with slice.json (e.g. step 4's field/spec diff).
41
41
 
42
42
  At the start of every session, read `.build-kit/AGENTS.md` if it exists to load accumulated project learnings.
43
43