@produck/agent-toolkit 0.4.0 → 0.6.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.
- package/README.md +78 -16
- package/bin/agent-toolkit.mjs +32 -0
- package/bin/command/enforce-node-baseline/help.txt +8 -5
- package/bin/command/enforce-node-baseline/index.mjs +32 -0
- package/bin/command/main/help.txt +4 -0
- package/bin/command/preflight/index.mjs +7 -35
- package/bin/command/shared/workspace-validation.mjs +63 -0
- package/bin/command/sync-coverage-script/help.txt +10 -3
- package/bin/command/sync-coverage-script/index.mjs +29 -2
- package/bin/command/sync-editorconfig/editorconfig.template +15 -0
- package/bin/command/sync-editorconfig/help.txt +13 -0
- package/bin/command/sync-editorconfig/index.mjs +233 -0
- package/bin/command/sync-eslint-config/help.txt +18 -0
- package/bin/command/sync-eslint-config/index.mjs +248 -0
- package/bin/command/sync-husky-hooks/help.txt +1 -9
- package/bin/command/sync-husky-hooks/index.mjs +1 -179
- package/bin/command/sync-prettier-config/help.txt +14 -0
- package/bin/command/sync-prettier-config/index.mjs +130 -0
- package/bin/command/sync-workspace-config/help.txt +21 -0
- package/bin/command/sync-workspace-config/index.mjs +290 -0
- package/bin/command/validate-commit-msg/help.txt +2 -1
- package/bin/command/validate-commit-msg/index.mjs +53 -3
- package/package.json +4 -6
- package/publish-assets/instructions/produck/10-produck-node.instructions.md +52 -7
- package/publish-assets/instructions/produck/20-produck-commit.instructions.md +7 -0
package/README.md
CHANGED
|
@@ -19,9 +19,16 @@ What it does (in order):
|
|
|
19
19
|
|
|
20
20
|
1. Syncs organization AI instruction files into `.github/instructions/produck/`
|
|
21
21
|
2. Runs preflight to verify required files and directories
|
|
22
|
-
3.
|
|
23
|
-
4.
|
|
24
|
-
|
|
22
|
+
3. Syncs root `produck:format` script and initializes `.prettierrc`
|
|
23
|
+
4. Syncs root `produck:lint` script, initializes/patches `eslint.config.mjs`,
|
|
24
|
+
and ensures `@produck/eslint-rules`
|
|
25
|
+
5. Syncs root shared governance (`produck:baseline`,
|
|
26
|
+
`produck:coverage`, `produck:precommit-check`), initializes `.c8rc.json`,
|
|
27
|
+
and syncs shared pinned devDependencies
|
|
28
|
+
(`c8`, `husky`, `lerna`, `@produck/agent-toolkit`)
|
|
29
|
+
6. Deploys the pinned `produck:coverage` script and `c8` devDependency to each workspace package, and enforces `scripts.test` (generates a default `test` script when missing).
|
|
30
|
+
**Note:** The `produck:coverage` script in subpackages is for local and AI development use only. It is NOT enforced by organization CI or `.c8rc.json`. Only the root workspace (monorepo root) is subject to org-level coverage enforcement and `.c8rc.json`.
|
|
31
|
+
7. Deploys `.husky/pre-commit` and `.husky/commit-msg`
|
|
25
32
|
|
|
26
33
|
After running, add the persistent enforcement entry to the repository
|
|
27
34
|
`package.json`:
|
|
@@ -43,6 +50,9 @@ npm run produck:baseline
|
|
|
43
50
|
- agent-toolkit run-capture
|
|
44
51
|
- agent-toolkit summarize-log
|
|
45
52
|
- agent-toolkit sync-coverage-script
|
|
53
|
+
- agent-toolkit sync-prettier-config
|
|
54
|
+
- agent-toolkit sync-eslint-config
|
|
55
|
+
- agent-toolkit sync-workspace-config
|
|
46
56
|
- agent-toolkit sync-husky-hooks
|
|
47
57
|
- agent-toolkit validate-commit-msg
|
|
48
58
|
- agent-toolkit sync-instructions
|
|
@@ -61,17 +71,25 @@ Equivalent explicit form:
|
|
|
61
71
|
npm exec -- agent-toolkit enforce-node-baseline --cwd .
|
|
62
72
|
```
|
|
63
73
|
|
|
64
|
-
`enforce-node-baseline` runs
|
|
74
|
+
`enforce-node-baseline` runs seven steps in fixed order and stops at the first
|
|
65
75
|
failure:
|
|
66
76
|
|
|
67
77
|
1. `sync-instructions` — distribute organization AI instruction files into
|
|
68
78
|
`.github/instructions/produck/`
|
|
69
79
|
2. `preflight` — verify required files and directories exist
|
|
70
|
-
3. `sync-
|
|
71
|
-
|
|
72
|
-
4. `sync-
|
|
73
|
-
|
|
74
|
-
`
|
|
80
|
+
3. `sync-prettier-config` — deploy organization format gate script
|
|
81
|
+
(`produck:format`) and initialize `.prettierrc`
|
|
82
|
+
4. `sync-eslint-config` — deploy organization lint gate script
|
|
83
|
+
(`produck:lint`), initialize/patch `eslint.config.mjs`, and ensure
|
|
84
|
+
`@produck/eslint-rules` integration
|
|
85
|
+
5. `sync-workspace-config` — deploy shared root governance scripts
|
|
86
|
+
(`produck:baseline`, `produck:coverage`, `produck:precommit-check`),
|
|
87
|
+
initialize root `.c8rc.json`, and sync shared pinned root devDependencies
|
|
88
|
+
(`c8`, `husky`, `lerna`, `@produck/agent-toolkit`)
|
|
89
|
+
6. `sync-coverage-script` — deploy pinned `produck:coverage` script and `c8`
|
|
90
|
+
devDependency into each workspace package, and ensure each workspace
|
|
91
|
+
package has `scripts.test` (auto-generate a default value when missing)
|
|
92
|
+
7. `sync-husky-hooks` — deploy `.husky/pre-commit` and `.husky/commit-msg`
|
|
75
93
|
|
|
76
94
|
Add to downstream repository root `package.json` for one-command enforcement:
|
|
77
95
|
|
|
@@ -121,22 +139,59 @@ Summarize captured output:
|
|
|
121
139
|
npm exec -- agent-toolkit summarize-log --file logs/test.log --match "FAIL|ERROR"
|
|
122
140
|
```
|
|
123
141
|
|
|
124
|
-
Deploy organization coverage script and pinned local c8 devDependency to
|
|
125
|
-
workspace packages:
|
|
142
|
+
Deploy organization coverage script and pinned local c8 devDependency to workspace packages:
|
|
126
143
|
|
|
127
144
|
```
|
|
128
145
|
npm exec -- agent-toolkit sync-coverage-script --cwd .
|
|
129
146
|
```
|
|
130
147
|
|
|
148
|
+
This command also enforces `scripts.test` in each workspace package.
|
|
149
|
+
If missing, it generates:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
node -e "console.log('No tests configured')"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Note:** The `produck:coverage` script in subpackages is for local and AI development use only. It is NOT enforced by organization CI or `.c8rc.json`. Only the root workspace (monorepo root) is subject to org-level coverage enforcement and `.c8rc.json`.
|
|
156
|
+
|
|
157
|
+
Deploy organization format config and script baseline to repository root:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
npm exec -- agent-toolkit sync-prettier-config --cwd .
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
This command manages `scripts.produck:format` and `.prettierrc` only.
|
|
164
|
+
|
|
165
|
+
Deploy organization lint config and script baseline to repository root:
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
npm exec -- agent-toolkit sync-eslint-config --cwd .
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
This command manages `scripts.produck:lint`, `eslint.config.mjs`, and
|
|
172
|
+
`devDependencies.@produck/eslint-rules`. If `eslint.config.mjs` exists without
|
|
173
|
+
`@produck/eslint-rules`, it appends Produck integration to the exported config
|
|
174
|
+
array.
|
|
175
|
+
|
|
176
|
+
Deploy organization root shared scripts and shared pinned dependencies to
|
|
177
|
+
repository root:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
npm exec -- agent-toolkit sync-workspace-config --cwd .
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This command manages `scripts.produck:baseline`,
|
|
184
|
+
`scripts.produck:coverage`, `scripts.produck:precommit-check`, initializes
|
|
185
|
+
`.c8rc.json`, and pins `c8`, `husky`, `lerna`, and `@produck/agent-toolkit`
|
|
186
|
+
in root `devDependencies`.
|
|
187
|
+
|
|
131
188
|
Deploy organization local anti-drift husky hooks to repository root:
|
|
132
189
|
|
|
133
190
|
```
|
|
134
191
|
npm exec -- agent-toolkit sync-husky-hooks --cwd .
|
|
135
192
|
```
|
|
136
193
|
|
|
137
|
-
This command
|
|
138
|
-
`@produck/agent-toolkit`) to organization baseline fixed versions and syncs
|
|
139
|
-
`.husky/pre-commit` and `.husky/commit-msg`.
|
|
194
|
+
This command syncs only `.husky/pre-commit` and `.husky/commit-msg`.
|
|
140
195
|
|
|
141
196
|
Validate commit message format:
|
|
142
197
|
|
|
@@ -185,11 +240,18 @@ Organization-only instruction source (not published):
|
|
|
185
240
|
|
|
186
241
|
## Local verification
|
|
187
242
|
|
|
243
|
+
`verify` is an optional package-level health check and is not a commit gate.
|
|
244
|
+
Use repository style gates first, then run package checks when needed.
|
|
245
|
+
|
|
188
246
|
From repository root:
|
|
189
247
|
|
|
190
248
|
```bash
|
|
191
|
-
npm
|
|
249
|
+
npm run format:check
|
|
250
|
+
npm run lint
|
|
251
|
+
npm --workspace @produck/agent-toolkit run test
|
|
192
252
|
npm --workspace @produck/agent-toolkit run pack:check
|
|
253
|
+
# optional health check
|
|
254
|
+
npm --workspace @produck/agent-toolkit run verify
|
|
193
255
|
```
|
|
194
256
|
|
|
195
257
|
## Publishing
|
|
@@ -220,7 +282,7 @@ Repository includes manual workflow:
|
|
|
220
282
|
|
|
221
283
|
Workflow behavior:
|
|
222
284
|
|
|
223
|
-
-
|
|
285
|
+
- Runs test and pack:check for `@produck/agent-toolkit`.
|
|
224
286
|
- Does not publish to npm.
|
|
225
287
|
- Used as release gate before workspace-level publish.
|
|
226
288
|
|
package/bin/agent-toolkit.mjs
CHANGED
|
@@ -16,6 +16,22 @@ import {
|
|
|
16
16
|
printSyncInstructionsHelp,
|
|
17
17
|
runSyncInstructions,
|
|
18
18
|
} from './command/sync-instructions/index.mjs';
|
|
19
|
+
import {
|
|
20
|
+
printSyncPrettierConfigHelp,
|
|
21
|
+
runSyncPrettierConfig,
|
|
22
|
+
} from './command/sync-prettier-config/index.mjs';
|
|
23
|
+
import {
|
|
24
|
+
printSyncEditorconfigHelp,
|
|
25
|
+
runSyncEditorconfig,
|
|
26
|
+
} from './command/sync-editorconfig/index.mjs';
|
|
27
|
+
import {
|
|
28
|
+
printSyncEslintConfigHelp,
|
|
29
|
+
runSyncEslintConfig,
|
|
30
|
+
} from './command/sync-eslint-config/index.mjs';
|
|
31
|
+
import {
|
|
32
|
+
printSyncWorkspaceConfigHelp,
|
|
33
|
+
runSyncWorkspaceConfig,
|
|
34
|
+
} from './command/sync-workspace-config/index.mjs';
|
|
19
35
|
import { hasFlag, parseCommonArgs } from './command/shared/args.mjs';
|
|
20
36
|
import {
|
|
21
37
|
printValidateCommitMsgHelp,
|
|
@@ -43,6 +59,18 @@ const COMMANDS = {
|
|
|
43
59
|
printHelp: printSyncCoverageScriptHelp,
|
|
44
60
|
run: runSyncCoverageScript,
|
|
45
61
|
},
|
|
62
|
+
'sync-prettier-config': {
|
|
63
|
+
printHelp: printSyncPrettierConfigHelp,
|
|
64
|
+
run: runSyncPrettierConfig,
|
|
65
|
+
},
|
|
66
|
+
'sync-eslint-config': {
|
|
67
|
+
printHelp: printSyncEslintConfigHelp,
|
|
68
|
+
run: runSyncEslintConfig,
|
|
69
|
+
},
|
|
70
|
+
'sync-workspace-config': {
|
|
71
|
+
printHelp: printSyncWorkspaceConfigHelp,
|
|
72
|
+
run: runSyncWorkspaceConfig,
|
|
73
|
+
},
|
|
46
74
|
'sync-husky-hooks': {
|
|
47
75
|
printHelp: printSyncHuskyHooksHelp,
|
|
48
76
|
run: runSyncHuskyHooks,
|
|
@@ -55,6 +83,10 @@ const COMMANDS = {
|
|
|
55
83
|
printHelp: printSyncInstructionsHelp,
|
|
56
84
|
run: runSyncInstructions,
|
|
57
85
|
},
|
|
86
|
+
'sync-editorconfig': {
|
|
87
|
+
printHelp: printSyncEditorconfigHelp,
|
|
88
|
+
run: runSyncEditorconfig,
|
|
89
|
+
},
|
|
58
90
|
};
|
|
59
91
|
|
|
60
92
|
const DEFAULT_COMMAND = 'enforce-node-baseline';
|
|
@@ -7,13 +7,16 @@ Behavior:
|
|
|
7
7
|
- Runs mandatory baseline flow in fixed order:
|
|
8
8
|
1) sync-instructions
|
|
9
9
|
2) preflight
|
|
10
|
-
3) sync-
|
|
11
|
-
4) sync-
|
|
10
|
+
3) sync-prettier-config
|
|
11
|
+
4) sync-eslint-config
|
|
12
|
+
5) sync-workspace-config
|
|
13
|
+
6) sync-coverage-script
|
|
14
|
+
7) sync-husky-hooks
|
|
12
15
|
- Stops at first failed step and exits non-zero
|
|
13
16
|
- Prints one combined JSON report for all executed steps
|
|
14
17
|
|
|
15
18
|
Rules:
|
|
16
|
-
- --check runs non-mutating validation mode for step 1, step 3, and step
|
|
17
|
-
- --dry-run runs non-mutating preview mode for step 1, step 3, and step
|
|
19
|
+
- --check runs non-mutating validation mode for step 1, step 3, step 4, step 5, step 6, and step 7
|
|
20
|
+
- --dry-run runs non-mutating preview mode for step 1, step 3, step 4, step 5, step 6, and step 7
|
|
18
21
|
- --check takes precedence over --dry-run
|
|
19
|
-
- --workspace filters coverage sync targets in step
|
|
22
|
+
- --workspace filters coverage sync targets in step 6
|
|
@@ -120,9 +120,41 @@ export function runEnforceNodeBaseline(options) {
|
|
|
120
120
|
syncHuskyArgs.push('--dry-run');
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
const syncWorkspaceConfigArgs = ['sync-workspace-config', '--cwd', cwd];
|
|
124
|
+
if (check) {
|
|
125
|
+
syncWorkspaceConfigArgs.push('--check');
|
|
126
|
+
} else if (dryRun) {
|
|
127
|
+
syncWorkspaceConfigArgs.push('--dry-run');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const syncEditorconfigArgs = ['sync-editorconfig', '--cwd', cwd];
|
|
131
|
+
if (check) {
|
|
132
|
+
syncEditorconfigArgs.push('--check');
|
|
133
|
+
} else if (dryRun) {
|
|
134
|
+
syncEditorconfigArgs.push('--dry-run');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const syncPrettierConfigArgs = ['sync-prettier-config', '--cwd', cwd];
|
|
138
|
+
if (check) {
|
|
139
|
+
syncPrettierConfigArgs.push('--check');
|
|
140
|
+
} else if (dryRun) {
|
|
141
|
+
syncPrettierConfigArgs.push('--dry-run');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const syncEslintConfigArgs = ['sync-eslint-config', '--cwd', cwd];
|
|
145
|
+
if (check) {
|
|
146
|
+
syncEslintConfigArgs.push('--check');
|
|
147
|
+
} else if (dryRun) {
|
|
148
|
+
syncEslintConfigArgs.push('--dry-run');
|
|
149
|
+
}
|
|
150
|
+
|
|
123
151
|
const plan = [
|
|
124
152
|
{ name: 'sync-instructions', args: syncInstructionsArgs },
|
|
125
153
|
{ name: 'preflight', args: preflightArgs },
|
|
154
|
+
{ name: 'sync-editorconfig', args: syncEditorconfigArgs },
|
|
155
|
+
{ name: 'sync-prettier-config', args: syncPrettierConfigArgs },
|
|
156
|
+
{ name: 'sync-eslint-config', args: syncEslintConfigArgs },
|
|
157
|
+
{ name: 'sync-workspace-config', args: syncWorkspaceConfigArgs },
|
|
126
158
|
{ name: 'sync-coverage-script', args: syncCoverageArgs },
|
|
127
159
|
{ name: 'sync-husky-hooks', args: syncHuskyArgs },
|
|
128
160
|
];
|
|
@@ -4,10 +4,10 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
|
|
5
5
|
import { getSingle, hasFlag } from '../shared/args.mjs';
|
|
6
6
|
import { printTextResource } from '../shared/text-resource.mjs';
|
|
7
|
+
import { validateWorkspaceShape } from '../shared/workspace-validation.mjs';
|
|
7
8
|
|
|
8
9
|
const COMMAND_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
9
10
|
const HELP_FILE = path.resolve(COMMAND_DIR, 'help.txt');
|
|
10
|
-
const GLOB_TOKEN_PATTERN = /[*?{}[\]]/;
|
|
11
11
|
const REQUIRED_WORKSPACE_FIELDS = ['private', 'workspaces', 'scripts'];
|
|
12
12
|
const REQUIRED_WORKSPACE_SCRIPTS = ['deps:install', 'test', 'produck:coverage', 'lint'];
|
|
13
13
|
|
|
@@ -43,40 +43,12 @@ function validateWorkspacePackageJson(cwd, checkPath) {
|
|
|
43
43
|
return check;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
check.ok = false;
|
|
53
|
-
} else {
|
|
54
|
-
check.missingScripts = REQUIRED_WORKSPACE_SCRIPTS.filter((scriptName) => {
|
|
55
|
-
return !(scriptName in json.scripts);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const workspaceList = Array.isArray(json.workspaces)
|
|
60
|
-
? json.workspaces.map((entry) => String(entry))
|
|
61
|
-
: [];
|
|
62
|
-
if (!Array.isArray(json.workspaces)) {
|
|
63
|
-
check.wildcardWorkspaces = ['<non-array-workspaces>'];
|
|
64
|
-
check.ok = false;
|
|
65
|
-
} else {
|
|
66
|
-
check.wildcardWorkspaces = workspaceList.filter((entry) => GLOB_TOKEN_PATTERN.test(entry));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (json.private !== true) {
|
|
70
|
-
check.ok = false;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (check.missingFields.length > 0 || check.missingScripts.length > 0) {
|
|
74
|
-
check.ok = false;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (check.wildcardWorkspaces.length > 0) {
|
|
78
|
-
check.ok = false;
|
|
79
|
-
}
|
|
46
|
+
const shape = validateWorkspaceShape(json, REQUIRED_WORKSPACE_FIELDS, REQUIRED_WORKSPACE_SCRIPTS);
|
|
47
|
+
check.missingFields = shape.missingFields;
|
|
48
|
+
check.scriptTypeValid = shape.scriptTypeValid;
|
|
49
|
+
check.missingScripts = shape.missingScripts;
|
|
50
|
+
check.wildcardWorkspaces = shape.wildcardWorkspaces;
|
|
51
|
+
check.ok = shape.ok;
|
|
80
52
|
|
|
81
53
|
return check;
|
|
82
54
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const GLOB_TOKEN_PATTERN = /[*?{}[\]]/;
|
|
2
|
+
|
|
3
|
+
export function toObjectRecord(value) {
|
|
4
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
5
|
+
return { ...value };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function findMissingKeys(record, requiredKeys) {
|
|
12
|
+
return requiredKeys.filter((key) => {
|
|
13
|
+
return !(key in record);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function validateWorkspaceShape(pkg, requiredFields, requiredScripts) {
|
|
18
|
+
const missingFields = findMissingKeys(pkg, requiredFields);
|
|
19
|
+
const scripts = toObjectRecord(pkg.scripts);
|
|
20
|
+
const scriptTypeValid =
|
|
21
|
+
typeof pkg.scripts === 'object' && pkg.scripts !== null && !Array.isArray(pkg.scripts);
|
|
22
|
+
const missingScripts = scriptTypeValid ? findMissingKeys(scripts, requiredScripts) : [];
|
|
23
|
+
|
|
24
|
+
const workspacesIsArray = Array.isArray(pkg.workspaces);
|
|
25
|
+
const wildcardWorkspaces = workspacesIsArray
|
|
26
|
+
? pkg.workspaces.map((entry) => String(entry)).filter((entry) => GLOB_TOKEN_PATTERN.test(entry))
|
|
27
|
+
: ['<non-array-workspaces>'];
|
|
28
|
+
|
|
29
|
+
const privateIsTrue = pkg.private === true;
|
|
30
|
+
const ok =
|
|
31
|
+
missingFields.length === 0 &&
|
|
32
|
+
scriptTypeValid &&
|
|
33
|
+
missingScripts.length === 0 &&
|
|
34
|
+
workspacesIsArray &&
|
|
35
|
+
wildcardWorkspaces.length === 0 &&
|
|
36
|
+
privateIsTrue;
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
ok,
|
|
40
|
+
missingFields,
|
|
41
|
+
scriptTypeValid,
|
|
42
|
+
missingScripts,
|
|
43
|
+
wildcardWorkspaces,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function validateRequiredExactEntries(currentRecord, requiredRecord) {
|
|
48
|
+
const mismatches = {};
|
|
49
|
+
|
|
50
|
+
for (const [name, expectedValue] of Object.entries(requiredRecord)) {
|
|
51
|
+
if (currentRecord[name] !== expectedValue) {
|
|
52
|
+
mismatches[name] = {
|
|
53
|
+
expected: expectedValue,
|
|
54
|
+
actual: name in currentRecord ? currentRecord[name] : null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
ok: Object.keys(mismatches).length === 0,
|
|
61
|
+
mismatches,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -3,10 +3,14 @@ Usage:
|
|
|
3
3
|
[--workspace <path>] ... [--check] [--dry-run] [--json <file>]
|
|
4
4
|
|
|
5
5
|
Behavior:
|
|
6
|
-
-
|
|
6
|
+
- Adds or updates scripts.produck:coverage and devDependencies.c8 in each workspace package.json.
|
|
7
|
+
- Enforces scripts.test in each workspace package.json.
|
|
8
|
+
- If scripts.test is missing, generates:
|
|
9
|
+
node -e "console.log('No tests configured')"
|
|
10
|
+
- The produck:coverage script in subpackages is for local and AI development use only.
|
|
11
|
+
- Subpackage produck:coverage is NOT enforced by organization CI or .c8rc.json.
|
|
12
|
+
- Only the root workspace (monorepo root) is subject to org-level coverage enforcement and .c8rc.json.
|
|
7
13
|
- Organization-reserved script key is scripts.produck:coverage
|
|
8
|
-
- Applies organization-required pinned local c8 devDependency to workspace
|
|
9
|
-
package.json files
|
|
10
14
|
- Target script is rendered from organization tooling baseline file
|
|
11
15
|
(lookup order):
|
|
12
16
|
1) .github/distribution/produck/tooling-version-baseline.json
|
|
@@ -17,6 +21,9 @@ Behavior:
|
|
|
17
21
|
Rules:
|
|
18
22
|
- When --workspace is omitted, root package.json workspaces are used
|
|
19
23
|
- Root workspaces must be explicit paths (no glob tokens)
|
|
24
|
+
- Workspace package.json files must include scripts.test
|
|
20
25
|
- Workspace package.json files must pin devDependencies.c8 to baseline version
|
|
26
|
+
- Subpackage produck:coverage is not a CI or org gate; it is for local/dev use only
|
|
27
|
+
- Only the root workspace is enforced by org CI and .c8rc.json
|
|
21
28
|
- --check validates without writing and exits non-zero on mismatch
|
|
22
29
|
- --dry-run prints planned changes without writing
|
|
@@ -15,6 +15,8 @@ const TOOLING_BASELINE_CANDIDATE_PATHS = [
|
|
|
15
15
|
];
|
|
16
16
|
const GLOB_TOKEN_PATTERN = /[*?{}[\]]/;
|
|
17
17
|
const REQUIRED_COVERAGE_SCRIPT_KEY = 'produck:coverage';
|
|
18
|
+
const REQUIRED_TEST_SCRIPT_KEY = 'test';
|
|
19
|
+
const DEFAULT_TEST_SCRIPT_VALUE = 'node -e "console.log(\'No tests configured\')"';
|
|
18
20
|
|
|
19
21
|
export function printSyncCoverageScriptHelp() {
|
|
20
22
|
printTextResource(HELP_FILE);
|
|
@@ -132,10 +134,14 @@ function reconcileCoverageScript(
|
|
|
132
134
|
validJson: false,
|
|
133
135
|
previousCoverage: null,
|
|
134
136
|
coverageScript: null,
|
|
137
|
+
previousTestScript: null,
|
|
138
|
+
testScript: null,
|
|
135
139
|
previousC8DevDependency: null,
|
|
136
140
|
c8DevDependency: null,
|
|
137
141
|
matchesRequiredCoverageBefore: false,
|
|
138
142
|
matchesRequiredCoverageAfter: false,
|
|
143
|
+
hasRequiredTestScriptBefore: false,
|
|
144
|
+
hasRequiredTestScriptAfter: false,
|
|
139
145
|
matchesRequiredC8DevDependencyBefore: false,
|
|
140
146
|
matchesRequiredC8DevDependencyAfter: false,
|
|
141
147
|
updated: false,
|
|
@@ -172,18 +178,30 @@ function reconcileCoverageScript(
|
|
|
172
178
|
typeof scripts[REQUIRED_COVERAGE_SCRIPT_KEY] === 'string'
|
|
173
179
|
? scripts[REQUIRED_COVERAGE_SCRIPT_KEY]
|
|
174
180
|
: null;
|
|
181
|
+
const previousTestScript =
|
|
182
|
+
typeof scripts[REQUIRED_TEST_SCRIPT_KEY] === 'string' &&
|
|
183
|
+
scripts[REQUIRED_TEST_SCRIPT_KEY].trim() !== ''
|
|
184
|
+
? scripts[REQUIRED_TEST_SCRIPT_KEY]
|
|
185
|
+
: null;
|
|
175
186
|
const previousC8DevDependency =
|
|
176
187
|
typeof devDependencies.c8 === 'string' ? devDependencies.c8 : null;
|
|
177
188
|
result.previousCoverage = previousCoverage;
|
|
189
|
+
result.previousTestScript = previousTestScript;
|
|
178
190
|
result.previousC8DevDependency = previousC8DevDependency;
|
|
179
191
|
result.matchesRequiredCoverageBefore = previousCoverage === requiredCoverageScript;
|
|
192
|
+
result.hasRequiredTestScriptBefore = previousTestScript !== null;
|
|
180
193
|
result.matchesRequiredC8DevDependencyBefore = previousC8DevDependency === requiredC8Version;
|
|
181
194
|
|
|
182
195
|
if (
|
|
183
|
-
(!result.matchesRequiredCoverageBefore ||
|
|
196
|
+
(!result.matchesRequiredCoverageBefore ||
|
|
197
|
+
!result.hasRequiredTestScriptBefore ||
|
|
198
|
+
!result.matchesRequiredC8DevDependencyBefore) &&
|
|
184
199
|
mode === 'sync'
|
|
185
200
|
) {
|
|
186
201
|
scripts[REQUIRED_COVERAGE_SCRIPT_KEY] = requiredCoverageScript;
|
|
202
|
+
if (!result.hasRequiredTestScriptBefore) {
|
|
203
|
+
scripts[REQUIRED_TEST_SCRIPT_KEY] = DEFAULT_TEST_SCRIPT_VALUE;
|
|
204
|
+
}
|
|
187
205
|
devDependencies.c8 = requiredC8Version;
|
|
188
206
|
pkg.scripts = scripts;
|
|
189
207
|
pkg.devDependencies = devDependencies;
|
|
@@ -195,12 +213,18 @@ function reconcileCoverageScript(
|
|
|
195
213
|
mode === 'sync' && !result.matchesRequiredCoverageBefore
|
|
196
214
|
? requiredCoverageScript
|
|
197
215
|
: previousCoverage;
|
|
216
|
+
result.testScript =
|
|
217
|
+
mode === 'sync' && !result.hasRequiredTestScriptBefore
|
|
218
|
+
? DEFAULT_TEST_SCRIPT_VALUE
|
|
219
|
+
: previousTestScript;
|
|
198
220
|
result.c8DevDependency =
|
|
199
221
|
mode === 'sync' && !result.matchesRequiredC8DevDependencyBefore
|
|
200
222
|
? requiredC8Version
|
|
201
223
|
: previousC8DevDependency;
|
|
202
224
|
|
|
203
225
|
result.matchesRequiredCoverageAfter = result.updated || result.matchesRequiredCoverageBefore;
|
|
226
|
+
result.hasRequiredTestScriptAfter =
|
|
227
|
+
(mode === 'sync' && !result.hasRequiredTestScriptBefore) || result.hasRequiredTestScriptBefore;
|
|
204
228
|
result.matchesRequiredC8DevDependencyAfter =
|
|
205
229
|
result.updated || result.matchesRequiredC8DevDependencyBefore;
|
|
206
230
|
return result;
|
|
@@ -232,6 +256,7 @@ export function runSyncCoverageScript(options) {
|
|
|
232
256
|
c8Version: toolingBaseline.tools.c8.version,
|
|
233
257
|
},
|
|
234
258
|
requiredCoverageScript,
|
|
259
|
+
requiredTestScript: DEFAULT_TEST_SCRIPT_VALUE,
|
|
235
260
|
requiredC8DevDependency: requiredC8Version,
|
|
236
261
|
workspaces: workspacePaths,
|
|
237
262
|
results: [],
|
|
@@ -256,7 +281,9 @@ export function runSyncCoverageScript(options) {
|
|
|
256
281
|
|
|
257
282
|
if (
|
|
258
283
|
mode === 'check' &&
|
|
259
|
-
(!item.matchesRequiredCoverageAfter ||
|
|
284
|
+
(!item.matchesRequiredCoverageAfter ||
|
|
285
|
+
!item.hasRequiredTestScriptAfter ||
|
|
286
|
+
!item.matchesRequiredC8DevDependencyAfter)
|
|
260
287
|
) {
|
|
261
288
|
report.ok = false;
|
|
262
289
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Usage:
|
|
2
|
+
agent-toolkit sync-editorconfig [--cwd <dir>] [--check] [--dry-run]
|
|
3
|
+
[--json <file>]
|
|
4
|
+
|
|
5
|
+
Behavior:
|
|
6
|
+
- Applies organization-required root .editorconfig file
|
|
7
|
+
- Creates .editorconfig if missing, or merges missing required entries
|
|
8
|
+
if file already exists
|
|
9
|
+
|
|
10
|
+
Rules:
|
|
11
|
+
- --check validates without writing and exits non-zero on mismatch
|
|
12
|
+
- --dry-run prints planned changes without writing
|
|
13
|
+
- --check takes precedence over --dry-run
|