mustflow 2.103.3 → 2.103.10
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/dist/cli/commands/run.js +11 -0
- package/dist/cli/i18n/en.js +2 -0
- package/dist/cli/i18n/es.js +2 -0
- package/dist/cli/i18n/fr.js +2 -0
- package/dist/cli/i18n/hi.js +2 -0
- package/dist/cli/i18n/ko.js +2 -0
- package/dist/cli/i18n/zh.js +2 -0
- package/dist/cli/lib/external-skill-import.js +78 -14
- package/dist/cli/lib/local-index/sql.js +9 -1
- package/dist/cli/lib/run-plan.js +37 -0
- package/dist/core/change-impact.js +16 -0
- package/dist/core/code-outline.js +3 -13
- package/dist/core/config-chain.js +3 -13
- package/dist/core/dependency-graph.js +3 -13
- package/dist/core/docs-link-integrity.js +23 -4
- package/dist/core/env-contract.js +3 -13
- package/dist/core/export-diff.js +3 -3
- package/dist/core/ignored-directories.js +40 -0
- package/dist/core/reference-drift.js +4 -2
- package/dist/core/related-files.js +3 -13
- package/dist/core/repo-merge-conflict-scan.js +3 -9
- package/dist/core/route-outline.js +3 -13
- package/dist/core/script-pack-suggestions.js +23 -12
- package/dist/core/secret-risk-scan.js +3 -13
- package/dist/core/skill-route-resolution.js +21 -1
- package/package.json +2 -2
- package/schemas/link-integrity-report.schema.json +1 -0
- package/schemas/reference-drift-report.schema.json +1 -0
- package/templates/default/i18n.toml +19 -7
- package/templates/default/locales/en/.mustflow/skills/ai-generated-code-hardening/SKILL.md +30 -7
- package/templates/default/locales/en/.mustflow/skills/api-request-performance-review/SKILL.md +12 -6
- package/templates/default/locales/en/.mustflow/skills/completion-evidence-gate/SKILL.md +20 -9
- package/templates/default/locales/en/.mustflow/skills/hot-path-performance-review/SKILL.md +20 -15
- package/templates/default/locales/en/.mustflow/skills/next-action-menu/SKILL.md +22 -7
- package/templates/default/locales/en/.mustflow/skills/quadratic-scan-review/SKILL.md +21 -19
- package/templates/default/locales/en/.mustflow/skills/react-code-change/SKILL.md +54 -8
- package/templates/default/locales/en/.mustflow/skills/vertical-slice-tdd/SKILL.md +22 -8
- package/templates/default/manifest.toml +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { existsSync, lstatSync, readdirSync } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { DEFAULT_IGNORED_DIRECTORIES, isIgnoredDirectoryPath } from './ignored-directories.js';
|
|
4
5
|
import { ensureInside, ensureInsideWithoutSymlinks, readFileInsideWithoutSymlinks } from './safe-filesystem.js';
|
|
5
6
|
export const RELATED_FILES_PACK_ID = 'repo';
|
|
6
7
|
export const RELATED_FILES_SCRIPT_ID = 'related-files';
|
|
@@ -12,17 +13,7 @@ const MAX_ISSUES = 50;
|
|
|
12
13
|
const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs'];
|
|
13
14
|
const RESOLVE_EXTENSIONS = [...SOURCE_EXTENSIONS, '.json'];
|
|
14
15
|
const RELATED_EXTENSIONS = [...RESOLVE_EXTENSIONS, '.d.ts', '.md', '.mdx', '.css', '.scss', '.sass', '.less'];
|
|
15
|
-
const IGNORED_DIRECTORIES =
|
|
16
|
-
'.git',
|
|
17
|
-
'.mustflow/cache',
|
|
18
|
-
'.mustflow/state',
|
|
19
|
-
'node_modules',
|
|
20
|
-
'dist',
|
|
21
|
-
'build',
|
|
22
|
-
'coverage',
|
|
23
|
-
'.next',
|
|
24
|
-
'.turbo',
|
|
25
|
-
];
|
|
16
|
+
const IGNORED_DIRECTORIES = DEFAULT_IGNORED_DIRECTORIES;
|
|
26
17
|
const CONFIG_FILE_PATTERNS = [
|
|
27
18
|
/^package\.json$/u,
|
|
28
19
|
/^tsconfig(?:\.[^.]+)?\.json$/u,
|
|
@@ -71,8 +62,7 @@ function isSourceLanguage(language) {
|
|
|
71
62
|
return language !== 'json' && language !== 'other';
|
|
72
63
|
}
|
|
73
64
|
function isIgnoredDirectory(relativePath) {
|
|
74
|
-
|
|
75
|
-
return IGNORED_DIRECTORIES.some((directory) => normalized === directory || normalized.startsWith(`${directory}/`));
|
|
65
|
+
return isIgnoredDirectoryPath(normalizeRelativePath(relativePath), IGNORED_DIRECTORIES);
|
|
76
66
|
}
|
|
77
67
|
function makeFinding(code, severity, pathValue, message) {
|
|
78
68
|
return { code, severity, path: pathValue, message };
|
|
@@ -2,6 +2,7 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { spawnSync } from 'node:child_process';
|
|
3
3
|
import { existsSync, lstatSync, readdirSync } from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { DEFAULT_IGNORED_DIRECTORIES, isIgnoredDirectoryPath } from './ignored-directories.js';
|
|
5
6
|
import { ensureInsideWithoutSymlinks, readUtf8FileInsideWithoutSymlinks } from './safe-filesystem.js';
|
|
6
7
|
export const REPO_MERGE_CONFLICT_SCAN_PACK_ID = 'repo';
|
|
7
8
|
export const REPO_MERGE_CONFLICT_SCAN_SCRIPT_ID = 'merge-conflict-scan';
|
|
@@ -15,15 +16,9 @@ const MARKER_PATTERNS = [
|
|
|
15
16
|
{ prefix: '>>>>>>>', marker: 'end' },
|
|
16
17
|
];
|
|
17
18
|
const SKIPPED_DIRECTORY_NAMES = new Set([
|
|
18
|
-
|
|
19
|
-
'node_modules',
|
|
19
|
+
...DEFAULT_IGNORED_DIRECTORIES,
|
|
20
20
|
'vendor',
|
|
21
21
|
'third_party',
|
|
22
|
-
'dist',
|
|
23
|
-
'build',
|
|
24
|
-
'coverage',
|
|
25
|
-
'.mustflow/cache',
|
|
26
|
-
'.mustflow/state',
|
|
27
22
|
]);
|
|
28
23
|
function normalizeRelativePath(value) {
|
|
29
24
|
return value.replace(/\\/gu, '/').replace(/^\.\/+/u, '').replace(/\/+$/u, '') || '.';
|
|
@@ -95,8 +90,7 @@ function collectGitChangedFiles(root, issues, findings) {
|
|
|
95
90
|
}
|
|
96
91
|
function shouldSkipDirectory(relativePath) {
|
|
97
92
|
const normalized = normalizeRelativePath(relativePath);
|
|
98
|
-
|
|
99
|
-
return SKIPPED_DIRECTORY_NAMES.has(normalized) || SKIPPED_DIRECTORY_NAMES.has(firstSegment);
|
|
93
|
+
return isIgnoredDirectoryPath(normalized, [...SKIPPED_DIRECTORY_NAMES]);
|
|
100
94
|
}
|
|
101
95
|
function isLikelyTextFile(relativePath) {
|
|
102
96
|
const extension = path.posix.extname(relativePath).toLowerCase();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { lstatSync, readdirSync } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { DEFAULT_IGNORED_DIRECTORIES, isIgnoredDirectoryPath } from './ignored-directories.js';
|
|
4
5
|
import { ensureInside, ensureInsideWithoutSymlinks, readFileInsideWithoutSymlinks } from './safe-filesystem.js';
|
|
5
6
|
export const CODE_ROUTE_OUTLINE_SCRIPT_ID = 'route-outline';
|
|
6
7
|
export const CODE_ROUTE_OUTLINE_SCRIPT_REF = `code/${CODE_ROUTE_OUTLINE_SCRIPT_ID}`;
|
|
@@ -39,17 +40,7 @@ const LIFECYCLE_METHODS = [
|
|
|
39
40
|
'onAfterHandle',
|
|
40
41
|
'onError',
|
|
41
42
|
];
|
|
42
|
-
const IGNORED_DIRECTORIES =
|
|
43
|
-
'.git',
|
|
44
|
-
'.mustflow/cache',
|
|
45
|
-
'.mustflow/state',
|
|
46
|
-
'node_modules',
|
|
47
|
-
'dist',
|
|
48
|
-
'build',
|
|
49
|
-
'coverage',
|
|
50
|
-
'.next',
|
|
51
|
-
'.turbo',
|
|
52
|
-
];
|
|
43
|
+
const IGNORED_DIRECTORIES = DEFAULT_IGNORED_DIRECTORIES;
|
|
53
44
|
const ERROR_CODES = new Set([
|
|
54
45
|
'code_route_outline_path_outside_root',
|
|
55
46
|
'code_route_outline_unreadable_path',
|
|
@@ -85,8 +76,7 @@ function languageForPath(filePath) {
|
|
|
85
76
|
}
|
|
86
77
|
}
|
|
87
78
|
function isIgnoredDirectory(relativePath) {
|
|
88
|
-
|
|
89
|
-
return IGNORED_DIRECTORIES.some((directory) => normalized === directory || normalized.startsWith(`${directory}/`));
|
|
79
|
+
return isIgnoredDirectoryPath(normalizeRelativePath(relativePath), IGNORED_DIRECTORIES);
|
|
90
80
|
}
|
|
91
81
|
function makeFinding(code, severity, pathValue, message) {
|
|
92
82
|
return { code, severity, path: pathValue, message };
|
|
@@ -80,26 +80,37 @@ export function classifyScriptPackPathSurface(relativePath) {
|
|
|
80
80
|
return surfaces.length > 0 ? uniqueSortedSurfaces(surfaces) : ['unknown'];
|
|
81
81
|
}
|
|
82
82
|
function readChangedPaths(mustflowRoot, issues) {
|
|
83
|
-
const result = spawnSync('git', ['status', '--
|
|
83
|
+
const result = spawnSync('git', ['status', '--porcelain=v1', '-z', '--untracked-files=all'], {
|
|
84
84
|
cwd: mustflowRoot,
|
|
85
85
|
encoding: 'utf8',
|
|
86
86
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
87
87
|
windowsHide: true,
|
|
88
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
88
89
|
});
|
|
89
|
-
if (result.status !== 0) {
|
|
90
|
-
const detail = result.stderr.trim() || result.stdout.trim() || `git status exited with ${result.status}
|
|
90
|
+
if (result.error || result.status !== 0) {
|
|
91
|
+
const detail = result.error?.message ?? (result.stderr.trim() || result.stdout.trim() || `git status exited with ${result.status}`);
|
|
91
92
|
issues.push(`Could not read changed paths: ${detail}`);
|
|
92
93
|
return [];
|
|
93
94
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
95
|
+
const paths = [];
|
|
96
|
+
const records = result.stdout.split('\0');
|
|
97
|
+
let index = 0;
|
|
98
|
+
while (index < records.length) {
|
|
99
|
+
const record = records[index] ?? '';
|
|
100
|
+
index += 1;
|
|
101
|
+
if (record.length === 0) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const status = record.slice(0, 2);
|
|
105
|
+
const relativePath = record.slice(3);
|
|
106
|
+
if (relativePath.length > 0) {
|
|
107
|
+
paths.push(relativePath);
|
|
108
|
+
}
|
|
109
|
+
if (status.includes('R') || status.includes('C')) {
|
|
110
|
+
index += 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return paths;
|
|
103
114
|
}
|
|
104
115
|
function surfacesForScript(script) {
|
|
105
116
|
const surfaces = new Set();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { existsSync, lstatSync, readdirSync } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { DEFAULT_IGNORED_DIRECTORIES, isIgnoredDirectoryPath } from './ignored-directories.js';
|
|
4
5
|
import { ensureInside, ensureInsideWithoutSymlinks, readFileInsideWithoutSymlinks } from './safe-filesystem.js';
|
|
5
6
|
export const SECRET_RISK_SCAN_PACK_ID = 'repo';
|
|
6
7
|
export const SECRET_RISK_SCAN_SCRIPT_ID = 'secret-risk-scan';
|
|
@@ -35,17 +36,7 @@ const ENV_EXAMPLE_NAMES = [
|
|
|
35
36
|
'.env.local.example',
|
|
36
37
|
'.dev.vars.example',
|
|
37
38
|
];
|
|
38
|
-
const IGNORED_DIRECTORIES =
|
|
39
|
-
'.git',
|
|
40
|
-
'.mustflow/cache',
|
|
41
|
-
'.mustflow/state',
|
|
42
|
-
'node_modules',
|
|
43
|
-
'dist',
|
|
44
|
-
'build',
|
|
45
|
-
'coverage',
|
|
46
|
-
'.next',
|
|
47
|
-
'.turbo',
|
|
48
|
-
];
|
|
39
|
+
const IGNORED_DIRECTORIES = DEFAULT_IGNORED_DIRECTORIES;
|
|
49
40
|
const ERROR_CODES = new Set([
|
|
50
41
|
'secret_risk_path_outside_root',
|
|
51
42
|
'secret_risk_unreadable_path',
|
|
@@ -68,8 +59,7 @@ function makeFinding(code, severity, pathValue, message, details = {}) {
|
|
|
68
59
|
return { code, severity, path: pathValue, message, ...details };
|
|
69
60
|
}
|
|
70
61
|
function isIgnoredDirectory(relativePath) {
|
|
71
|
-
|
|
72
|
-
return IGNORED_DIRECTORIES.some((directory) => normalized === directory || normalized.startsWith(`${directory}/`));
|
|
62
|
+
return isIgnoredDirectoryPath(normalizeRelativePath(relativePath), IGNORED_DIRECTORIES);
|
|
73
63
|
}
|
|
74
64
|
function isSecretFile(relativePath) {
|
|
75
65
|
return SECRET_FILE_NAMES.includes(path.basename(relativePath).toLowerCase());
|
|
@@ -8,6 +8,7 @@ const SKILL_ROUTER_PATH = '.mustflow/skills/router.toml';
|
|
|
8
8
|
const SKILL_ROUTES_METADATA_PATH = '.mustflow/skills/routes.toml';
|
|
9
9
|
const SKILL_FRONTMATTER_SOURCE = '.mustflow/skills/*/SKILL.md';
|
|
10
10
|
const EXTERNAL_SKILL_FRONTMATTER_SOURCE = '.mustflow/external-skills/*/SKILL.md';
|
|
11
|
+
const EXTERNAL_SKILL_PROVENANCE_FILE = 'mustflow-skill-source.json';
|
|
11
12
|
const DEFAULT_MAX_CANDIDATES = 5;
|
|
12
13
|
const DEFAULT_MAX_MAIN = 1;
|
|
13
14
|
const DEFAULT_MAX_ADJUNCTS = 2;
|
|
@@ -214,6 +215,25 @@ function readSkillFrontmatterRoutes(projectRoot) {
|
|
|
214
215
|
}
|
|
215
216
|
return routes;
|
|
216
217
|
}
|
|
218
|
+
function hasValidExternalSkillProvenance(projectRoot, skillDirectory) {
|
|
219
|
+
const provenancePath = path.join(projectRoot, '.mustflow', 'external-skills', skillDirectory, EXTERNAL_SKILL_PROVENANCE_FILE);
|
|
220
|
+
if (!existsSync(provenancePath)) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
const content = readUtf8FileInsideWithoutSymlinks(projectRoot, provenancePath, {
|
|
225
|
+
maxBytes: MUSTFLOW_TEXT_MAX_BYTES,
|
|
226
|
+
});
|
|
227
|
+
const parsed = JSON.parse(content);
|
|
228
|
+
return (isRecord(parsed) &&
|
|
229
|
+
parsed.schema_version === '1' &&
|
|
230
|
+
parsed.kind === 'external_skill_source' &&
|
|
231
|
+
isRecord(parsed.source));
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
217
237
|
function readExternalSkillFrontmatterRoutes(projectRoot) {
|
|
218
238
|
const skillRoot = path.join(projectRoot, '.mustflow', 'external-skills');
|
|
219
239
|
if (!existsSync(skillRoot)) {
|
|
@@ -227,7 +247,7 @@ function readExternalSkillFrontmatterRoutes(projectRoot) {
|
|
|
227
247
|
for (const skillDirectory of skillDirectories) {
|
|
228
248
|
const skillPath = `.mustflow/external-skills/${skillDirectory}/SKILL.md`;
|
|
229
249
|
const absoluteSkillPath = path.join(projectRoot, ...skillPath.split('/'));
|
|
230
|
-
if (!existsSync(absoluteSkillPath)) {
|
|
250
|
+
if (!existsSync(absoluteSkillPath) || !hasValidExternalSkillProvenance(projectRoot, skillDirectory)) {
|
|
231
251
|
continue;
|
|
232
252
|
}
|
|
233
253
|
const content = readUtf8FileInsideWithoutSymlinks(projectRoot, absoluteSkillPath, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mustflow",
|
|
3
|
-
"version": "2.103.
|
|
3
|
+
"version": "2.103.10",
|
|
4
4
|
"description": "Agent workflow documents and CLI for mustflow repository roots.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT-0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"check:package": "node -e \"const fs=require('fs'); JSON.parse(fs.readFileSync('package.json','utf8')); console.log('package.json ok')\"",
|
|
48
48
|
"check:typecheck": "tsc -p tsconfig.json --noEmit",
|
|
49
49
|
"prepack": "npm run build",
|
|
50
|
-
"check:pack": "npm pack --dry-run --json",
|
|
50
|
+
"check:pack": "npm pack --dry-run --json --ignore-scripts",
|
|
51
51
|
"check:install": "npm run check:pack && node --test tests/integration/*.test.js",
|
|
52
52
|
"release:check": "npm run check && npm run docs:check && npm run check:install",
|
|
53
53
|
"prepublishOnly": "npm run release:check",
|
|
@@ -86,6 +86,7 @@
|
|
|
86
86
|
"max_file_bytes": { "type": "integer", "minimum": 1 },
|
|
87
87
|
"default_paths": { "$ref": "#/$defs/stringArray" },
|
|
88
88
|
"path_filters": { "$ref": "#/$defs/stringArray" },
|
|
89
|
+
"ignored_directories": { "$ref": "#/$defs/stringArray" },
|
|
89
90
|
"checked_link_kinds": {
|
|
90
91
|
"type": "array",
|
|
91
92
|
"items": { "$ref": "#/$defs/linkKind" }
|
|
@@ -86,6 +86,7 @@
|
|
|
86
86
|
"max_file_bytes": { "type": "integer", "minimum": 1 },
|
|
87
87
|
"default_paths": { "$ref": "#/$defs/stringArray" },
|
|
88
88
|
"path_filters": { "$ref": "#/$defs/stringArray" },
|
|
89
|
+
"ignored_directories": { "$ref": "#/$defs/stringArray" },
|
|
89
90
|
"checked_reference_kinds": {
|
|
90
91
|
"type": "array",
|
|
91
92
|
"items": { "$ref": "#/$defs/referenceKind" }
|
|
@@ -116,7 +116,7 @@ translations = {}
|
|
|
116
116
|
[documents."skill.ai-generated-code-hardening"]
|
|
117
117
|
source = "locales/en/.mustflow/skills/ai-generated-code-hardening/SKILL.md"
|
|
118
118
|
source_locale = "en"
|
|
119
|
-
revision =
|
|
119
|
+
revision = 3
|
|
120
120
|
translations = {}
|
|
121
121
|
|
|
122
122
|
[documents."skill.quality-gaming-guard"]
|
|
@@ -194,13 +194,13 @@ translations = {}
|
|
|
194
194
|
[documents."skill.hot-path-performance-review"]
|
|
195
195
|
source = "locales/en/.mustflow/skills/hot-path-performance-review/SKILL.md"
|
|
196
196
|
source_locale = "en"
|
|
197
|
-
revision =
|
|
197
|
+
revision = 2
|
|
198
198
|
translations = {}
|
|
199
199
|
|
|
200
200
|
[documents."skill.api-request-performance-review"]
|
|
201
201
|
source = "locales/en/.mustflow/skills/api-request-performance-review/SKILL.md"
|
|
202
202
|
source_locale = "en"
|
|
203
|
-
revision =
|
|
203
|
+
revision = 2
|
|
204
204
|
translations = {}
|
|
205
205
|
|
|
206
206
|
[documents."skill.api-failure-triage"]
|
|
@@ -326,7 +326,7 @@ translations = {}
|
|
|
326
326
|
[documents."skill.quadratic-scan-review"]
|
|
327
327
|
source = "locales/en/.mustflow/skills/quadratic-scan-review/SKILL.md"
|
|
328
328
|
source_locale = "en"
|
|
329
|
-
revision =
|
|
329
|
+
revision = 2
|
|
330
330
|
translations = {}
|
|
331
331
|
|
|
332
332
|
[documents."skill.type-state-modeling-review"]
|
|
@@ -568,6 +568,12 @@ source_locale = "en"
|
|
|
568
568
|
revision = 1
|
|
569
569
|
translations = {}
|
|
570
570
|
|
|
571
|
+
[documents."skill.idea-triage"]
|
|
572
|
+
source = "locales/en/.mustflow/skills/idea-triage/SKILL.md"
|
|
573
|
+
source_locale = "en"
|
|
574
|
+
revision = 1
|
|
575
|
+
translations = {}
|
|
576
|
+
|
|
571
577
|
[documents."skill.astro-code-change"]
|
|
572
578
|
source = "locales/en/.mustflow/skills/astro-code-change/SKILL.md"
|
|
573
579
|
source_locale = "en"
|
|
@@ -673,7 +679,7 @@ translations = {}
|
|
|
673
679
|
[documents."skill.react-code-change"]
|
|
674
680
|
source = "locales/en/.mustflow/skills/react-code-change/SKILL.md"
|
|
675
681
|
source_locale = "en"
|
|
676
|
-
revision =
|
|
682
|
+
revision = 2
|
|
677
683
|
translations = {}
|
|
678
684
|
|
|
679
685
|
[documents."skill.python-code-change"]
|
|
@@ -769,7 +775,13 @@ translations = {}
|
|
|
769
775
|
[documents."skill.completion-evidence-gate"]
|
|
770
776
|
source = "locales/en/.mustflow/skills/completion-evidence-gate/SKILL.md"
|
|
771
777
|
source_locale = "en"
|
|
772
|
-
revision =
|
|
778
|
+
revision = 5
|
|
779
|
+
translations = {}
|
|
780
|
+
|
|
781
|
+
[documents."skill.next-action-menu"]
|
|
782
|
+
source = "locales/en/.mustflow/skills/next-action-menu/SKILL.md"
|
|
783
|
+
source_locale = "en"
|
|
784
|
+
revision = 3
|
|
773
785
|
translations = {}
|
|
774
786
|
|
|
775
787
|
[documents."skill.evidence-stall-breaker"]
|
|
@@ -1080,7 +1092,7 @@ translations = {}
|
|
|
1080
1092
|
[documents."skill.vertical-slice-tdd"]
|
|
1081
1093
|
source = "locales/en/.mustflow/skills/vertical-slice-tdd/SKILL.md"
|
|
1082
1094
|
source_locale = "en"
|
|
1083
|
-
revision =
|
|
1095
|
+
revision = 2
|
|
1084
1096
|
translations = {}
|
|
1085
1097
|
|
|
1086
1098
|
[documents."skill.llm-service-ux-review"]
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
mustflow_doc: skill.ai-generated-code-hardening
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 3
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: ai-generated-code-hardening
|
|
9
|
-
description: Apply this skill when AI-generated, assistant-authored, vibe-coded, or broad code changes need evidence-backed hardening against symptom-only fixes, pinpoint hardcoding, duplicate helpers or shapes, hidden coupling, weak tests, swallowed errors, excessive complexity, and boundary drift.
|
|
9
|
+
description: Apply this skill when AI-generated, assistant-authored, vibe-coded, or broad code changes need evidence-backed hardening against symptom-only fixes, pinpoint hardcoding, duplicate helpers or shapes, hidden coupling, fake small-sample performance confidence, weak tests, swallowed errors, excessive complexity, and boundary drift.
|
|
10
10
|
metadata:
|
|
11
11
|
mustflow_schema: "1"
|
|
12
12
|
mustflow_kind: procedure
|
|
@@ -33,8 +33,8 @@ Use this skill to turn agent-written code from "looks plausible" into maintainab
|
|
|
33
33
|
repository code. The goal is not style cleanup. The goal is to catch the failure
|
|
34
34
|
modes that appear when an agent forgets the repository between sessions: symptom-only
|
|
35
35
|
patches, pinpoint hardcoding, duplicate helpers, duplicate shapes, hidden coupling,
|
|
36
|
-
|
|
37
|
-
files.
|
|
36
|
+
fake confidence from tiny fixtures, hidden repeated work, weak tests, swallowed errors,
|
|
37
|
+
accidental public surfaces, and oversized functions or files.
|
|
38
38
|
|
|
39
39
|
<!-- mustflow-section: use-when -->
|
|
40
40
|
## Use When
|
|
@@ -51,6 +51,9 @@ files.
|
|
|
51
51
|
re-export drift.
|
|
52
52
|
- Tests were added or changed and may only check strings, function names, snapshots,
|
|
53
53
|
mocks, or implementation details instead of observable behavior.
|
|
54
|
+
- The code looks clean on sample data but may hide repeated scans, repeated copying,
|
|
55
|
+
repeated I/O, unbounded fan-out, allocation churn, or response-size growth under
|
|
56
|
+
realistic data.
|
|
54
57
|
- Error handling, fallback paths, defensive guards, or default values were added in
|
|
55
58
|
multiple callers instead of one boundary.
|
|
56
59
|
- New or changed functions/files are becoming hard to review because of excessive
|
|
@@ -189,7 +192,23 @@ files.
|
|
|
189
192
|
- Split a god file only when the new module has a stable owner, direction, and
|
|
190
193
|
verification path.
|
|
191
194
|
|
|
192
|
-
8.
|
|
195
|
+
8. Check small-sample performance traps.
|
|
196
|
+
- Treat fixture-sized success as weak evidence when the path handles users,
|
|
197
|
+
orders, comments, logs, rows, files, permissions, relations, or rendered list
|
|
198
|
+
items that can grow.
|
|
199
|
+
- Search AI-authored code for `map`, `filter`, `find`, `findIndex`, `includes`,
|
|
200
|
+
`indexOf`, `reduce`, `sort`, `slice`, `splice`, `shift`, spread accumulation,
|
|
201
|
+
`concat`, `cloneDeep`, `JSON.stringify`, `parse`, `validate`, `sanitize`,
|
|
202
|
+
`normalize`, and helper names such as `isAllowed`, `canAccess`, `resolve`,
|
|
203
|
+
`build`, or `format` in repeated paths.
|
|
204
|
+
- Escalate concrete hidden O(N^2), allocation churn, or request fan-out evidence
|
|
205
|
+
to `quadratic-scan-review`, `hot-path-performance-review`, or
|
|
206
|
+
`api-request-performance-review` instead of burying it as style feedback.
|
|
207
|
+
- Do not claim a performance improvement from static review alone. Mark it as
|
|
208
|
+
static complexity risk unless configured tests, query counts, traces, profiles,
|
|
209
|
+
or benchmarks support the claim.
|
|
210
|
+
|
|
211
|
+
9. Harden tests against fake confidence.
|
|
193
212
|
- Verify behavior and side effects, not only function names, strings, snapshots,
|
|
194
213
|
or the presence of files.
|
|
195
214
|
- For bug fixes, add at least one nearby negative or sibling case when feasible so
|
|
@@ -203,7 +222,7 @@ files.
|
|
|
203
222
|
- If production code gained defensive fallback only to satisfy a brittle test,
|
|
204
223
|
fix the test or move the fallback to the owning boundary.
|
|
205
224
|
|
|
206
|
-
|
|
225
|
+
10. Use enforcement evidence without inventing enforcement.
|
|
207
226
|
- Run existing configured lint, build, and related test intents when they cover
|
|
208
227
|
the risk.
|
|
209
228
|
- If the repository lacks dependency-boundary, complexity, max-depth,
|
|
@@ -212,7 +231,7 @@ files.
|
|
|
212
231
|
- Never paste outside plugin commands, package-manager commands, or CI recipes
|
|
213
232
|
into mustflow command contracts without command-contract review.
|
|
214
233
|
|
|
215
|
-
|
|
234
|
+
11. Decide fix now, defer, or report.
|
|
216
235
|
- Fix now when the issue is in the touched code, small, directly tied to the
|
|
217
236
|
current behavior, and verifiable with configured commands.
|
|
218
237
|
- Defer when the issue needs broad architecture work, new dependencies, new CI
|
|
@@ -235,6 +254,8 @@ files.
|
|
|
235
254
|
duplicated guard/fallback risk is documented.
|
|
236
255
|
- Tests exercise behavior and meaningful side effects, with edge and failure paths
|
|
237
256
|
covered where relevant to the change.
|
|
257
|
+
- Sample-data performance confidence has been checked against realistic data-growth,
|
|
258
|
+
repeated-work, allocation, and I/O fan-out risks where relevant.
|
|
238
259
|
|
|
239
260
|
<!-- mustflow-section: verification -->
|
|
240
261
|
## Verification
|
|
@@ -281,5 +302,7 @@ Include:
|
|
|
281
302
|
found or ruled out.
|
|
282
303
|
- Error-handling and fallback decisions.
|
|
283
304
|
- Test hardening: behavior assertions, side effects, edge cases, and mock boundary.
|
|
305
|
+
- Small-sample performance traps: hidden repeated scans, copy churn, repeated I/O,
|
|
306
|
+
unbounded fan-out, or response growth fixed, escalated, or reported.
|
|
284
307
|
- Configured verification intents run and their result.
|
|
285
308
|
- Deferred enforcement, lint, or CI guard suggestions, clearly marked as not added.
|
package/templates/default/locales/en/.mustflow/skills/api-request-performance-review/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
mustflow_doc: skill.api-request-performance-review
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 2
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: api-request-performance-review
|
|
@@ -58,8 +58,8 @@ The core question is: "For one request, how many times do we repeat the same I/O
|
|
|
58
58
|
- Request path: endpoint, route, handler, controller, resolver, serializer, mapper, middleware, service method, response builder, and downstream calls under review.
|
|
59
59
|
- Request cost ledger inputs: route span, DB query count, Redis call count, external API call count, filesystem or object-storage calls, payload size, response bytes, JSON serialization time, DTO mapping time, cache hit or miss, queue time, pool acquire wait, transaction duration, lock wait, and request-path CPU work when available.
|
|
60
60
|
- Data shape: request parameters, page size, relation counts, tenant or user scope, expected result size, maximum payload, large JSON/TEXT/BLOB fields, and response projection.
|
|
61
|
-
- ORM behavior: lazy loading, eager loading, generated SQL, relation access in serializers or templates, Django `select_related` and `prefetch_related`, Rails `includes`, `preload`, `eager_load`, and `strict_loading`, or equivalent framework behavior.
|
|
62
|
-
- Database evidence when available: `SELECT *`, app-side filtering or sorting, deep `OFFSET`, `COUNT(*)`, index fit for `WHERE` plus `ORDER BY` plus `LIMIT`, `EXPLAIN`, estimated rows, actual rows, join cardinality, and selectivity.
|
|
61
|
+
- ORM behavior: lazy loading, eager loading, generated SQL, relation access in serializers or templates, `include` versus explicit `select`, relation load strategy, Django `select_related` and `prefetch_related`, Rails `includes`, `preload`, `eager_load`, and `strict_loading`, or equivalent framework behavior.
|
|
62
|
+
- Database evidence when available: actual SQL, query count, repeated `SELECT ... WHERE id = ?`, `SELECT *`, app-side filtering or sorting, deep `OFFSET`, `COUNT(*)`, index fit for `WHERE` plus `ORDER BY` plus `LIMIT`, `EXPLAIN`, scan type, sort method, estimated rows, actual rows, join cardinality, and selectivity.
|
|
63
63
|
- Cache and Redis evidence: request-scope cache, key dimensions, cache miss path, `MGET`, pipeline behavior, Redis round trips, Redis Slow Log limitations, hot keys, fallback behavior, and stampede controls.
|
|
64
64
|
- Correctness boundaries: authorization, tenant isolation, ordering, duplicates, pagination stability, consistency, idempotency, timeout, cancellation, partial failure, stale data, and response contract.
|
|
65
65
|
- Relevant command-intent contract entries for build, tests, docs, release checks, and mustflow validation.
|
|
@@ -98,6 +98,8 @@ The core question is: "For one request, how many times do we repeat the same I/O
|
|
|
98
98
|
- In Django, choose `select_related` for single-valued relations and `prefetch_related` for multi-valued relations when the route actually needs them.
|
|
99
99
|
- In Rails, compare `includes`, `preload`, `eager_load`, and `strict_loading`; use strict loading or query-count tests where local patterns support them.
|
|
100
100
|
- Treat eager loading too much as a separate bug. It can replace N+1 with row explosion, duplicate parents, memory bloat, or huge response mapping.
|
|
101
|
+
- For Prisma-style APIs, do not trust `include` as a performance proof. Compare actual SQL, query count, selected columns, relation load strategy, and response shape.
|
|
102
|
+
- Treat repeated `count`, `exists`, `sum`, `latest`, or `first` queries in list serialization as N+1 candidates; prefer grouped aggregation, batched lookup, or database-side projection when semantics match.
|
|
101
103
|
5. Check query projection and response projection together.
|
|
102
104
|
- Flag `SELECT *`, full entity hydration, unbounded DTOs, and list endpoints that fetch large JSON, TEXT, BLOB, image, metadata, audit, or internal columns.
|
|
103
105
|
- Fetch detail fields only after narrowing the row set when the route returns a list, feed, search result, or admin table.
|
|
@@ -111,7 +113,10 @@ The core question is: "For one request, how many times do we repeat the same I/O
|
|
|
111
113
|
- Expensive `COUNT(*)` for every request needs a product reason, approximate or cached count policy, or deferred count behavior.
|
|
112
114
|
8. Match indexes to the whole request query.
|
|
113
115
|
- Check `WHERE`, `ORDER BY`, and `LIMIT` together instead of asking only whether one predicate has an index.
|
|
114
|
-
-
|
|
116
|
+
- Prefer query-shaped index review over column-name index decoration: composite indexes often need equality predicates first, range or ordering columns next, and stable tie-breakers for pagination.
|
|
117
|
+
- Functions around columns, implicit casts, `LOWER(email)`, `DATE(created_at)`, timezone conversion, `%keyword%`, low-selectivity predicates, and mismatched sort order can defeat useful index access. Expression indexes, range predicates, or search-specific indexes may be needed when the database owns that capability.
|
|
118
|
+
- For soft-delete, tenant, status, or visibility predicates that appear on nearly every request, review partial or filtered indexes where the database supports them.
|
|
119
|
+
- For list projections, check whether a covering or index-only access path is possible before fetching large JSON, TEXT, BLOB, HTML, metadata, or audit columns.
|
|
115
120
|
- When plan evidence exists, compare `EXPLAIN` estimated rows with actual rows, join cardinality, loops, rows examined, rows returned, buffers, temp files, sort method, and lock or pool wait.
|
|
116
121
|
9. Keep external calls out of transactions.
|
|
117
122
|
- Do not hold a DB transaction while waiting for an external API, file upload, object storage, Redis fallback, image processing, logging sink, or user-controlled operation.
|
|
@@ -140,13 +145,14 @@ The core question is: "For one request, how many times do we repeat the same I/O
|
|
|
140
145
|
17. Label evidence honestly.
|
|
141
146
|
- Static review can identify likely API latency risks but cannot prove speedup.
|
|
142
147
|
- A trace from a tiny fixture, warm local cache, or empty database is not representative production evidence.
|
|
148
|
+
- If actual SQL, query-count, or query-plan evidence is missing, say so instead of treating tidy ORM code as proof of efficient database behavior.
|
|
143
149
|
|
|
144
150
|
<!-- mustflow-section: postconditions -->
|
|
145
151
|
## Postconditions
|
|
146
152
|
|
|
147
153
|
- The API request boundary and Request cost ledger are explicit.
|
|
148
154
|
- DB query count, Redis call count, external API call count, cache hit or miss behavior, response bytes, serialization cost, transaction scope, pool acquire wait, and request-path CPU work are fixed, bounded, instrumented, or reported.
|
|
149
|
-
- ORM lazy loading, eager-loading overfetch, `SELECT *`, app-side filtering or sorting, deep `OFFSET`, expensive `COUNT(*)`, index mismatch, external call inside transaction, Redis loop, and cache miss amplification are checked where relevant.
|
|
155
|
+
- ORM lazy loading, eager-loading overfetch, repeated count or aggregate queries, actual SQL and query count, `SELECT *`, app-side filtering or sorting, deep `OFFSET`, expensive `COUNT(*)`, index mismatch, composite/partial/expression/covering index fit, external call inside transaction, Redis loop, and cache miss amplification are checked where relevant.
|
|
150
156
|
- Correctness, authorization, tenant isolation, idempotency, ordering, pagination stability, partial failure, cancellation, timeout, and stale-data behavior remain intact or are reported as tradeoffs.
|
|
151
157
|
- API performance claims are backed by configured evidence, trace evidence, plan evidence, or labeled as static review risk.
|
|
152
158
|
|
|
@@ -181,7 +187,7 @@ Use the narrowest configured test, build, docs, release, or mustflow intent that
|
|
|
181
187
|
|
|
182
188
|
- API request path reviewed
|
|
183
189
|
- Request cost ledger: route span, DB query count, Redis count, external API calls, filesystem or object-storage calls, payload size, response bytes, JSON serialization time, DTO mapping time, cache hit or miss, queue time, pool acquire wait, transaction duration, lock wait, and request-path CPU work
|
|
184
|
-
- ORM lazy loading, eager loading, projection, pagination, count, index fit, app-side filtering or sorting, transaction, pool, Redis, cache miss, serialization, response size, CPU-heavy request work, and observability findings
|
|
190
|
+
- ORM lazy loading, eager loading, actual SQL, query count, projection, pagination, count, index fit, app-side filtering or sorting, transaction, pool, Redis, cache miss, serialization, response size, CPU-heavy request work, and observability findings
|
|
185
191
|
- API request performance change made or recommended
|
|
186
192
|
- Evidence level: measured trace, configured-test evidence, plan evidence, static review risk, manual-only, missing, or not applicable
|
|
187
193
|
- Command intents run
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
mustflow_doc: skill.completion-evidence-gate
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 5
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: completion-evidence-gate
|
|
@@ -43,6 +43,8 @@ missing, blocked, failed, stale, or only partially relevant.
|
|
|
43
43
|
|
|
44
44
|
- A task is ready for final reporting after files were created, modified, deleted, or intentionally left unchanged.
|
|
45
45
|
- The user asks whether work is complete, safe to merge, ready to commit, verified, released, installed, or done.
|
|
46
|
+
- A non-trivial task, commit, push, release preparation, deploy preparation, verification run, or
|
|
47
|
+
paused implementation is being reported and at least one concrete next action remains.
|
|
46
48
|
- A change touched more than one surface, such as source, tests, schemas, templates, workflow files, package metadata, documentation, or generated output.
|
|
47
49
|
- Verification was skipped, failed, manual-only, unavailable, or chosen from multiple plausible command intents.
|
|
48
50
|
- A previous verification failure, repeated-failure warning, write-drift risk, scope-drift risk, or external evidence risk could make a completion claim misleading.
|
|
@@ -70,8 +72,9 @@ missing, blocked, failed, stale, or only partially relevant.
|
|
|
70
72
|
- Optional script-pack discovery evidence when the command contract exposes `script_pack_list`.
|
|
71
73
|
- Synchronized surfaces expected by the changed contract: source, tests, fixtures, schemas, templates, manifests, docs, release metadata, generated output, and localized copies.
|
|
72
74
|
- Known remaining risks, unverified assumptions, blocked decisions, and rollback notes.
|
|
73
|
-
- Concrete follow-up candidates,
|
|
74
|
-
|
|
75
|
+
- Concrete follow-up candidates, including gated actions such as commit, push, release, deploy,
|
|
76
|
+
dependency upgrade, migration, or manual verification when they are plausible next steps.
|
|
77
|
+
- Whether a bounded `next-action-menu` must be included or intentionally omitted.
|
|
75
78
|
|
|
76
79
|
<!-- mustflow-section: preconditions -->
|
|
77
80
|
## Preconditions
|
|
@@ -120,11 +123,17 @@ missing, blocked, failed, stale, or only partially relevant.
|
|
|
120
123
|
- Use `implemented but unverified` when the files changed but no relevant configured verification was run.
|
|
121
124
|
- Use `blocked` when required evidence cannot be produced without a missing decision, unavailable environment, manual-only command, failed prerequisite, or user approval.
|
|
122
125
|
- Use `not complete` when a required acceptance criterion is not implemented or verification contradicts the claim.
|
|
123
|
-
7. Decide whether a next-action menu is
|
|
124
|
-
-
|
|
125
|
-
|
|
126
|
+
7. Decide whether a next-action menu is required.
|
|
127
|
+
- For a non-trivial final report, read and apply `next-action-menu` before final reporting when
|
|
128
|
+
at least one concrete, evidence-backed follow-up task remains.
|
|
129
|
+
- Treat changed-file work, a created commit, push or release readiness, deploy preparation,
|
|
130
|
+
completed verification, paused implementation, or unresolved manual gate as non-trivial for
|
|
131
|
+
this decision.
|
|
132
|
+
- Do not omit the menu merely because the remaining useful actions are approval-gated. Include
|
|
133
|
+
gated actions such as push, publish, deploy, dependency upgrade, migration, or manual release
|
|
134
|
+
verification as menu rows with the gate stated plainly.
|
|
126
135
|
- If no useful follow-up exists, the user asked not to include recommendations, or the only next
|
|
127
|
-
actions are speculative
|
|
136
|
+
actions are speculative, omit the menu and keep the final report concise.
|
|
128
137
|
- Do not treat this gate as automatic host behavior: the menu appears only when the skill is
|
|
129
138
|
selected and its use conditions are met.
|
|
130
139
|
8. Write the final report from evidence, not confidence.
|
|
@@ -140,8 +149,10 @@ missing, blocked, failed, stale, or only partially relevant.
|
|
|
140
149
|
- Every user requirement is mapped to proof, a limitation, or an explicit out-of-scope decision.
|
|
141
150
|
- Skipped, missing, failed, stale, or manual-only verification is visible.
|
|
142
151
|
- Contract, template, schema, docs, test, and release drift is either resolved or named as remaining risk.
|
|
143
|
-
-
|
|
144
|
-
|
|
152
|
+
- For non-trivial final reports, useful follow-up tasks appear through `next-action-menu` whenever
|
|
153
|
+
at least one concrete next action remains, including approval-gated next actions.
|
|
154
|
+
- Omitted menus state a clear reason grounded in no concrete next action, user opt-out, or
|
|
155
|
+
speculative-only follow-ups.
|
|
145
156
|
- No unconfigured command, hidden transcript, broad log, or invented tool result is treated as proof.
|
|
146
157
|
|
|
147
158
|
<!-- mustflow-section: verification -->
|