ai-catapult 0.1.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.
Files changed (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/bin/ai-catapult.js +229 -0
  4. package/dist/claude-plugin/.claude-plugin/marketplace.json +28 -0
  5. package/dist/claude-plugin/.claude-plugin/plugin.json +21 -0
  6. package/dist/claude-plugin/skills/ai-catapult-init/REFERENCE.md +1284 -0
  7. package/dist/claude-plugin/skills/ai-catapult-init/SKILL.md +79 -0
  8. package/dist/claude-plugin/skills/ai-catapult-init/modules/README.md +48 -0
  9. package/dist/claude-plugin/skills/ai-catapult-init/modules/archgate.md +42 -0
  10. package/dist/claude-plugin/skills/ai-catapult-init/modules/brd-prd-traceability.md +64 -0
  11. package/dist/claude-plugin/skills/ai-catapult-init/modules/cascade.md +110 -0
  12. package/dist/claude-plugin/skills/ai-catapult-init/modules/ci-policy.md +107 -0
  13. package/dist/claude-plugin/skills/ai-catapult-init/modules/documentation-blueprint.md +185 -0
  14. package/dist/claude-plugin/skills/ai-catapult-init/modules/evals.md +93 -0
  15. package/dist/claude-plugin/skills/ai-catapult-init/modules/foundation.md +19 -0
  16. package/dist/claude-plugin/skills/ai-catapult-init/modules/host-policy-automation.md +151 -0
  17. package/dist/claude-plugin/skills/ai-catapult-init/modules/language-packs.md +63 -0
  18. package/dist/claude-plugin/skills/ai-catapult-init/modules/mcp-a2a.md +63 -0
  19. package/dist/claude-plugin/skills/ai-catapult-init/modules/memory.md +102 -0
  20. package/dist/claude-plugin/skills/ai-catapult-init/modules/migration.md +107 -0
  21. package/dist/claude-plugin/skills/ai-catapult-init/modules/phases/01-discover-decide.md +33 -0
  22. package/dist/claude-plugin/skills/ai-catapult-init/modules/phases/README.md +33 -0
  23. package/dist/claude-plugin/skills/ai-catapult-init/modules/readme-documentation.md +120 -0
  24. package/dist/claude-plugin/skills/ai-catapult-init/modules/release-versioning.md +188 -0
  25. package/dist/claude-plugin/skills/ai-catapult-init/modules/skill-modernization.md +72 -0
  26. package/dist/claude-plugin/skills/ai-catapult-init/modules/sync.md +111 -0
  27. package/dist/claude-plugin/skills/ai-catapult-init/modules/topology.md +102 -0
  28. package/dist/claude-plugin/skills/ai-catapult-init/modules/traceability.md +136 -0
  29. package/dist/claude-plugin/skills/ai-catapult-init/modules/tracker-adapters.md +51 -0
  30. package/dist/claude-plugin/skills/ai-catapult-init/modules/validation.md +276 -0
  31. package/dist/claude-plugin/skills/ai-catapult-init/modules/workflow.md +45 -0
  32. package/dist/claude-plugin/skills/ai-catapult-init/templates/AGENTS.md +69 -0
  33. package/dist/claude-plugin/skills/ai-catapult-init/templates/CLAUDE.md +3 -0
  34. package/dist/claude-plugin/skills/ai-catapult-init/templates/GEMINI.md +3 -0
  35. package/dist/claude-plugin/skills/ai-catapult-init/templates/boundary-manifest.json +247 -0
  36. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/drift/backups/.gitkeep +0 -0
  37. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/drift/last-drift.json +7 -0
  38. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/evals/.gitkeep +0 -0
  39. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/evals/coverage-exceptions.json +1 -0
  40. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/handoff/.gitkeep +0 -0
  41. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/matrix.json +19 -0
  42. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/mcp/a2a-handoff.md +51 -0
  43. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/mcp/registry.json +27 -0
  44. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/observability/audit-checklist.md +32 -0
  45. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/observability/conventions.md +35 -0
  46. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/phases/01-discover-decide/status.json +16 -0
  47. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/phases/02-govern-plan/status.json +15 -0
  48. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/phases/03-configure-generate/status.json +22 -0
  49. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/phases/04-validate-handoff/status.json +18 -0
  50. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/policies/model-routing.json +29 -0
  51. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/reviews/ai-failure-modes.md +42 -0
  52. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/rules/security.md +38 -0
  53. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/rules/technical-bounds.md +38 -0
  54. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/skills/git-ops.json +6 -0
  55. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/skills/workspace-sync.json +6 -0
  56. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/system-prompts/architect.md +31 -0
  57. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/system-prompts/developer.md +31 -0
  58. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/system-prompts/qa-engineer.md +31 -0
  59. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/traceability/.gitkeep +0 -0
  60. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/workflows/repo-workflow.json +42 -0
  61. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-ai/workflows/repo-workflow.md +52 -0
  62. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-github/workflows/ci-prek.yml +21 -0
  63. package/dist/claude-plugin/skills/ai-catapult-init/templates/dot-rules.ts +178 -0
  64. package/dist/claude-plugin/skills/ai-catapult-init/templates/prek.toml +13 -0
  65. package/dist/codex-plugin/.codex-plugin/plugin.json +11 -0
  66. package/dist/codex-plugin/skills/ai-catapult-init/REFERENCE.md +1284 -0
  67. package/dist/codex-plugin/skills/ai-catapult-init/SKILL.md +79 -0
  68. package/dist/codex-plugin/skills/ai-catapult-init/modules/README.md +48 -0
  69. package/dist/codex-plugin/skills/ai-catapult-init/modules/archgate.md +42 -0
  70. package/dist/codex-plugin/skills/ai-catapult-init/modules/brd-prd-traceability.md +64 -0
  71. package/dist/codex-plugin/skills/ai-catapult-init/modules/cascade.md +110 -0
  72. package/dist/codex-plugin/skills/ai-catapult-init/modules/ci-policy.md +107 -0
  73. package/dist/codex-plugin/skills/ai-catapult-init/modules/documentation-blueprint.md +185 -0
  74. package/dist/codex-plugin/skills/ai-catapult-init/modules/evals.md +93 -0
  75. package/dist/codex-plugin/skills/ai-catapult-init/modules/foundation.md +19 -0
  76. package/dist/codex-plugin/skills/ai-catapult-init/modules/host-policy-automation.md +151 -0
  77. package/dist/codex-plugin/skills/ai-catapult-init/modules/language-packs.md +63 -0
  78. package/dist/codex-plugin/skills/ai-catapult-init/modules/mcp-a2a.md +63 -0
  79. package/dist/codex-plugin/skills/ai-catapult-init/modules/memory.md +102 -0
  80. package/dist/codex-plugin/skills/ai-catapult-init/modules/migration.md +107 -0
  81. package/dist/codex-plugin/skills/ai-catapult-init/modules/phases/01-discover-decide.md +33 -0
  82. package/dist/codex-plugin/skills/ai-catapult-init/modules/phases/README.md +33 -0
  83. package/dist/codex-plugin/skills/ai-catapult-init/modules/readme-documentation.md +120 -0
  84. package/dist/codex-plugin/skills/ai-catapult-init/modules/release-versioning.md +188 -0
  85. package/dist/codex-plugin/skills/ai-catapult-init/modules/skill-modernization.md +72 -0
  86. package/dist/codex-plugin/skills/ai-catapult-init/modules/sync.md +111 -0
  87. package/dist/codex-plugin/skills/ai-catapult-init/modules/topology.md +102 -0
  88. package/dist/codex-plugin/skills/ai-catapult-init/modules/traceability.md +136 -0
  89. package/dist/codex-plugin/skills/ai-catapult-init/modules/tracker-adapters.md +51 -0
  90. package/dist/codex-plugin/skills/ai-catapult-init/modules/validation.md +276 -0
  91. package/dist/codex-plugin/skills/ai-catapult-init/modules/workflow.md +45 -0
  92. package/dist/codex-plugin/skills/ai-catapult-init/templates/AGENTS.md +69 -0
  93. package/dist/codex-plugin/skills/ai-catapult-init/templates/CLAUDE.md +3 -0
  94. package/dist/codex-plugin/skills/ai-catapult-init/templates/GEMINI.md +3 -0
  95. package/dist/codex-plugin/skills/ai-catapult-init/templates/boundary-manifest.json +247 -0
  96. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/drift/backups/.gitkeep +0 -0
  97. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/drift/last-drift.json +7 -0
  98. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/evals/.gitkeep +0 -0
  99. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/evals/coverage-exceptions.json +1 -0
  100. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/handoff/.gitkeep +0 -0
  101. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/matrix.json +19 -0
  102. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/mcp/a2a-handoff.md +51 -0
  103. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/mcp/registry.json +27 -0
  104. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/observability/audit-checklist.md +32 -0
  105. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/observability/conventions.md +35 -0
  106. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/phases/01-discover-decide/status.json +16 -0
  107. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/phases/02-govern-plan/status.json +15 -0
  108. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/phases/03-configure-generate/status.json +22 -0
  109. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/phases/04-validate-handoff/status.json +18 -0
  110. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/policies/model-routing.json +29 -0
  111. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/reviews/ai-failure-modes.md +42 -0
  112. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/rules/security.md +38 -0
  113. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/rules/technical-bounds.md +38 -0
  114. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/skills/git-ops.json +6 -0
  115. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/skills/workspace-sync.json +6 -0
  116. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/system-prompts/architect.md +31 -0
  117. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/system-prompts/developer.md +31 -0
  118. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/system-prompts/qa-engineer.md +31 -0
  119. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/traceability/.gitkeep +0 -0
  120. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/workflows/repo-workflow.json +42 -0
  121. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-ai/workflows/repo-workflow.md +52 -0
  122. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-github/workflows/ci-prek.yml +21 -0
  123. package/dist/codex-plugin/skills/ai-catapult-init/templates/dot-rules.ts +178 -0
  124. package/dist/codex-plugin/skills/ai-catapult-init/templates/prek.toml +13 -0
  125. package/package.json +53 -0
  126. package/scripts/build-claude-plugin.sh +179 -0
  127. package/scripts/build-codex-plugin.sh +104 -0
  128. package/scripts/snapshot-dist.sh +26 -0
  129. package/setup.sh +63 -0
  130. package/skills.lock.json +6 -0
  131. package/src/install.js +380 -0
  132. package/src/scaffold.js +220 -0
@@ -0,0 +1,220 @@
1
+ /**
2
+ * scaffold.js — deterministic v3 .ai/ scaffold engine (Slice 3).
3
+ *
4
+ * Reads vendored ai-catapult-init/templates/ + boundary-manifest.json and
5
+ * emits all MECHANICAL paths into a target directory. Judgment-laden paths
6
+ * are not written as files (only their parent dirs may be created where a
7
+ * .gitkeep sits in the template tree to track the directory).
8
+ *
9
+ * Determinism guarantees:
10
+ * - Template files are iterated in sorted manifest order (not filesystem order).
11
+ * - Token substitution is a pure synchronous replace — no timestamps beyond
12
+ * the injected {{DATE}}, no Math.random, no OS entropy.
13
+ * - Same inputs → byte-identical output.
14
+ *
15
+ * Token map (all tokens that appear across templates):
16
+ * {{REPO_ID}} → repoId
17
+ * {{DATE}} → date (YYYY-MM-DD)
18
+ * {{UPSTREAM_URL}} → upstreamUrl
19
+ * {{UPSTREAM_REF}} → upstreamRef
20
+ *
21
+ * Path-prefix mapping (template path → real filesystem path):
22
+ * dot-ai/ → .ai/
23
+ * dot-github/ → .github/
24
+ * dot-rules.ts → .rules.ts
25
+ * (everything else maps 1:1)
26
+ */
27
+
28
+ import { readFileSync, writeFileSync, mkdirSync, readdirSync, existsSync } from 'node:fs';
29
+ import { dirname, join, resolve, sep } from 'node:path';
30
+
31
+ /**
32
+ * Map a template-relative path to its real output path.
33
+ * e.g. "dot-ai/matrix.json" → ".ai/matrix.json"
34
+ * "dot-github/workflows/ci.yml" → ".github/workflows/ci.yml"
35
+ * "dot-rules.ts" → ".rules.ts"
36
+ */
37
+ function templatePathToRealPath(templatePath) {
38
+ if (templatePath.startsWith('dot-ai/')) {
39
+ return '.ai/' + templatePath.slice('dot-ai/'.length);
40
+ }
41
+ if (templatePath.startsWith('dot-github/')) {
42
+ return '.github/' + templatePath.slice('dot-github/'.length);
43
+ }
44
+ if (templatePath === 'dot-rules.ts') {
45
+ return '.rules.ts';
46
+ }
47
+ // All other templates (AGENTS.md, CLAUDE.md, GEMINI.md, prek.toml) map 1:1.
48
+ return templatePath;
49
+ }
50
+
51
+ /**
52
+ * Substitute all {{TOKEN}} placeholders in content.
53
+ * @param {string} content - raw template content
54
+ * @param {object} tokens - { REPO_ID, DATE, UPSTREAM_URL, UPSTREAM_REF }
55
+ * @returns {string}
56
+ */
57
+ function substituteTokens(content, tokens) {
58
+ return content
59
+ .replaceAll('{{REPO_ID}}', tokens.REPO_ID)
60
+ .replaceAll('{{DATE}}', tokens.DATE)
61
+ .replaceAll('{{UPSTREAM_URL}}', tokens.UPSTREAM_URL)
62
+ .replaceAll('{{UPSTREAM_REF}}', tokens.UPSTREAM_REF);
63
+ }
64
+
65
+ /**
66
+ * Assert that destPath is strictly inside targetDir.
67
+ * Throws a clear error if a path traversal is detected.
68
+ * @param {string} destPath - absolute destination path
69
+ * @param {string} targetDir - absolute target root
70
+ */
71
+ function assertNoTraversal(destPath, targetDir) {
72
+ const resolvedDest = resolve(destPath);
73
+ const resolvedRoot = resolve(targetDir) + sep;
74
+ if (!resolvedDest.startsWith(resolvedRoot)) {
75
+ throw new Error(
76
+ `Path traversal detected: manifest path resolves to "${resolvedDest}" which is outside target directory "${resolve(targetDir)}". Aborting.`,
77
+ );
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Recursively copy any .gitkeep files from the template tree into targetDir,
83
+ * using the same dot-* path mapping as templatePathToRealPath.
84
+ *
85
+ * @param {string} baseTemplatesDir - absolute path to templates root (for computing relative paths)
86
+ * @param {string} currentDir - current directory being walked
87
+ * @param {string} targetDir - absolute output root
88
+ * @param {boolean} force - overwrite existing files
89
+ * @param {string[]} collisions - accumulator for collision paths (when force=false)
90
+ */
91
+ function emitGitkeeps(baseTemplatesDir, currentDir, targetDir, force, collisions) {
92
+ const entries = readdirSync(currentDir, { withFileTypes: true });
93
+ // Sort for determinism
94
+ entries.sort((a, b) => a.name.localeCompare(b.name));
95
+ for (const entry of entries) {
96
+ const srcFull = join(currentDir, entry.name);
97
+ if (entry.isDirectory()) {
98
+ emitGitkeeps(baseTemplatesDir, srcFull, targetDir, force, collisions);
99
+ } else if (entry.name === '.gitkeep') {
100
+ // e.g. baseTemplatesDir = "/…/templates", srcFull = "/…/templates/dot-ai/evals/.gitkeep"
101
+ // relFromTemplates = "dot-ai/evals/.gitkeep"
102
+ const relFromTemplates = srcFull.slice(baseTemplatesDir.length + 1);
103
+ const realRel = templatePathToRealPath(relFromTemplates);
104
+ const destFull = join(targetDir, realRel);
105
+ assertNoTraversal(destFull, targetDir);
106
+ if (!force && existsSync(destFull)) {
107
+ collisions.push(realRel);
108
+ continue;
109
+ }
110
+ mkdirSync(dirname(destFull), { recursive: true });
111
+ writeFileSync(destFull, '', 'utf8');
112
+ }
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Scaffold the mechanical v3 .ai/ skeleton into targetDir.
118
+ *
119
+ * @param {object} opts
120
+ * @param {string} opts.targetDir - absolute path to emit into
121
+ * @param {string} opts.templatesDir - absolute path to vendored templates/
122
+ * @param {string} opts.repoId - {{REPO_ID}} substitution value
123
+ * @param {string} opts.date - {{DATE}} substitution value (YYYY-MM-DD)
124
+ * @param {string} opts.upstreamUrl - {{UPSTREAM_URL}} substitution value
125
+ * @param {string} opts.upstreamRef - {{UPSTREAM_REF}} substitution value
126
+ * @param {boolean} [opts.force] - overwrite existing files without error
127
+ * @returns {{ emittedPaths: string[], judgmentLadenPaths: string[] }}
128
+ */
129
+ export function scaffold({ targetDir, templatesDir, repoId, date, upstreamUrl, upstreamRef, force = false }) {
130
+ const manifestPath = join(templatesDir, 'boundary-manifest.json');
131
+
132
+ // Fix #8: friendly error when vendor/manifest is missing
133
+ let manifest;
134
+ try {
135
+ manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
136
+ } catch (err) {
137
+ if (err.code === 'ENOENT') {
138
+ process.stderr.write('vendor/ missing or stale — run: bash setup.sh\n');
139
+ process.exit(1);
140
+ }
141
+ throw err;
142
+ }
143
+
144
+ const tokens = {
145
+ REPO_ID: repoId,
146
+ DATE: date,
147
+ UPSTREAM_URL: upstreamUrl,
148
+ UPSTREAM_REF: upstreamRef,
149
+ };
150
+
151
+ // Fix #3: collect collisions before writing anything
152
+ const collisions = [];
153
+
154
+ // Iterate in manifest order (deterministic — not filesystem readdir order).
155
+ for (const entry of manifest.paths) {
156
+ if (entry.classification !== 'mechanical' || entry.template === null) {
157
+ // Judgment-laden: do not emit any file.
158
+ continue;
159
+ }
160
+
161
+ const templateRelPath = entry.template; // e.g. "dot-ai/matrix.json"
162
+ const realRelPath = templatePathToRealPath(templateRelPath); // e.g. ".ai/matrix.json"
163
+
164
+ const srcPath = join(templatesDir, templateRelPath);
165
+ const destPath = join(targetDir, realRelPath);
166
+
167
+ // Fix #4: defense-in-depth traversal check
168
+ assertNoTraversal(destPath, targetDir);
169
+
170
+ if (!force && existsSync(destPath)) {
171
+ collisions.push(realRelPath);
172
+ }
173
+ }
174
+
175
+ // Fix #3: refuse if collisions exist and --force not passed
176
+ if (collisions.length > 0) {
177
+ process.stderr.write(
178
+ `error: init would overwrite existing files in ${targetDir}:\n` +
179
+ collisions.map((p) => ` ${p}`).join('\n') +
180
+ '\nPass --force to overwrite.\n',
181
+ );
182
+ process.exit(1);
183
+ }
184
+
185
+ // All clear — write files
186
+ const emittedPaths = [];
187
+ for (const entry of manifest.paths) {
188
+ if (entry.classification !== 'mechanical' || entry.template === null) {
189
+ continue;
190
+ }
191
+
192
+ const templateRelPath = entry.template;
193
+ const realRelPath = templatePathToRealPath(templateRelPath);
194
+
195
+ const srcPath = join(templatesDir, templateRelPath);
196
+ const destPath = join(targetDir, realRelPath);
197
+
198
+ const raw = readFileSync(srcPath, 'utf8');
199
+ const rendered = substituteTokens(raw, tokens);
200
+
201
+ mkdirSync(dirname(destPath), { recursive: true });
202
+ writeFileSync(destPath, rendered, 'utf8');
203
+ emittedPaths.push(realRelPath);
204
+ }
205
+
206
+ // Emit .gitkeep files so tracked empty directories land in the target.
207
+ // These are not listed in the boundary-manifest (they are git artifacts),
208
+ // so we walk the template tree for .gitkeep files and mirror them verbatim.
209
+ const gitkeepCollisions = [];
210
+ emitGitkeeps(templatesDir, templatesDir, targetDir, force, gitkeepCollisions);
211
+ // .gitkeep collisions are non-fatal — they are empty marker files; silently
212
+ // skip them if --force was not given (the directory already exists).
213
+
214
+ // Collect judgment-laden paths from manifest (for finish prompt).
215
+ const judgmentLadenPaths = manifest.paths
216
+ .filter((e) => e.classification === 'judgment_laden')
217
+ .map((e) => e.path);
218
+
219
+ return { emittedPaths, judgmentLadenPaths };
220
+ }