mustflow 2.84.0 → 2.99.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 +11 -2
- package/dist/cli/commands/script-pack.js +14 -0
- package/dist/cli/i18n/en.js +262 -0
- package/dist/cli/i18n/es.js +262 -0
- package/dist/cli/i18n/fr.js +262 -0
- package/dist/cli/i18n/hi.js +262 -0
- package/dist/cli/i18n/ko.js +262 -0
- package/dist/cli/i18n/zh.js +262 -0
- package/dist/cli/lib/repo-map.js +27 -6
- package/dist/cli/lib/run-root-trust.js +15 -1
- package/dist/cli/lib/script-pack-registry.js +397 -0
- package/dist/cli/lib/validation/index.js +2 -2
- package/dist/cli/lib/validation/primitives.js +4 -1
- package/dist/cli/script-packs/code-change-impact.js +178 -0
- package/dist/cli/script-packs/code-dependency-graph.js +181 -0
- package/dist/cli/script-packs/code-import-cycle.js +193 -0
- package/dist/cli/script-packs/docs-link-integrity.js +145 -0
- package/dist/cli/script-packs/repo-approval-gate.js +100 -0
- package/dist/cli/script-packs/repo-env-contract.js +156 -0
- package/dist/cli/script-packs/repo-git-ignore-audit.js +119 -0
- package/dist/cli/script-packs/repo-manifest-lock-drift.js +122 -0
- package/dist/cli/script-packs/repo-merge-conflict-scan.js +123 -0
- package/dist/cli/script-packs/repo-secret-risk-scan.js +147 -0
- package/dist/cli/script-packs/repo-skill-route-audit.js +86 -0
- package/dist/cli/script-packs/repo-version-source.js +92 -0
- package/dist/cli/script-packs/test-performance-report.js +247 -0
- package/dist/cli/script-packs/test-regression-selector.js +167 -0
- package/dist/core/change-impact.js +355 -0
- package/dist/core/change-surface-classification.js +198 -0
- package/dist/core/change-verification.js +32 -5
- package/dist/core/config-loading.js +121 -4
- package/dist/core/dependency-graph.js +490 -0
- package/dist/core/docs-link-integrity.js +443 -0
- package/dist/core/env-contract.js +450 -0
- package/dist/core/import-cycle.js +152 -0
- package/dist/core/line-endings.js +26 -13
- package/dist/core/public-json-contracts.js +167 -0
- package/dist/core/repo-approval-gate.js +116 -0
- package/dist/core/repo-git-ignore-audit.js +302 -0
- package/dist/core/repo-manifest-lock-drift.js +321 -0
- package/dist/core/repo-merge-conflict-scan.js +335 -0
- package/dist/core/repo-version-source.js +82 -0
- package/dist/core/route-outline.js +57 -5
- package/dist/core/script-pack-suggestions.js +97 -1
- package/dist/core/secret-risk-scan.js +440 -0
- package/dist/core/skill-route-audit.js +354 -0
- package/dist/core/test-performance-report.js +697 -0
- package/dist/core/test-regression-selector.js +335 -0
- package/package.json +1 -1
- package/schemas/README.md +54 -0
- package/schemas/change-impact-report.schema.json +184 -0
- package/schemas/commands.schema.json +12 -0
- package/schemas/dependency-graph-report.schema.json +149 -0
- package/schemas/env-contract-report.schema.json +203 -0
- package/schemas/import-cycle-report.schema.json +157 -0
- package/schemas/link-integrity-report.schema.json +176 -0
- package/schemas/repo-approval-gate-report.schema.json +115 -0
- package/schemas/repo-git-ignore-audit-report.schema.json +201 -0
- package/schemas/repo-manifest-lock-drift-report.schema.json +202 -0
- package/schemas/repo-merge-conflict-scan-report.schema.json +169 -0
- package/schemas/repo-version-source-report.schema.json +127 -0
- package/schemas/secret-risk-scan-report.schema.json +152 -0
- package/schemas/skill-route-audit-report.schema.json +144 -0
- package/schemas/test-performance-report.schema.json +319 -0
- package/schemas/test-regression-selector-report.schema.json +187 -0
- package/templates/default/i18n.toml +80 -26
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +51 -9
- package/templates/default/locales/en/.mustflow/skills/api-access-control-review/SKILL.md +48 -27
- package/templates/default/locales/en/.mustflow/skills/api-failure-triage/SKILL.md +270 -0
- package/templates/default/locales/en/.mustflow/skills/architecture-deepening-review/SKILL.md +28 -11
- package/templates/default/locales/en/.mustflow/skills/astro-code-change/SKILL.md +71 -27
- package/templates/default/locales/en/.mustflow/skills/auth-flow-triage/SKILL.md +192 -0
- package/templates/default/locales/en/.mustflow/skills/auth-permission-change/SKILL.md +59 -13
- package/templates/default/locales/en/.mustflow/skills/backend-log-evidence-review/SKILL.md +14 -5
- package/templates/default/locales/en/.mustflow/skills/cache-integrity-review/SKILL.md +30 -15
- package/templates/default/locales/en/.mustflow/skills/change-blast-radius-review/SKILL.md +45 -32
- package/templates/default/locales/en/.mustflow/skills/ci-pipeline-triage/SKILL.md +200 -0
- package/templates/default/locales/en/.mustflow/skills/clarifying-question-gate/SKILL.md +87 -13
- package/templates/default/locales/en/.mustflow/skills/cross-agent-session-reference/SKILL.md +23 -8
- package/templates/default/locales/en/.mustflow/skills/dependency-upgrade-review/SKILL.md +3 -1
- package/templates/default/locales/en/.mustflow/skills/docker-runtime-triage/SKILL.md +191 -0
- package/templates/default/locales/en/.mustflow/skills/github-contribution-quality-gate/SKILL.md +48 -11
- package/templates/default/locales/en/.mustflow/skills/go-code-change/SKILL.md +18 -13
- package/templates/default/locales/en/.mustflow/skills/javascript-code-change/SKILL.md +15 -13
- package/templates/default/locales/en/.mustflow/skills/line-ending-hygiene/SKILL.md +18 -10
- package/templates/default/locales/en/.mustflow/skills/llm-hallucination-control-review/SKILL.md +4 -1
- package/templates/default/locales/en/.mustflow/skills/motion-system-contract-review/SKILL.md +155 -0
- package/templates/default/locales/en/.mustflow/skills/next-action-menu/SKILL.md +177 -0
- package/templates/default/locales/en/.mustflow/skills/node-code-change/SKILL.md +16 -14
- package/templates/default/locales/en/.mustflow/skills/observability-debuggability-review/SKILL.md +15 -7
- package/templates/default/locales/en/.mustflow/skills/payment-integrity-review/SKILL.md +59 -35
- package/templates/default/locales/en/.mustflow/skills/powershell-code-change/SKILL.md +16 -6
- package/templates/default/locales/en/.mustflow/skills/prompt-contract-quality-review/SKILL.md +4 -1
- package/templates/default/locales/en/.mustflow/skills/python-code-change/SKILL.md +19 -10
- package/templates/default/locales/en/.mustflow/skills/rag-pipeline-triage/SKILL.md +206 -0
- package/templates/default/locales/en/.mustflow/skills/routes.toml +69 -9
- package/templates/default/locales/en/.mustflow/skills/rust-code-change/SKILL.md +10 -4
- package/templates/default/locales/en/.mustflow/skills/search-index-integrity-review/SKILL.md +181 -0
- package/templates/default/locales/en/.mustflow/skills/security-privacy-review/SKILL.md +3 -1
- package/templates/default/locales/en/.mustflow/skills/service-boundary-architecture/SKILL.md +37 -23
- package/templates/default/locales/en/.mustflow/skills/test-suite-performance-review/SKILL.md +323 -0
- package/templates/default/locales/en/.mustflow/skills/typescript-code-change/SKILL.md +18 -10
- package/templates/default/locales/en/.mustflow/skills/vector-search-integrity-review/SKILL.md +209 -0
- package/templates/default/locales/en/.mustflow/skills/version-freshness-check/SKILL.md +16 -14
- package/templates/default/manifest.toml +71 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { isRecord, readMustflowOwnedTomlFile } from './config-loading.js';
|
|
5
|
+
import { detectVersionSources, releaseVersioningIsEnabled, VERSIONING_CONFIG_PATH, } from './version-sources.js';
|
|
6
|
+
export const REPO_VERSION_SOURCE_PACK_ID = 'repo';
|
|
7
|
+
export const REPO_VERSION_SOURCE_SCRIPT_ID = 'version-source';
|
|
8
|
+
export const REPO_VERSION_SOURCE_SCRIPT_REF = `${REPO_VERSION_SOURCE_PACK_ID}/${REPO_VERSION_SOURCE_SCRIPT_ID}`;
|
|
9
|
+
export const REPO_VERSION_SOURCE_PREFERENCES_PATH = '.mustflow/config/preferences.toml';
|
|
10
|
+
function sha256(value) {
|
|
11
|
+
return `sha256:${createHash('sha256').update(value).digest('hex')}`;
|
|
12
|
+
}
|
|
13
|
+
function readPreferences(projectRoot, issues) {
|
|
14
|
+
const preferencesPath = path.join(projectRoot, ...REPO_VERSION_SOURCE_PREFERENCES_PATH.split('/'));
|
|
15
|
+
if (!existsSync(preferencesPath)) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const parsed = readMustflowOwnedTomlFile(projectRoot, REPO_VERSION_SOURCE_PREFERENCES_PATH);
|
|
20
|
+
return isRecord(parsed) ? parsed : undefined;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
24
|
+
issues.push(`Could not read ${REPO_VERSION_SOURCE_PREFERENCES_PATH}: ${message}`);
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function countSources(sources) {
|
|
29
|
+
return {
|
|
30
|
+
sources: sources.length,
|
|
31
|
+
declared_sources: sources.filter((source) => source.declared === true).length,
|
|
32
|
+
source_authority_sources: sources.filter((source) => source.authority === 'source').length,
|
|
33
|
+
derived_authority_sources: sources.filter((source) => source.authority === 'derived').length,
|
|
34
|
+
unclassified_authority_sources: sources.filter((source) => source.authority === undefined).length,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function createInputHash(reportInput) {
|
|
38
|
+
return sha256(JSON.stringify(reportInput));
|
|
39
|
+
}
|
|
40
|
+
export function inspectRepoVersionSource(projectRoot) {
|
|
41
|
+
const root = path.resolve(projectRoot);
|
|
42
|
+
const issues = [];
|
|
43
|
+
const preferences = readPreferences(root, issues);
|
|
44
|
+
const versioningEnabled = releaseVersioningIsEnabled(preferences);
|
|
45
|
+
const sources = detectVersionSources(root);
|
|
46
|
+
const findings = [];
|
|
47
|
+
if (versioningEnabled && sources.length === 0) {
|
|
48
|
+
findings.push({
|
|
49
|
+
code: 'versioning_enabled_without_sources',
|
|
50
|
+
severity: 'high',
|
|
51
|
+
path: REPO_VERSION_SOURCE_PREFERENCES_PATH,
|
|
52
|
+
message: 'Release versioning preferences are enabled, but no version source was detected.',
|
|
53
|
+
json_pointer: null,
|
|
54
|
+
metric: null,
|
|
55
|
+
actual: 0,
|
|
56
|
+
expected: 1,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const counts = countSources(sources);
|
|
60
|
+
const status = issues.length > 0 ? 'error' : findings.length > 0 ? 'failed' : 'passed';
|
|
61
|
+
return {
|
|
62
|
+
schema_version: '1',
|
|
63
|
+
command: 'script-pack',
|
|
64
|
+
pack_id: REPO_VERSION_SOURCE_PACK_ID,
|
|
65
|
+
script_id: REPO_VERSION_SOURCE_SCRIPT_ID,
|
|
66
|
+
script_ref: REPO_VERSION_SOURCE_SCRIPT_REF,
|
|
67
|
+
action: 'inspect',
|
|
68
|
+
status,
|
|
69
|
+
ok: status === 'passed',
|
|
70
|
+
mustflow_root: root,
|
|
71
|
+
input: {
|
|
72
|
+
preferences_path: REPO_VERSION_SOURCE_PREFERENCES_PATH,
|
|
73
|
+
declared_sources_path: VERSIONING_CONFIG_PATH,
|
|
74
|
+
},
|
|
75
|
+
input_hash: createInputHash({ versioningEnabled, counts, sources, findings, issues }),
|
|
76
|
+
versioning_enabled: versioningEnabled,
|
|
77
|
+
counts,
|
|
78
|
+
sources,
|
|
79
|
+
findings,
|
|
80
|
+
issues,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -821,20 +821,72 @@ function extractNestjsLifecycleDecorator(line) {
|
|
|
821
821
|
: null;
|
|
822
822
|
}
|
|
823
823
|
function extractNestjsHandlerName(line) {
|
|
824
|
-
const
|
|
825
|
-
if (
|
|
824
|
+
const signature = line.trimStart();
|
|
825
|
+
if (signature.length === 0) {
|
|
826
826
|
return null;
|
|
827
827
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
828
|
+
let offset = signature.startsWith('*') ? 1 : 0;
|
|
829
|
+
offset = skipAsciiWhitespace(signature, offset);
|
|
830
|
+
while (true) {
|
|
831
|
+
const next = readIdentifier(signature, offset);
|
|
832
|
+
if (next === null || !isNestjsHandlerModifier(next.value)) {
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
offset = skipAsciiWhitespace(signature, next.end);
|
|
836
|
+
}
|
|
837
|
+
if (signature.charAt(offset) === '*') {
|
|
838
|
+
offset = skipAsciiWhitespace(signature, offset + 1);
|
|
839
|
+
}
|
|
840
|
+
const nameToken = readIdentifier(signature, offset);
|
|
841
|
+
if (nameToken === null) {
|
|
831
842
|
return null;
|
|
832
843
|
}
|
|
844
|
+
const callStart = skipAsciiWhitespace(signature, nameToken.end);
|
|
845
|
+
if (signature.charAt(callStart) !== '(') {
|
|
846
|
+
return null;
|
|
847
|
+
}
|
|
848
|
+
const name = nameToken.value;
|
|
833
849
|
if (/\b(?:if|for|while|switch|return|class|interface|function|new|throw|typeof|in|of)\b/u.test(name)) {
|
|
834
850
|
return null;
|
|
835
851
|
}
|
|
836
852
|
return name;
|
|
837
853
|
}
|
|
854
|
+
function skipAsciiWhitespace(text, offset) {
|
|
855
|
+
let index = offset;
|
|
856
|
+
while (index < text.length) {
|
|
857
|
+
const code = text.charCodeAt(index);
|
|
858
|
+
if (code !== 9 && code !== 10 && code !== 11 && code !== 12 && code !== 13 && code !== 32) {
|
|
859
|
+
break;
|
|
860
|
+
}
|
|
861
|
+
index += 1;
|
|
862
|
+
}
|
|
863
|
+
return index;
|
|
864
|
+
}
|
|
865
|
+
function readIdentifier(text, offset) {
|
|
866
|
+
const first = text.charCodeAt(offset);
|
|
867
|
+
if (!isIdentifierStart(first)) {
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
let end = offset + 1;
|
|
871
|
+
while (end < text.length && isIdentifierPart(text.charCodeAt(end))) {
|
|
872
|
+
end += 1;
|
|
873
|
+
}
|
|
874
|
+
return { value: text.slice(offset, end), end };
|
|
875
|
+
}
|
|
876
|
+
function isIdentifierStart(code) {
|
|
877
|
+
return code === 36 || code === 95 || (code >= 65 && code <= 90) || (code >= 97 && code <= 122);
|
|
878
|
+
}
|
|
879
|
+
function isIdentifierPart(code) {
|
|
880
|
+
return isIdentifierStart(code) || (code >= 48 && code <= 57);
|
|
881
|
+
}
|
|
882
|
+
function isNestjsHandlerModifier(value) {
|
|
883
|
+
return (value === 'public' ||
|
|
884
|
+
value === 'private' ||
|
|
885
|
+
value === 'protected' ||
|
|
886
|
+
value === 'async' ||
|
|
887
|
+
value === 'static' ||
|
|
888
|
+
value === 'readonly');
|
|
889
|
+
}
|
|
838
890
|
function extractNestjsRouteEntries(relativePath, language, contentSha256, lines, block) {
|
|
839
891
|
const routes = [];
|
|
840
892
|
let controllerLifecycle = [];
|
|
@@ -2,13 +2,15 @@ import { spawnSync } from 'node:child_process';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
const CODE_NAVIGATION_SCRIPT_REFS = new Set([
|
|
4
4
|
'code/outline',
|
|
5
|
+
'code/dependency-graph',
|
|
6
|
+
'code/import-cycle',
|
|
5
7
|
'code/symbol-read',
|
|
6
8
|
'code/route-outline',
|
|
7
9
|
'code/export-diff',
|
|
8
10
|
'repo/related-files',
|
|
9
11
|
]);
|
|
10
12
|
const CONFIG_CHAIN_SURFACES = new Set(['config', 'package', 'source', 'test']);
|
|
11
|
-
const CONFIG_FILE_PATTERN = /(?:^|\/)(?:tsconfig(?:\..*)?\.json|eslint\.config\.[cm]?[jt]s|\.eslintrc(?:\.json)?|\.prettierrc(?:\.json)?|prettier\.config\.[cm]?[jt]s|vite\.config\.[cm]?[jt]s|vitest\.config\.[cm]?[jt]s|tailwind\.config\.[cm]?[jt]s|jest\.config\.[cm]?[jt]s|playwright\.config\.[cm]?[jt]s|astro\.config\.mjs|svelte\.config\.js)$/u;
|
|
13
|
+
const CONFIG_FILE_PATTERN = /(?:^|\/)(?:\.gitignore|\.env\.(?:example|sample|template|defaults)|\.dev\.vars\.example|tsconfig(?:\..*)?\.json|eslint\.config\.[cm]?[jt]s|\.eslintrc(?:\.json)?|\.prettierrc(?:\.json)?|prettier\.config\.[cm]?[jt]s|vite\.config\.[cm]?[jt]s|vitest\.config\.[cm]?[jt]s|tailwind\.config\.[cm]?[jt]s|jest\.config\.[cm]?[jt]s|playwright\.config\.[cm]?[jt]s|astro\.config\.mjs|svelte\.config\.js)$/u;
|
|
12
14
|
export function isScriptPackSuggestionPhase(value) {
|
|
13
15
|
return ['before_change', 'during_change', 'after_change', 'review'].includes(value);
|
|
14
16
|
}
|
|
@@ -121,7 +123,13 @@ function surfacesForScript(script) {
|
|
|
121
123
|
addIf('generated', /generated|protected|vendor|cache|boundary/u);
|
|
122
124
|
addIf('config', /config|command/u);
|
|
123
125
|
addIf('package', /package|release/u);
|
|
126
|
+
addIf('test', /test|suite|fixture|coverage|selection|timing|performance/u);
|
|
124
127
|
addIf('source', /code|source|symbol/u);
|
|
128
|
+
if (script.ref === 'repo/manifest-lock-drift') {
|
|
129
|
+
surfaces.add('config');
|
|
130
|
+
surfaces.add('generated');
|
|
131
|
+
surfaces.add('template');
|
|
132
|
+
}
|
|
125
133
|
return uniqueSortedSurfaces(surfaces);
|
|
126
134
|
}
|
|
127
135
|
function confidenceForScore(score) {
|
|
@@ -139,6 +147,10 @@ function pathsWithSurface(analyzedPaths, surface) {
|
|
|
139
147
|
function hasPathWithSurface(analyzedPaths, surface) {
|
|
140
148
|
return analyzedPaths.some((entry) => entry.surfaces.includes(surface));
|
|
141
149
|
}
|
|
150
|
+
function isGitIgnoreAuditPriorityPath(relativePath) {
|
|
151
|
+
const normalized = relativePath.replace(/\\/gu, '/').replace(/^\.\/+/u, '');
|
|
152
|
+
return normalized === '.gitignore' || normalized.endsWith('/.gitignore') || normalized === '.git/info/exclude';
|
|
153
|
+
}
|
|
142
154
|
function firstAvailablePath(analyzedPaths, preferredSurfaces) {
|
|
143
155
|
for (const surface of preferredSurfaces) {
|
|
144
156
|
const [candidate] = pathsWithSurface(analyzedPaths, surface);
|
|
@@ -166,6 +178,17 @@ function createRunHint(script, analyzedPaths) {
|
|
|
166
178
|
}
|
|
167
179
|
return 'After code/outline returns a source anchor, run: mf script-pack run code/symbol-read read --anchor <anchor-id> --json';
|
|
168
180
|
}
|
|
181
|
+
if (script.ref === 'code/dependency-graph') {
|
|
182
|
+
const sourcePaths = pathsWithSurface(analyzedPaths, 'source');
|
|
183
|
+
return createConcretePathHint('mf script-pack run code/dependency-graph scan', sourcePaths, script.usage);
|
|
184
|
+
}
|
|
185
|
+
if (script.ref === 'code/import-cycle') {
|
|
186
|
+
const sourcePaths = pathsWithSurface(analyzedPaths, 'source');
|
|
187
|
+
return createConcretePathHint('mf script-pack run code/import-cycle check', sourcePaths, script.usage);
|
|
188
|
+
}
|
|
189
|
+
if (script.ref === 'code/change-impact') {
|
|
190
|
+
return 'mf script-pack run code/change-impact analyze --base HEAD --json';
|
|
191
|
+
}
|
|
169
192
|
if (script.ref === 'code/route-outline') {
|
|
170
193
|
const sourcePaths = pathsWithSurface(analyzedPaths, 'source');
|
|
171
194
|
return createConcretePathHint('mf script-pack run code/route-outline scan', sourcePaths, script.usage);
|
|
@@ -191,15 +214,64 @@ function createRunHint(script, analyzedPaths) {
|
|
|
191
214
|
.map((entry) => entry.path);
|
|
192
215
|
return createConcretePathHint('mf script-pack run docs/reference-drift check', docsPaths, script.usage);
|
|
193
216
|
}
|
|
217
|
+
if (script.ref === 'docs/link-integrity') {
|
|
218
|
+
const docsPaths = analyzedPaths
|
|
219
|
+
.filter((entry) => entry.surfaces.some((surface) => surface === 'docs' || surface === 'schema'))
|
|
220
|
+
.map((entry) => entry.path);
|
|
221
|
+
return createConcretePathHint('mf script-pack run docs/link-integrity check', docsPaths, script.usage);
|
|
222
|
+
}
|
|
223
|
+
if (script.ref === 'test/performance-report') {
|
|
224
|
+
return 'mf script-pack run test/performance-report summarize --json';
|
|
225
|
+
}
|
|
226
|
+
if (script.ref === 'test/regression-selector') {
|
|
227
|
+
const testSelectionPaths = analyzedPaths
|
|
228
|
+
.filter((entry) => entry.surfaces.some((surface) => surface === 'source' || surface === 'test'))
|
|
229
|
+
.map((entry) => entry.path);
|
|
230
|
+
const pathPart = testSelectionPaths.length > 0 ? ` ${testSelectionPaths.map(quoteCliArg).join(' ')}` : '';
|
|
231
|
+
return `mf script-pack run test/regression-selector select${pathPart} --base HEAD --json`;
|
|
232
|
+
}
|
|
194
233
|
if (script.ref === 'repo/generated-boundary') {
|
|
195
234
|
return createConcretePathHint('mf script-pack run repo/generated-boundary check', analyzedPaths.map((entry) => entry.path), script.usage);
|
|
196
235
|
}
|
|
236
|
+
if (script.ref === 'repo/merge-conflict-scan') {
|
|
237
|
+
return createConcretePathHint('mf script-pack run repo/merge-conflict-scan check', analyzedPaths.map((entry) => entry.path), 'mf script-pack run repo/merge-conflict-scan check --json');
|
|
238
|
+
}
|
|
239
|
+
if (script.ref === 'repo/git-ignore-audit') {
|
|
240
|
+
return createConcretePathHint('mf script-pack run repo/git-ignore-audit audit', analyzedPaths.map((entry) => entry.path), 'mf script-pack run repo/git-ignore-audit audit --json');
|
|
241
|
+
}
|
|
242
|
+
if (script.ref === 'repo/manifest-lock-drift') {
|
|
243
|
+
const manifestPaths = analyzedPaths
|
|
244
|
+
.filter((entry) => entry.surfaces.some((surface) => surface === 'config' || surface === 'template' || surface === 'generated'))
|
|
245
|
+
.map((entry) => entry.path);
|
|
246
|
+
return createConcretePathHint('mf script-pack run repo/manifest-lock-drift check', manifestPaths, 'mf script-pack run repo/manifest-lock-drift check --json');
|
|
247
|
+
}
|
|
248
|
+
if (script.ref === 'repo/skill-route-audit') {
|
|
249
|
+
return 'mf script-pack run repo/skill-route-audit audit --json';
|
|
250
|
+
}
|
|
251
|
+
if (script.ref === 'repo/version-source') {
|
|
252
|
+
return 'mf script-pack run repo/version-source inspect --json';
|
|
253
|
+
}
|
|
254
|
+
if (script.ref === 'repo/approval-gate') {
|
|
255
|
+
return 'mf script-pack run repo/approval-gate check --action <action_type> --json';
|
|
256
|
+
}
|
|
197
257
|
if (script.ref === 'repo/config-chain') {
|
|
198
258
|
const configPaths = analyzedPaths
|
|
199
259
|
.filter((entry) => entry.surfaces.some((surface) => CONFIG_CHAIN_SURFACES.has(surface)))
|
|
200
260
|
.map((entry) => entry.path);
|
|
201
261
|
return createConcretePathHint('mf script-pack run repo/config-chain inspect', configPaths, script.usage);
|
|
202
262
|
}
|
|
263
|
+
if (script.ref === 'repo/env-contract') {
|
|
264
|
+
const envPaths = analyzedPaths
|
|
265
|
+
.filter((entry) => entry.surfaces.some((surface) => surface === 'config' || surface === 'source' || surface === 'docs' || surface === 'package'))
|
|
266
|
+
.map((entry) => entry.path);
|
|
267
|
+
return createConcretePathHint('mf script-pack run repo/env-contract scan', envPaths, script.usage);
|
|
268
|
+
}
|
|
269
|
+
if (script.ref === 'repo/secret-risk-scan') {
|
|
270
|
+
const secretRiskPaths = analyzedPaths
|
|
271
|
+
.filter((entry) => entry.surfaces.some((surface) => surface === 'config' || surface === 'source' || surface === 'docs' || surface === 'package' || surface === 'test'))
|
|
272
|
+
.map((entry) => entry.path);
|
|
273
|
+
return createConcretePathHint('mf script-pack run repo/secret-risk-scan scan', secretRiskPaths, script.usage);
|
|
274
|
+
}
|
|
203
275
|
if (script.ref === 'repo/related-files') {
|
|
204
276
|
const relatedPaths = analyzedPaths
|
|
205
277
|
.filter((entry) => entry.surfaces.some((surface) => surface === 'source' || surface === 'test'))
|
|
@@ -260,6 +332,30 @@ export function createScriptPackSuggestionReport(mustflowRoot, options) {
|
|
|
260
332
|
score += 2;
|
|
261
333
|
reasons.push('Prioritizes generated-boundary checks for generated paths.');
|
|
262
334
|
}
|
|
335
|
+
if (script.ref === 'repo/merge-conflict-scan' && requestedSurfaces.size > 0) {
|
|
336
|
+
score += 1;
|
|
337
|
+
reasons.push('Prioritizes merge-conflict marker scans for changed repository paths.');
|
|
338
|
+
}
|
|
339
|
+
if (script.ref === 'repo/git-ignore-audit' &&
|
|
340
|
+
analyzedPaths.some((entry) => isGitIgnoreAuditPriorityPath(entry.path))) {
|
|
341
|
+
score += 1;
|
|
342
|
+
reasons.push('Prioritizes Git ignore evidence for explicit ignore-control paths.');
|
|
343
|
+
}
|
|
344
|
+
if (script.ref === 'repo/skill-route-audit' &&
|
|
345
|
+
(requestedSurfaces.has('skill') || requestedSurfaces.has('template') || requestedSurfaces.has('config'))) {
|
|
346
|
+
score += 3;
|
|
347
|
+
reasons.push('Prioritizes skill-route audits for skill, template, and workflow metadata surfaces.');
|
|
348
|
+
}
|
|
349
|
+
if (script.ref === 'repo/version-source' &&
|
|
350
|
+
(requestedSurfaces.has('package') || requestedSurfaces.has('template') || requestedSurfaces.has('config'))) {
|
|
351
|
+
score += 2;
|
|
352
|
+
reasons.push('Prioritizes version-source inspection for package, template, and versioning metadata surfaces.');
|
|
353
|
+
}
|
|
354
|
+
if (script.ref === 'repo/approval-gate' &&
|
|
355
|
+
(requestedSurfaces.has('config') || requestedSurfaces.has('package') || requestedSurfaces.has('template'))) {
|
|
356
|
+
score += 2;
|
|
357
|
+
reasons.push('Prioritizes approval-gate checks for approval-sensitive workflow and release surfaces.');
|
|
358
|
+
}
|
|
263
359
|
if (score === 0) {
|
|
264
360
|
return null;
|
|
265
361
|
}
|