@produck/agent-toolkit 0.9.2 → 0.10.0

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.
@@ -42,6 +42,10 @@ import {
42
42
  printSyncPublishHelp,
43
43
  runSyncPublish,
44
44
  } from './command/sync-publish/index.mjs';
45
+ import {
46
+ printSyncTypescriptHelp,
47
+ runSyncTypescript,
48
+ } from './command/sync-typescript/index.mjs';
45
49
  import { hasFlag, parseCommonArgs } from './command/shared/args.mjs';
46
50
  import {
47
51
  printValidateCommitMsgHelp,
@@ -101,6 +105,10 @@ const COMMANDS = {
101
105
  printHelp: printSyncPublishHelp,
102
106
  run: runSyncPublish,
103
107
  },
108
+ 'sync-typescript': {
109
+ printHelp: printSyncTypescriptHelp,
110
+ run: runSyncTypescript,
111
+ },
104
112
  };
105
113
 
106
114
  const DEFAULT_COMMAND = 'enforce-node-baseline';
@@ -49,6 +49,7 @@ const OUTPUT_LERNA_PATH = path.resolve(
49
49
  PACKAGE_ROOT,
50
50
  'publish-assets/lerna.json',
51
51
  );
52
+ const ROOT_PACKAGE_JSON_PATH = path.resolve(REPO_ROOT, 'package.json');
52
53
  const LEGACY_OUTPUT_PATH = path.resolve(
53
54
  PACKAGE_ROOT,
54
55
  'publish-assets/instructions/org.instructions.md',
@@ -80,6 +81,10 @@ function validateSourceFile(fileName, text) {
80
81
  }
81
82
  }
82
83
 
84
+ function resolveSemverExact(text) {
85
+ return text.replace(/^[\^~>=<]+\s*/, '').trim();
86
+ }
87
+
83
88
  function readAndValidateToolingBaseline() {
84
89
  if (!fs.existsSync(SOURCE_TOOLING_BASELINE_PATH)) {
85
90
  throw new Error(
@@ -98,25 +103,40 @@ function readAndValidateToolingBaseline() {
98
103
  );
99
104
  }
100
105
 
101
- const c8Version = baseline?.tools?.c8?.version;
102
- const lernaVersion = baseline?.tools?.lerna?.version;
103
- const coverageScriptTemplate = baseline?.coverage?.scriptTemplate;
104
-
105
106
  if (typeof baseline.schemaVersion !== 'number') {
106
107
  throw new Error(
107
108
  `Invalid tooling baseline schemaVersion in: ${SOURCE_TOOLING_BASELINE_PATH}`,
108
109
  );
109
110
  }
110
111
 
112
+ // Auto-resolve tool versions: only override version when set to "auto"
113
+ const rootPkg = JSON.parse(fs.readFileSync(ROOT_PACKAGE_JSON_PATH, 'utf8'));
114
+ const devDeps = rootPkg.devDependencies || {};
115
+
116
+ for (const [toolName, entry] of Object.entries(baseline.tools)) {
117
+ if (entry.version === 'auto') {
118
+ const depVersion = devDeps[toolName];
119
+ if (typeof depVersion === 'string' && depVersion.trim()) {
120
+ entry.version = resolveSemverExact(depVersion);
121
+ }
122
+ }
123
+ }
124
+
125
+ const c8Version = baseline?.tools?.c8?.version;
126
+ const lernaVersion = baseline?.tools?.lerna?.version;
127
+ const coverageScriptTemplate = baseline?.coverage?.scriptTemplate;
128
+
111
129
  if (typeof c8Version !== 'string' || c8Version.trim() === '') {
112
130
  throw new Error(
113
- `Invalid tools.c8.version in: ${SOURCE_TOOLING_BASELINE_PATH}`,
131
+ `Invalid tools.c8.version in: ${SOURCE_TOOLING_BASELINE_PATH} ` +
132
+ '(c8 must be listed in root package.json devDependencies)',
114
133
  );
115
134
  }
116
135
 
117
136
  if (typeof lernaVersion !== 'string' || lernaVersion.trim() === '') {
118
137
  throw new Error(
119
- `Invalid tools.lerna.version in: ${SOURCE_TOOLING_BASELINE_PATH}`,
138
+ `Invalid tools.lerna.version in: ${SOURCE_TOOLING_BASELINE_PATH} ` +
139
+ '(lerna must be listed in root package.json devDependencies)',
120
140
  );
121
141
  }
122
142
 
@@ -129,6 +149,7 @@ function readAndValidateToolingBaseline() {
129
149
  );
130
150
  }
131
151
 
152
+ // Dynamically inject @produck/eslint-rules version from its own package.json
132
153
  const eslintRulesPkgPath = path.resolve(
133
154
  PACKAGE_ROOT,
134
155
  '../eslint-rules/package.json',
@@ -146,6 +167,7 @@ function readAndValidateToolingBaseline() {
146
167
  };
147
168
  }
148
169
  }
170
+
149
171
  return `${JSON.stringify(baseline, null, 2)}\n`;
150
172
  }
151
173
 
@@ -7,6 +7,7 @@ agent-toolkit commands:
7
7
  sync-editorconfig
8
8
  sync-git
9
9
  sync-format
10
+ sync-typescript
10
11
  sync-install
11
12
  sync-lint
12
13
  sync-publish
@@ -51,6 +51,35 @@ function parseJsonFile(filePath, label) {
51
51
  }
52
52
  }
53
53
 
54
+ function resolveSemverExact(text) {
55
+ return text.replace(/^[\^~>=<]+\s*/, '').trim();
56
+ }
57
+
58
+ function resolveToolVersionFromDevDeps(baseline, toolName) {
59
+ // If baseline has a concrete version (not "auto"), use it directly.
60
+ // This is the case when reading the published publish-assets baseline.
61
+ const baselineVersion = String(
62
+ baseline?.tools?.[toolName]?.version || '',
63
+ ).trim();
64
+ if (baselineVersion && baselineVersion !== 'auto') {
65
+ return baselineVersion;
66
+ }
67
+
68
+ // Fall back to resolving from local root package.json devDependencies.
69
+ // This covers source baseline with version="auto" during local dev.
70
+ const repoRoot = path.resolve(PACKAGE_ROOT, '../..');
71
+ const pkgJsonPath = path.resolve(repoRoot, 'package.json');
72
+ if (fs.existsSync(pkgJsonPath)) {
73
+ const pkg = parseJsonFile(pkgJsonPath, 'root package.json');
74
+ const dep = pkg?.devDependencies?.[toolName];
75
+ if (typeof dep === 'string' && dep.trim()) {
76
+ return resolveSemverExact(dep);
77
+ }
78
+ }
79
+
80
+ return '';
81
+ }
82
+
54
83
  function loadToolingBaseline() {
55
84
  const toolingBaselinePath = TOOLING_BASELINE_CANDIDATE_PATHS.find(
56
85
  (candidatePath) => {
@@ -76,7 +105,7 @@ function loadToolingBaseline() {
76
105
  process.exit(2);
77
106
  }
78
107
 
79
- const c8Version = baseline?.tools?.c8?.version;
108
+ const c8Version = resolveToolVersionFromDevDeps(baseline, 'c8');
80
109
  if (typeof c8Version !== 'string' || c8Version.trim() === '') {
81
110
  console.error(
82
111
  `Tooling baseline tools.c8.version must be a non-empty string: ${toolingBaselinePath}`,
@@ -1,15 +1,20 @@
1
1
  {
2
+ "branches": 99.5,
2
3
  "check-coverage": true,
3
4
  "exclude": [
4
5
  "**/node_modules/**",
5
6
  "**/coverage/**",
6
7
  "**/dist/**",
7
8
  "**/build/**",
8
- "**/out/**"
9
+ "**/out/**",
10
+ "**/test/**"
9
11
  ],
10
- "reporter": ["lcov", "html", "text-summary"],
11
- "branches": 99.5,
12
12
  "functions": 99.5,
13
- "statements": 99.5,
14
- "lines": 99.5
13
+ "lines": 99.5,
14
+ "reporter": [
15
+ "lcov",
16
+ "html",
17
+ "text-summary"
18
+ ],
19
+ "statements": 99.5
15
20
  }
@@ -99,6 +99,35 @@ function parseJsonFile(filePath, label) {
99
99
  }
100
100
  }
101
101
 
102
+ function resolveSemverExact(text) {
103
+ return text.replace(/^[\^~>=<]+\s*/, '').trim();
104
+ }
105
+
106
+ function resolveToolVersionFromDevDeps(baseline, toolName) {
107
+ // If baseline has a concrete version (not "auto"), use it directly.
108
+ // This is the case when reading the published publish-assets baseline.
109
+ const baselineVersion = String(
110
+ baseline?.tools?.[toolName]?.version || '',
111
+ ).trim();
112
+ if (baselineVersion && baselineVersion !== 'auto') {
113
+ return baselineVersion;
114
+ }
115
+
116
+ // Fall back to resolving from local root package.json devDependencies.
117
+ // This covers source baseline with version="auto" during local dev.
118
+ const repoRoot = path.resolve(PACKAGE_ROOT, '../..');
119
+ const pkgJsonPath = path.resolve(repoRoot, 'package.json');
120
+ if (fs.existsSync(pkgJsonPath)) {
121
+ const pkg = parseJsonFile(pkgJsonPath, 'root package.json');
122
+ const dep = pkg?.devDependencies?.[toolName];
123
+ if (typeof dep === 'string' && dep.trim()) {
124
+ return resolveSemverExact(dep);
125
+ }
126
+ }
127
+
128
+ return '';
129
+ }
130
+
102
131
  function loadToolingBaseline() {
103
132
  const toolingBaselinePath = TOOLING_BASELINE_CANDIDATE_PATHS.find(
104
133
  (candidatePath) => {
@@ -117,9 +146,7 @@ function loadToolingBaseline() {
117
146
  }
118
147
 
119
148
  const baseline = parseJsonFile(toolingBaselinePath, 'Tooling baseline file');
120
- const prettierVersion = String(
121
- baseline?.tools?.prettier?.version || '',
122
- ).trim();
149
+ const prettierVersion = resolveToolVersionFromDevDeps(baseline, 'prettier');
123
150
 
124
151
  if (!prettierVersion) {
125
152
  console.error(
@@ -116,6 +116,35 @@ function getRequiredToolkitDevDependency() {
116
116
  return version;
117
117
  }
118
118
 
119
+ function resolveSemverExact(text) {
120
+ return text.replace(/^[\^~>=<]+\s*/, '').trim();
121
+ }
122
+
123
+ function resolveToolVersionFromDevDeps(baseline, toolName) {
124
+ // If baseline has a concrete version (not "auto"), use it directly.
125
+ // This is the case when reading the published publish-assets baseline.
126
+ const baselineVersion = String(
127
+ baseline?.tools?.[toolName]?.version || '',
128
+ ).trim();
129
+ if (baselineVersion && baselineVersion !== 'auto') {
130
+ return baselineVersion;
131
+ }
132
+
133
+ // Fall back to resolving from local root package.json devDependencies.
134
+ // This covers source baseline with version="auto" during local dev.
135
+ const repoRoot = path.resolve(PACKAGE_ROOT, '../..');
136
+ const pkgJsonPath = path.resolve(repoRoot, 'package.json');
137
+ if (fs.existsSync(pkgJsonPath)) {
138
+ const pkg = parseJsonFile(pkgJsonPath, 'root package.json');
139
+ const dep = pkg?.devDependencies?.[toolName];
140
+ if (typeof dep === 'string' && dep.trim()) {
141
+ return resolveSemverExact(dep);
142
+ }
143
+ }
144
+
145
+ return '';
146
+ }
147
+
119
148
  function loadToolingBaseline() {
120
149
  const toolingBaselinePath = TOOLING_BASELINE_CANDIDATE_PATHS.find(
121
150
  (candidatePath) => {
@@ -134,8 +163,8 @@ function loadToolingBaseline() {
134
163
  }
135
164
 
136
165
  const baseline = parseJsonFile(toolingBaselinePath, 'Tooling baseline file');
137
- const huskyVersion = String(baseline?.tools?.husky?.version || '').trim();
138
- const lernaVersion = String(baseline?.tools?.lerna?.version || '').trim();
166
+ const huskyVersion = resolveToolVersionFromDevDeps(baseline, 'husky');
167
+ const lernaVersion = resolveToolVersionFromDevDeps(baseline, 'lerna');
139
168
 
140
169
  if (!huskyVersion || !lernaVersion) {
141
170
  console.error(
@@ -128,16 +128,38 @@ function getRequiredEslintDevDependencies() {
128
128
  eslintRulesVersion = v;
129
129
  }
130
130
 
131
+ function resolveSemverExact(text) {
132
+ return text.replace(/^[\^~>=<]+\s*/, '').trim();
133
+ }
134
+
135
+ function resolveToolVersionFromDevDeps(name) {
136
+ // If baseline has a concrete version (not "auto"), use it directly.
137
+ // This is the case when reading the published publish-assets baseline.
138
+ const entry = baseline?.tools?.[name];
139
+ const v = typeof entry?.version === 'string' ? entry.version.trim() : '';
140
+ if (v && v !== 'auto') {
141
+ return v;
142
+ }
143
+
144
+ // Fall back to resolving from local root package.json devDependencies.
145
+ // This covers source baseline with version="auto" during local dev.
146
+ const repoRoot = path.resolve(PACKAGE_ROOT, '../..');
147
+ const pkgJsonPath = path.resolve(repoRoot, 'package.json');
148
+ if (fs.existsSync(pkgJsonPath)) {
149
+ const pkg = parseJsonFile(pkgJsonPath, 'root package.json');
150
+ const dep = pkg?.devDependencies?.[name];
151
+ if (typeof dep === 'string' && dep.trim()) {
152
+ return resolveSemverExact(dep);
153
+ }
154
+ }
155
+
156
+ return '';
157
+ }
158
+
131
159
  const deps = { [ESLINT_RULES_PACKAGE_NAME]: eslintRulesVersion };
132
160
 
133
161
  for (const name of ESLINT_TOOLING_PACKAGE_NAMES) {
134
- const entry = baseline?.tools?.[name];
135
- const v =
136
- typeof entry?.version === 'string'
137
- ? entry.version.trim()
138
- : /* c8 ignore next */
139
- '';
140
- /* c8 ignore next 6 */
162
+ const v = resolveToolVersionFromDevDeps(name);
141
163
  if (!v) {
142
164
  console.error(
143
165
  `Tooling baseline tools["${name}"].version must be a non-empty string: ${toolingBaselinePath}`,
@@ -0,0 +1,14 @@
1
+ Usage:
2
+ agent-toolkit sync-typescript --package-root <pkg> [--cwd <dir>]
3
+ [--check] [--dry-run] [--json <file>]
4
+
5
+ Behavior:
6
+ - Creates a tsconfig.json for a sub-package that extends the root
7
+ tsconfig.json with the correct relative path
8
+ - If tsconfig.json already exists, skips without modifying
9
+
10
+ Rules:
11
+ - --package-root is required
12
+ - --check validates without writing and exits non-zero if file is missing
13
+ - --dry-run prints planned changes without writing
14
+ - --check takes precedence over --dry-run
@@ -0,0 +1,154 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ import { getSingle, hasFlag } from '../shared/args.mjs';
6
+ import { printTextResource } from '../shared/text-resource.mjs';
7
+
8
+ const COMMAND_DIR = path.dirname(fileURLToPath(import.meta.url));
9
+ const HELP_FILE = path.resolve(COMMAND_DIR, 'help.txt');
10
+ const TSCONFIG_FILE = 'tsconfig.json';
11
+
12
+ const PACKAGE_TSCONFIG_TEMPLATE = {
13
+ compilerOptions: {
14
+ lib: ['ESNext'],
15
+ types: ['node'],
16
+ strictNullChecks: true,
17
+ allowJs: true,
18
+ noEmit: true,
19
+ module: 'NodeNext',
20
+ },
21
+ };
22
+
23
+ export function printSyncTypescriptHelp() {
24
+ printTextResource(HELP_FILE);
25
+ }
26
+
27
+ function readJsonIfExists(filePath) {
28
+ if (!fs.existsSync(filePath)) {
29
+ return null;
30
+ }
31
+ try {
32
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
33
+ } catch {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ function computeExtendsPath(packageRoot, repoRoot) {
39
+ const relative = path.relative(packageRoot, repoRoot);
40
+ const normalized = relative.replace(/\\/g, '/');
41
+ if (!normalized || normalized === '.') {
42
+ return './tsconfig.json';
43
+ }
44
+ return normalized.startsWith('..')
45
+ ? `${normalized}/tsconfig.json`
46
+ : `./${normalized}/tsconfig.json`;
47
+ }
48
+
49
+ export function runSyncTypescript(options) {
50
+ const cwd = path.resolve(getSingle(options, '--cwd', process.cwd()));
51
+ const check = hasFlag(options, '--check');
52
+ const dryRun = hasFlag(options, '--dry-run') && !check;
53
+ const jsonFile = getSingle(options, '--json', '');
54
+ const packageRoot = getSingle(options, '--package-root', '');
55
+ const mode = check ? 'check' : dryRun ? 'dry-run' : 'sync';
56
+
57
+ if (!packageRoot) {
58
+ console.error('--package-root is required');
59
+ process.exit(2);
60
+ }
61
+
62
+ if (!fs.existsSync(cwd)) {
63
+ console.error(`CWD does not exist: ${cwd}`);
64
+ process.exit(2);
65
+ }
66
+
67
+ const pkgDir = path.resolve(cwd, packageRoot);
68
+ if (!fs.existsSync(pkgDir)) {
69
+ console.error(`Package root does not exist: ${pkgDir}`);
70
+ process.exit(2);
71
+ }
72
+
73
+ const tsconfigPath = path.resolve(pkgDir, TSCONFIG_FILE);
74
+ const current = readJsonIfExists(tsconfigPath);
75
+ const fileExists = current !== null;
76
+
77
+ // If tsconfig.json already exists, skip without checking content
78
+ if (fileExists) {
79
+ const report = {
80
+ cwd,
81
+ mode,
82
+ ok: true,
83
+ tsconfigPath,
84
+ required: {
85
+ file: path.join(packageRoot, TSCONFIG_FILE),
86
+ },
87
+ status: {
88
+ fileExistsBefore: true,
89
+ mismatchesBefore: [],
90
+ fileExistsAfter: true,
91
+ mismatchesAfter: [],
92
+ updated: false,
93
+ skipped: true,
94
+ },
95
+ };
96
+
97
+ if (jsonFile) {
98
+ const outPath = path.resolve(cwd, jsonFile);
99
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
100
+ fs.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
101
+ }
102
+
103
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
104
+ return;
105
+ }
106
+
107
+ const expectedExtends = computeExtendsPath(pkgDir, cwd);
108
+ const expectedPkgConfig = {
109
+ extends: expectedExtends,
110
+ ...PACKAGE_TSCONFIG_TEMPLATE,
111
+ };
112
+
113
+ const plannedContent = `${JSON.stringify(expectedPkgConfig, null, 2)}\n`;
114
+
115
+ if (mode === 'sync') {
116
+ fs.writeFileSync(tsconfigPath, plannedContent, 'utf8');
117
+ }
118
+
119
+ const mismatches = [
120
+ {
121
+ file: path.join(packageRoot, TSCONFIG_FILE),
122
+ expected: JSON.stringify(expectedPkgConfig, null, 2),
123
+ actual: 'missing',
124
+ },
125
+ ];
126
+
127
+ const report = {
128
+ cwd,
129
+ mode,
130
+ ok: mode !== 'check',
131
+ tsconfigPath,
132
+ required: {
133
+ file: path.join(packageRoot, TSCONFIG_FILE),
134
+ },
135
+ status: {
136
+ fileExistsBefore: false,
137
+ mismatchesBefore: mismatches,
138
+ fileExistsAfter: mode === 'sync',
139
+ mismatchesAfter: mode === 'sync' ? [] : mismatches,
140
+ updated: mode === 'sync',
141
+ },
142
+ };
143
+
144
+ if (jsonFile) {
145
+ const outPath = path.resolve(cwd, jsonFile);
146
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
147
+ fs.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
148
+ }
149
+
150
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
151
+ if (!report.ok) {
152
+ process.exit(2);
153
+ }
154
+ }
package/package.json CHANGED
@@ -1,36 +1,36 @@
1
1
  {
2
- "name": "@produck/agent-toolkit",
3
- "version": "0.9.2",
4
- "description": "Central CLI toolkit for organization AI execution workflows",
5
- "type": "module",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/produck/.github.git",
9
- "directory": "packages/agent-toolkit"
10
- },
11
2
  "bin": {
12
3
  "agent-toolkit": "bin/agent-toolkit.mjs"
13
4
  },
14
- "scripts": {
15
- "prepack": "node ./bin/build-publish-assets.mjs",
16
- "test": "node test/index.mjs",
17
- "produck:coverage": "c8 --reporter=lcov --reporter=html --reporter=text-summary npm test",
18
- "produck:lint": "eslint --fix . --max-warnings=0"
5
+ "description": "Central CLI toolkit for organization AI execution workflows",
6
+ "devDependencies": {
7
+ "@produck/eslint-rules": "^0.4.1",
8
+ "c8": "11.0.0"
9
+ },
10
+ "engines": {
11
+ "node": ">=18.0.0"
19
12
  },
20
13
  "files": [
21
14
  "bin",
22
15
  "publish-assets"
23
16
  ],
17
+ "license": "MIT",
18
+ "name": "@produck/agent-toolkit",
24
19
  "publishConfig": {
25
20
  "access": "public"
26
21
  },
27
- "engines": {
28
- "node": ">=18.0.0"
22
+ "repository": {
23
+ "directory": "packages/agent-toolkit",
24
+ "type": "git",
25
+ "url": "git+https://github.com/produck/.github.git"
29
26
  },
30
- "license": "MIT",
31
- "devDependencies": {
32
- "@produck/eslint-rules": "^0.4.0",
33
- "c8": "11.0.0"
27
+ "scripts": {
28
+ "prepack": "node ./bin/build-publish-assets.mjs",
29
+ "produck:coverage": "c8 --reporter=lcov --reporter=html --reporter=text-summary npm test",
30
+ "produck:lint": "eslint --fix . --max-warnings=0",
31
+ "test": "node test/index.mjs"
34
32
  },
35
- "gitHead": "aa9500630476fb423720f0b0056096e0e87e4c21"
33
+ "type": "module",
34
+ "version": "0.10.0",
35
+ "gitHead": "d0d432838dddbbc90f340b525bdd41153f8e6502"
36
36
  }
@@ -32,12 +32,12 @@ repositories:
32
32
  - `.github/copilot-instructions.md` — repository-specific exceptions and
33
33
  stricter local constraints.
34
34
 
35
- Editing rule (upstream only):
35
+ Editing rule:
36
36
 
37
37
  - Update downstream baseline rules directly in
38
38
  `.github/distribution/produck/*.instructions.md`.
39
- - Add organization-only governance under
40
- `.github/instructions/produck/` only when it must not be distributed.
39
+ - For internal-only governance (this repo only, not distributed), add files
40
+ under `.github/instructions/produck/`.
41
41
 
42
42
  ## Default expectations
43
43
 
@@ -53,16 +53,8 @@ Notes:
53
53
  - Use central remediation command to deploy root lint script/config and
54
54
  eslint integration baseline:
55
55
  `npm exec -- agent-toolkit sync-lint --cwd .`.
56
- - `c8` execution baseline for deployed coverage scripts is fixed to the
57
- version specified in `tooling-version-baseline.json`.
58
56
  - Downstream repositories must not use unversioned `npx c8` or `c8@latest`
59
57
  in shared scripts/CI.
60
- - Root local governance must pin `devDependencies.c8`,
61
- `devDependencies.husky`, `devDependencies.lerna`, and
62
- `devDependencies.@produck/agent-toolkit` via
63
- `agent-toolkit sync-git`.
64
- - Root local governance must pin `devDependencies.@produck/eslint-rules`
65
- via `agent-toolkit sync-lint`.
66
58
 
67
59
  - Testing strategy and framework are repository-defined.
68
60
  - `verify` scripts are optional repository-local health checks and are not
@@ -78,43 +70,14 @@ Notes:
78
70
  - Commit prechecks still require passing repository style gates (for example
79
71
  `produck:format` and `produck:lint`).
80
72
 
81
- Central toolkit command role model:
82
-
83
- - `agent-toolkit sync-instructions` is guidance-first distribution for
84
- organization baseline instructions.
85
- - `sync-instructions` is not a hard gate; use it to reduce instruction drift,
86
- but do not assume it can fully prevent AI hallucination or iterative drift.
87
- - `agent-toolkit preflight` is the hard guard for organization engineering
88
- baseline and is mandatory for required baseline checks.
89
- - `agent-toolkit sync-install` is the hard guard for root install script
90
- governance and is mandatory in monorepo mode.
91
- - `agent-toolkit sync-coverage` is the hard guard for monorepo coverage
92
- governance and is mandatory in monorepo mode.
93
- - `agent-toolkit sync-git` is the hard guard for local anti-drift hook
94
- governance and is mandatory in monorepo mode.
95
- - `agent-toolkit sync-format` is the hard guard for root format
96
- script/config governance and is mandatory in monorepo mode.
97
- - `agent-toolkit sync-lint` is the hard guard for root lint
98
- script/config and eslint integration governance and is mandatory in monorepo
99
- mode.
100
- - `agent-toolkit sync-publish` is the hard guard for root publish script
101
- governance when `lerna.json` is present.
102
- - For simplified downstream execution of mandatory flow (1 -> 2 -> ... -> 9),
103
- use:
104
- `npm exec -- agent-toolkit`.
105
- - Equivalent explicit form:
73
+ Enforcement:
74
+
75
+ - For one-step execution of all mandatory checks, use:
106
76
  `npm exec -- agent-toolkit enforce-node-baseline --cwd .`.
107
- - `agent-toolkit validate-commit-msg` is a hard guard for AI-agent-authored
108
- `git commit` and `git commit --amend` operations.
109
- - For human engineers, commit-message validation is recommended rather than
110
- mandatory unless repository-specific hooks/CI enforce it.
111
- - Do not require retroactive rewrite/amend of historical commits solely to
112
- satisfy commit-message validator rules.
113
- - `agent-toolkit run-capture` and `agent-toolkit summarize-log` are AI-agent
114
- execution guardrails.
115
- - These guardrails pair with node-first execution policy: prefer Node.js
116
- interpreter workflows for parsing/filtering over brittle OS-shell pipelines.
117
- - For human engineers, `run-capture` and `summarize-log` are optional helpers.
77
+ - `agent-toolkit validate-commit-msg` is required for AI-agent-authored
78
+ `git commit` and `git commit --amend`.
79
+ - For human engineers, commit-message validation is recommended.
80
+ - Do not require retroactive rewrite/amend of historical commits.
118
81
 
119
82
  Test authoring baseline:
120
83
 
@@ -143,67 +106,164 @@ Team conventions for `.gitignore`:
143
106
 
144
107
  ## Monorepo mode
145
108
 
146
- Repository layout:
109
+ ### Repository layout
147
110
 
148
111
  - Root-level `docs/` is required.
149
112
  - Each package/app should contain its own `src/` and `test/`.
150
113
 
151
- Script placement:
114
+ ### Root `package.json` governance
115
+
116
+ The root `package.json` exists only for development orchestration. It is
117
+ never consumed as a downstream dependency, so runtime-oriented fields are
118
+ prohibited.
119
+
120
+ #### Required fields
121
+
122
+ - `name` — A fixed name stabilizes the `name` field in `package-lock.json`.
123
+ - `private`: `true` — Prevents accidental npm publish.
124
+ - `workspaces` — Explicit path list only; see constraints below.
125
+ - `scripts` — See [Required scripts](#required-scripts) section below.
126
+ - `devDependencies` — The development materials manifest. Root
127
+ `devDependencies` is the single source of truth for organization-level and
128
+ repository-level tooling.
129
+
130
+ #### Optional fields
131
+
132
+ - `version` — Root is not published; version is meaningless.
133
+ - `description` — Root is not published; description has no practical use.
134
+ - `engines` — Not required. Leave this to Node.js version managers if
135
+ needed.
136
+
137
+ #### Prohibited fields
138
+
139
+ The following fields must never appear in root `package.json`:
140
+
141
+ - `type`
142
+ - `main`
143
+ - `exports`
144
+ - `types`
145
+ - `files`
146
+ - `publishConfig`
147
+ - `dependencies`
148
+
149
+ #### `workspaces` field constraints
150
+
151
+ - Do not use wildcard/glob patterns (for example `packages/*`, `**`, `?`,
152
+ `{}` or `[]`).
153
+ - List each workspace package path explicitly.
154
+
155
+ ### Required scripts
156
+
157
+ Root `package.json` must define:
158
+
159
+ | Script key | Required value |
160
+ | ----------------------- | ------------------------------------------------------------------------------------------------- |
161
+ | `produck:install` | `npm -v && npm install` |
162
+ | `prepare` | `husky` |
163
+ | `test` | Repository-defined (may use `--workspaces --if-present`) |
164
+ | `produck:coverage` | Organization-defined via `agent-toolkit sync-coverage` |
165
+ | `produck:lint` | Organization-defined via `agent-toolkit sync-lint` |
166
+ | `produck:format` | Organization-defined via `agent-toolkit sync-format` |
167
+ | `produck:commit:check` | `npm run produck:format && npm run produck:lint` |
168
+ | `produck:baseline` | `npm exec --package=@produck/agent-toolkit@latest -- agent-toolkit enforce-node-baseline --cwd .` |
169
+ | `produck:publish` | Required when `lerna.json` is present; governed by `agent-toolkit sync-publish` |
170
+ | `produck:publish:check` | Required when `lerna.json` is present; governed by `agent-toolkit sync-publish` |
171
+
172
+ Notes:
152
173
 
153
- - Root `package.json` must provide `produck:install`, `test`, `produck:coverage`,
154
- and `produck:lint` orchestration scripts.
155
- - Root `package.json` must reserve `produck:commit:check` for organization
156
- anti-drift gate with required value:
157
- `npm run produck:format && npm run produck:lint`.
158
- - Root `package.json` must reserve `prepare` for husky setup with required
159
- value: `husky`.
160
- - Root `package.json` must reserve `produck:format` and `produck:lint` for
161
- organization-controlled format/lint gates.
162
- - Root `package.json` must reserve `produck:publish` for organization-controlled
163
- publish gate when `lerna.json` is present (governed by
164
- `agent-toolkit sync-publish`).
165
174
  - `publish` may be defined at root or package level based on release workflow.
166
- - Workspace subpackage `produck:coverage` scripts must be synchronized by
167
- `agent-toolkit sync-coverage`.
168
- - Root local hook governance must be synchronized by
169
- `agent-toolkit sync-git`.
170
- - Root local shared script governance must initialize
171
- `scripts.produck:install` with required value `npm -v && npm install`
172
- via `agent-toolkit sync-install`.
173
- - Root local format governance must be synchronized by
174
- `agent-toolkit sync-format`.
175
- - Root local lint governance must be synchronized by
176
- `agent-toolkit sync-lint`.
177
- - Root local shared script/dependency governance must pin root
178
- `devDependencies.c8`,
179
- `devDependencies.husky`, `devDependencies.lerna`,
180
- `devDependencies.@produck/agent-toolkit` via
181
- `agent-toolkit sync-git`.
182
- - Root local shared script/dependency governance must initialize
183
- `scripts.produck:coverage` with workspace-level execution behavior:
184
- attempt `test` on all workspace packages using `--workspaces --if-present`.
185
- - Root local shared script/dependency governance must initialize `.c8rc.json`
186
- via `agent-toolkit sync-coverage`.
187
- - Root local format governance must initialize `.prettierrc` and
188
- `scripts.produck:format` via `agent-toolkit sync-format`.
189
- - Root local lint governance must initialize `eslint.config.mjs`,
190
- `scripts.produck:lint`, and `devDependencies.@produck/eslint-rules`
191
- (including append-mode integration for existing eslint config) via
192
- `agent-toolkit sync-lint`.
193
- - Root `package.json` must define a `produck:baseline` script for organization
194
- baseline enforcement:
175
+ - Remediation commands (run from root):
176
+ - `npm exec -- agent-toolkit sync-install --cwd .` — deploy root install script
177
+ - `npm exec -- agent-toolkit sync-coverage --cwd .` — deploy coverage scripts
178
+ - `npm exec -- agent-toolkit sync-git --cwd .` — deploy git hooks and deps
179
+ - `npm exec -- agent-toolkit sync-format --cwd .` — deploy format config
180
+ - `npm exec -- agent-toolkit sync-lint --cwd .` — deploy lint config
181
+
182
+ ### Workspace `package.json` governance
183
+
184
+ #### Property restrictions
185
+
186
+ Workspace-level `package.json` must NOT contain:
187
+
188
+ - `private` — Package publication state is managed by the root workspace;
189
+ individual workspace packages should not declare it.
190
+ - `workspaces` — Only the root `package.json` defines workspace paths.
191
+ Nested declarations violate the centralization principle.
192
+ - Root orchestration scripts These are the root `package.json`'s
193
+ responsibility and must not be duplicated in workspace packages:
194
+ `produck:install`, `produck:baseline`, `produck:commit:check`, `prepare`,
195
+ `produck:format`, `produck:publish`, `produck:publish:check`
196
+
197
+ #### Recommended structure
198
+
199
+ Workspace packages should keep their `package.json` lean, containing only:
200
+
201
+ - Package metadata: `name`, `version`, `type`, `main`, `exports`, etc.
202
+ - Dependencies: `dependencies`, `devDependencies`
203
+ - Package-level scripts: `test`, `produck:coverage`
204
+
205
+ #### Publish metadata governance
206
+
207
+ Workspace packages that are published to npm must correctly declare the
208
+ following fields. These control the package's npm registry page appearance and
209
+ link back to the git hosting platform.
210
+
211
+ **Required fields:**
212
+
213
+ - `description` — Short summary shown on npm search results and package page.
214
+ Must be meaningful and accurate.
215
+ - `license` — SPDX license identifier (for example `"MIT"`). Displayed on npm
216
+ package page.
217
+
218
+ **Repository linkage fields** (affect npm "repository", "bugs", "homepage"
219
+ links):
220
+
221
+ - `repository` — Must use the expanded object form with `directory` to
222
+ identify the subpackage location within the monorepo:
195
223
  ```json
196
- "produck:baseline": "npm exec --package=@produck/agent-toolkit@latest -- agent-toolkit enforce-node-baseline --cwd ."
224
+ "repository": {
225
+ "type": "git",
226
+ "url": "git+https://github.com/produck/<repo>.git",
227
+ "directory": "packages/<name>"
228
+ }
197
229
  ```
230
+ The `url` value must match the repository's canonical git remote. The
231
+ `directory` value must be the package's workspace-relative path from the
232
+ monorepo root.
233
+ - `bugs` — Must link to the GitHub issues page:
234
+ ```json
235
+ "bugs": {
236
+ "url": "https://github.com/produck/<repo>/issues"
237
+ }
238
+ ```
239
+ - `homepage` — Must point to the package's README on the default branch, using
240
+ the `directory` form to navigate to the subpackage:
241
+ ```json
242
+ "homepage": "https://github.com/produck/<repo>/tree/main/packages/<name>#readme"
243
+ ```
244
+
245
+ **Recommended fields:**
246
+
247
+ - `keywords` — Array of strings that describe the package. Improves npm search
248
+ discoverability. Omit if the package has no meaningful keywords.
249
+
250
+ **Rationale:**
251
+
252
+ - Without `repository.directory`, npm links the repository field to the
253
+ monorepo root, which is not helpful for subpackage visitors.
254
+ - Without `bugs`, npm omits the "Report issues" link on the package page.
255
+ - Without `description`, npm shows "(not yet filled)" on the package page.
256
+ - Invalid or missing `license` causes npm warnings during publish.
198
257
 
199
- Release tooling policy (required):
258
+ ### Release tooling policy
200
259
 
201
260
  - Monorepo release workflow must use `lerna`.
202
261
  - `lerna` execution version is governed at organization level, not per
203
262
  repository.
204
263
  - Source of truth for `lerna` version baseline:
205
264
  `.github/distribution/produck/tooling-version-baseline.json`.
206
- - Required execution baseline: version specified in `tooling-version-baseline.json`.
265
+ - Required execution baseline: version specified in the
266
+ `tooling-version-baseline.json`.
207
267
  - Required invocation:
208
268
  `npm exec -- lerna <subcommand>`.
209
269
  - Downstream repositories must not use unversioned `npx lerna` or
@@ -212,34 +272,7 @@ Release tooling policy (required):
212
272
  - Keep an emergency organization-level rollback path when baseline version is
213
273
  updated.
214
274
 
215
- Root workspace `package.json` minimal baseline (required):
216
-
217
- - `private`: `true`
218
- - `workspaces` (explicit package path list only)
219
- - `scripts` with at least: `produck:install`, `test`, `produck:coverage`,
220
- `produck:lint`
221
- - `publish` script is optional at root when release is managed per package or
222
- by external workflow.
223
-
224
- `workspaces` field constraints (required):
225
-
226
- - Do not use wildcard/glob patterns (for example `packages/*`, `**`, `?`,
227
- `{}` or `[]`).
228
- - List each workspace package path explicitly.
229
-
230
- Avoid unused root runtime/publish fields by default:
231
-
232
- - `type`
233
- - `main`
234
- - `exports`
235
- - `types`
236
- - `files`
237
- - `publishConfig`
238
-
239
- Add the fields above only when the monorepo root itself is an executable
240
- runtime package or is intentionally published.
241
-
242
- Ignore strategy:
275
+ ### Ignore strategy
243
276
 
244
277
  - Keep ignore rules centralized at repository root whenever possible.
245
278
  - Add package-level `.gitignore` only when a package has unique generated
@@ -52,6 +52,35 @@ import './feature-b.test.mjs';
52
52
  - Avoid global side effects that persist across test cases.
53
53
  - Clean up resources (temp files, open handles) at the end of each test case.
54
54
 
55
+ ## API usage conventions
56
+
57
+ - Callback functions for `describe` and `it` MUST use arrow functions. Do not
58
+ use `function` keyword or method shorthand syntax.
59
+
60
+ Correct:
61
+
62
+ ```js
63
+ describe('my feature', () => {
64
+ it('should work', () => {
65
+ // assertions
66
+ });
67
+ });
68
+ ```
69
+
70
+ Wrong:
71
+
72
+ ```js
73
+ describe('my feature', function () {
74
+ it('should work', function () {
75
+ // assertions
76
+ });
77
+ });
78
+ ```
79
+
80
+ - Deep nesting of `describe` blocks can make test output harder to read. When
81
+ nesting becomes excessive, split the test file and use `await import()` to
82
+ reorganize — this keeps the actual test code at shallow nesting levels.
83
+
55
84
  ## Naming conventions
56
85
 
57
86
  - Test files use the `.test.mjs` suffix.
@@ -59,6 +88,69 @@ import './feature-b.test.mjs';
59
88
  the module name or command name).
60
89
  - `it` labels should describe the expected behavior in plain language.
61
90
 
91
+ ### Suite name conventions
92
+
93
+ The `describe` suite name encodes the member type under test using a prefix
94
+ convention:
95
+
96
+ | Prefix | Meaning | Example |
97
+ | ------ | ---------------------------------------------------- | ------------------------- |
98
+ | `::` | Class static public member or namespace static | `describe('::parse()')` |
99
+ | `.` | Class instance member | `describe('.validate()')` |
100
+ | `()` | Marks the target as a function (composable) | `describe('::create()')` |
101
+ | `>` | Return-value testing, nested inside a function suite | `describe('>result')` |
102
+ | `#` | Event emitter — test event dispatch behavior | `describe('#error')` |
103
+
104
+ Prefixes and `()` compose freely. For example:
105
+
106
+ | Suite name | Meaning |
107
+ | ------------- | ----------------------------- |
108
+ | `::parse()` | Static function `parse` |
109
+ | `::VERSION` | Static property `VERSION` |
110
+ | `.validate()` | Instance method `validate` |
111
+ | `.name` | Instance property `name` |
112
+ | `validate()` | Standalone function (unbound) |
113
+
114
+ Examples:
115
+
116
+ ```js
117
+ describe('::parse()', () => {
118
+ it('should parse valid input', () => {
119
+ /* ... */
120
+ });
121
+ });
122
+
123
+ describe('::VERSION', () => {
124
+ it('should be a semver string', () => {
125
+ /* ... */
126
+ });
127
+ });
128
+
129
+ describe('.validate()', () => {
130
+ it('should reject invalid data', () => {
131
+ /* ... */
132
+ });
133
+
134
+ describe('>result', () => {
135
+ it('should be a boolean', () => {
136
+ /* ... */
137
+ });
138
+ });
139
+ });
140
+
141
+ describe('.name', () => {
142
+ it('should be non-empty', () => {
143
+ /* ... */
144
+ });
145
+ });
146
+
147
+ describe('#error', () => {
148
+ it('should emit on failure', () => {
149
+ /* ... */
150
+ });
151
+ });
152
+ ```
153
+
62
154
  ## Local debug workflow (recommended)
63
155
 
64
156
  When debugging a failing test case:
@@ -34,17 +34,14 @@ The Produck monorepo provides unified configuration across all packages for cons
34
34
  - If a repository overrides inherited rules, include only the deltas and
35
35
  document the rationale.
36
36
 
37
- **Usage in packages:**
37
+ **Usage:**
38
38
 
39
- ```javascript
40
- // packages/my-package/eslint.config.mjs
41
- import rootConfig from '../../eslint.config.mjs';
42
-
43
- export default [
44
- ...rootConfig,
45
- // Package-specific overrides here
46
- ];
47
- ```
39
+ - Root `eslint.config.mjs` applies to all packages automatically via ESLint
40
+ flat config resolution — sub-packages are NOT required to create their own
41
+ `eslint.config.mjs`.
42
+ - Sub-packages may create a package-level `eslint.config.mjs` on demand for
43
+ workspace-specific overrides, but this is opt-in and not proactively
44
+ deployed.
48
45
 
49
46
  ### 2. TypeScript Configuration (`tsconfig.json`, conditional)
50
47
 
@@ -59,24 +56,34 @@ export default [
59
56
  - If any package uses TypeScript source files or needs centralized strict/type
60
57
  options, create root `tsconfig.json` and let TypeScript packages extend it.
61
58
 
62
- **Recommended key settings when present:**
59
+ **Governance (enforced by `agent-toolkit sync-typescript`):**
60
+
61
+ Run `agent-toolkit sync-typescript --package-root packages/<name> --cwd .`
62
+ to ensure a sub-package has a `tsconfig.json` that extends the root with the
63
+ correct relative path and uses standard compiler options. If the file already
64
+ exists, it is skipped without modification.
65
+
66
+ **Enforced settings:**
63
67
 
64
68
  - Target: ES2022
65
69
  - Strict mode: enabled
66
- - Module resolution: node
70
+ - Module resolution: bundler
67
71
  - Source maps: enabled
68
72
  - Declaration files: generated
69
73
 
70
- **Usage in TypeScript packages:**
74
+ **Usage in TypeScript packages (auto-generated by `--package-root`):**
71
75
 
72
76
  ```json
73
77
  {
74
78
  "extends": "../../tsconfig.json",
75
79
  "compilerOptions": {
76
- "outDir": "./dist"
77
- },
78
- "include": ["src/**/*"],
79
- "exclude": ["node_modules", "dist", "test"]
80
+ "lib": ["ESNext"],
81
+ "types": ["node"],
82
+ "strictNullChecks": true,
83
+ "allowJs": true,
84
+ "noEmit": true,
85
+ "module": "NodeNext"
86
+ }
80
87
  }
81
88
  ```
82
89
 
@@ -161,32 +168,22 @@ npm run produck:coverage
161
168
 
162
169
  1. Create `packages/my-package/` directory
163
170
  2. Create `packages/my-package/package.json` with workspace configuration
164
- 3. Inherit root configs:
165
- - ESLint: extend `../../eslint.config.mjs`
171
+ 3. Config inheritance:
172
+ - ESLint: root `eslint.config.mjs` applies automatically — package-level
173
+ `eslint.config.mjs` is opt-in and not proactively deployed.
166
174
  - TypeScript (when root `tsconfig.json` exists): extend
167
175
  `../../tsconfig.json`
168
176
  - Prettier: uses root `.prettierrc` automatically
169
177
 
170
178
  ### Package-Level Overrides
171
179
 
172
- Each package can extend/override shared config:
173
-
174
- **ESLint example:**
180
+ Each package's specific needs should be handled within the root shared config
181
+ whenever possible. Per-package ESLint config files are opt-in and not
182
+ proactively deployed; sub-packages may create one on demand.
175
183
 
176
- ```javascript
177
- import rootConfig from '../../eslint.config.mjs';
178
- import onlyWarn from 'eslint-plugin-only-warn';
179
-
180
- export default [
181
- ...rootConfig,
182
- {
183
- plugins: { 'only-warn': onlyWarn },
184
- rules: {
185
- 'custom-rule': 'warn', // package-specific override
186
- },
187
- },
188
- ];
189
- ```
184
+ For TypeScript configuration, packages may extend root `tsconfig.json` (see
185
+ [TypeScript Configuration](#2-typescript-configuration-tsconfigjson-conditional)
186
+ above).
190
187
 
191
188
  ## .editorconfig
192
189
 
@@ -191,6 +191,18 @@ Commit precheck gate (AI-agent required, human recommended):
191
191
 
192
192
  If validation fails, fix the message and rerun until it passes.
193
193
 
194
+ ## Workspace Draft Files
195
+
196
+ AI agents **must not** create or organize commit message draft files (such as
197
+ `.git/COMMIT_EDITMSG` snapshots, staged-message backups, or raw draft text
198
+ files) anywhere in the working tree.
199
+
200
+ **Exception**: draft files are allowed if the filename matches the
201
+ `*.ign*` glob pattern (for example `commit-msg.ign` or
202
+ `message.draft.ignore`). This ensures the file is covered by the
203
+ organization-level `.gitignore` rules and will never be accidentally
204
+ committed.
205
+
194
206
  ## Notes
195
207
 
196
208
  - Keep the summary concise and specific.
@@ -1,79 +1,84 @@
1
1
  {
2
+ "coverage": {
3
+ "scriptTemplate": "c8 --reporter=lcov --reporter=html --reporter=text-summary npm test"
4
+ },
5
+ "enforce": {
6
+ "sharedScriptsDisallow": [
7
+ "npx c8",
8
+ "c8@latest",
9
+ "npx lerna",
10
+ "lerna@latest",
11
+ "npx prettier",
12
+ "prettier@latest"
13
+ ]
14
+ },
2
15
  "schemaVersion": 1,
3
- "updatedAt": "2026-05-12",
4
16
  "tools": {
5
- "c8": {
6
- "version": "11.0.0",
17
+ "@eslint/config-helpers": {
18
+ "allowLatest": false,
7
19
  "policy": "pinned",
8
- "allowLatest": false
20
+ "version": "0.6.0"
9
21
  },
10
- "husky": {
11
- "version": "9.1.7",
22
+ "@eslint/js": {
23
+ "allowLatest": false,
12
24
  "policy": "pinned",
13
- "allowLatest": false
25
+ "version": "10.0.1"
14
26
  },
15
- "lerna": {
16
- "version": "9.0.7",
27
+ "@eslint/json": {
28
+ "allowLatest": false,
17
29
  "policy": "pinned",
18
- "allowLatest": false
30
+ "version": "1.2.0"
19
31
  },
20
- "prettier": {
21
- "version": "3.8.3",
32
+ "@eslint/markdown": {
33
+ "allowLatest": false,
22
34
  "policy": "pinned",
23
- "allowLatest": false
35
+ "version": "8.0.2"
24
36
  },
25
- "eslint": {
26
- "version": "10.4.0",
37
+ "@types/node": {
38
+ "allowLatest": false,
27
39
  "policy": "pinned",
28
- "allowLatest": false
40
+ "version": "22.19.19"
29
41
  },
30
- "@eslint/js": {
31
- "version": "10.0.1",
42
+ "c8": {
43
+ "allowLatest": false,
32
44
  "policy": "pinned",
33
- "allowLatest": false
45
+ "version": "11.0.0"
34
46
  },
35
- "@eslint/json": {
36
- "version": "1.2.0",
47
+ "eslint": {
48
+ "allowLatest": false,
37
49
  "policy": "pinned",
38
- "allowLatest": false
50
+ "version": "10.4.0"
39
51
  },
40
- "@eslint/markdown": {
41
- "version": "8.0.1",
52
+ "globals": {
53
+ "allowLatest": false,
42
54
  "policy": "pinned",
43
- "allowLatest": false
55
+ "version": "17.6.0"
44
56
  },
45
- "@eslint/config-helpers": {
46
- "version": "0.6.0",
57
+ "husky": {
58
+ "allowLatest": false,
47
59
  "policy": "pinned",
48
- "allowLatest": false
60
+ "version": "9.1.7"
49
61
  },
50
- "typescript-eslint": {
51
- "version": "8.59.4",
62
+ "lerna": {
63
+ "allowLatest": false,
52
64
  "policy": "pinned",
53
- "allowLatest": false
65
+ "version": "9.0.7"
54
66
  },
55
- "globals": {
56
- "version": "17.6.0",
67
+ "prettier": {
68
+ "allowLatest": false,
57
69
  "policy": "pinned",
58
- "allowLatest": false
70
+ "version": "3.8.3"
71
+ },
72
+ "typescript-eslint": {
73
+ "allowLatest": false,
74
+ "policy": "pinned",
75
+ "version": "8.60.0"
59
76
  },
60
77
  "@produck/eslint-rules": {
61
- "version": "0.4.0",
78
+ "version": "0.4.1",
62
79
  "policy": "pinned",
63
80
  "allowLatest": false
64
81
  }
65
82
  },
66
- "coverage": {
67
- "scriptTemplate": "c8 --reporter=lcov --reporter=html --reporter=text-summary npm test"
68
- },
69
- "enforce": {
70
- "sharedScriptsDisallow": [
71
- "npx c8",
72
- "c8@latest",
73
- "npx lerna",
74
- "lerna@latest",
75
- "npx prettier",
76
- "prettier@latest"
77
- ]
78
- }
83
+ "updatedAt": "2026-05-12"
79
84
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "$schema": "./node_modules/lerna/schemas/lerna-schema.json",
3
3
  "command": {
4
- "version": {
5
- "commitHooks": false
6
- },
7
4
  "publish": {
8
5
  "ignoreScripts": false,
9
6
  "message": "[PUBLISH]"
7
+ },
8
+ "version": {
9
+ "commitHooks": false
10
10
  }
11
11
  },
12
12
  "useNx": false,
@@ -7,5 +7,13 @@
7
7
  "bracketSpacing": true,
8
8
  "arrowParens": "always",
9
9
  "printWidth": 80,
10
- "endOfLine": "lf"
10
+ "endOfLine": "lf",
11
+ "overrides": [
12
+ {
13
+ "files": "*.json",
14
+ "options": {
15
+ "printWidth": 1
16
+ }
17
+ }
18
+ ]
11
19
  }