mustflow 2.103.22 → 2.103.31
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 +5 -2
- package/dist/cli/commands/flow.js +93 -0
- package/dist/cli/commands/run/executor.js +28 -3
- package/dist/cli/commands/run/windows-command-script.js +23 -0
- package/dist/cli/i18n/en.js +11 -0
- package/dist/cli/i18n/es.js +11 -0
- package/dist/cli/i18n/fr.js +11 -0
- package/dist/cli/i18n/hi.js +11 -0
- package/dist/cli/i18n/ko.js +11 -0
- package/dist/cli/i18n/zh.js +11 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/lib/active-command-lock.js +4 -0
- package/dist/cli/lib/command-registry.js +7 -0
- package/dist/cli/lib/repo-flow-frontmatter.js +35 -0
- package/dist/cli/lib/repo-flow.js +209 -0
- package/dist/cli/lib/repo-map.js +3 -0
- package/dist/cli/lib/run-plan.js +8 -4
- package/dist/cli/lib/validation/constants.js +10 -0
- package/dist/cli/lib/validation/index.js +54 -1
- package/dist/core/generated-boundary.js +1 -0
- package/package.json +2 -1
- package/templates/default/i18n.toml +30 -6
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +29 -6
- package/templates/default/locales/en/.mustflow/skills/astro-code-change/SKILL.md +95 -23
- package/templates/default/locales/en/.mustflow/skills/axum-code-change/SKILL.md +219 -0
- package/templates/default/locales/en/.mustflow/skills/babylon-code-change/SKILL.md +318 -0
- package/templates/default/locales/en/.mustflow/skills/bun-code-change/SKILL.md +27 -12
- package/templates/default/locales/en/.mustflow/skills/elysia-code-change/SKILL.md +74 -20
- package/templates/default/locales/en/.mustflow/skills/godot-code-change/SKILL.md +272 -0
- package/templates/default/locales/en/.mustflow/skills/hono-code-change/SKILL.md +37 -23
- package/templates/default/locales/en/.mustflow/skills/routes.toml +28 -4
- package/templates/default/locales/en/.mustflow/skills/svelte-code-change/SKILL.md +65 -40
- package/templates/default/locales/en/.mustflow/skills/vue-code-change/SKILL.md +305 -0
- package/templates/default/manifest.toml +29 -1
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { writeUtf8FileInsideWithoutSymlinks } from '../../core/safe-filesystem.js';
|
|
4
|
+
import { isRecord } from './command-contract.js';
|
|
5
|
+
import { getRepoFlowSourceFingerprint, renderRepoFlowFrontmatter, } from './repo-flow-frontmatter.js';
|
|
6
|
+
import { readMustflowTomlFile } from './toml.js';
|
|
7
|
+
const REPO_FLOW_PATH = 'REPO_FLOW.md';
|
|
8
|
+
const FLOW_IDS = [
|
|
9
|
+
'working-agreement',
|
|
10
|
+
'agent-task',
|
|
11
|
+
'command-execution',
|
|
12
|
+
'generated-evidence',
|
|
13
|
+
'contract-surfaces',
|
|
14
|
+
'edit-first',
|
|
15
|
+
];
|
|
16
|
+
const INPUT_PATHS = [
|
|
17
|
+
'AGENTS.md',
|
|
18
|
+
'.mustflow/docs/agent-workflow.md',
|
|
19
|
+
'.mustflow/config/mustflow.toml',
|
|
20
|
+
'.mustflow/config/commands.toml',
|
|
21
|
+
'.mustflow/config/preferences.toml',
|
|
22
|
+
'.mustflow/skills/router.toml',
|
|
23
|
+
'.mustflow/skills/routes.toml',
|
|
24
|
+
'.mustflow/skills/INDEX.md',
|
|
25
|
+
'README.md',
|
|
26
|
+
'REPO_MAP.md',
|
|
27
|
+
];
|
|
28
|
+
function getStringArray(value) {
|
|
29
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === 'string') : [];
|
|
30
|
+
}
|
|
31
|
+
function readTomlObject(projectRoot, relativePath) {
|
|
32
|
+
try {
|
|
33
|
+
const parsed = readMustflowTomlFile(projectRoot, relativePath);
|
|
34
|
+
return isRecord(parsed) ? parsed : {};
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function readMustflowConfig(projectRoot) {
|
|
41
|
+
const configPath = path.join(projectRoot, '.mustflow', 'config', 'mustflow.toml');
|
|
42
|
+
return existsSync(configPath) ? readTomlObject(projectRoot, '.mustflow/config/mustflow.toml') : {};
|
|
43
|
+
}
|
|
44
|
+
function readCommandsConfig(projectRoot) {
|
|
45
|
+
const configPath = path.join(projectRoot, '.mustflow', 'config', 'commands.toml');
|
|
46
|
+
return existsSync(configPath) ? readTomlObject(projectRoot, '.mustflow/config/commands.toml') : {};
|
|
47
|
+
}
|
|
48
|
+
function getPresentInputs(projectRoot) {
|
|
49
|
+
return INPUT_PATHS.filter((relativePath) => existsSync(path.join(projectRoot, ...relativePath.split('/'))));
|
|
50
|
+
}
|
|
51
|
+
function getConfiguredCommandIntents(commandsConfig) {
|
|
52
|
+
return isRecord(commandsConfig.intents) ? Object.keys(commandsConfig.intents).sort() : [];
|
|
53
|
+
}
|
|
54
|
+
function getGeneratedDocuments(mustflowConfig) {
|
|
55
|
+
const documentRoots = isRecord(mustflowConfig.document_roots) ? mustflowConfig.document_roots : {};
|
|
56
|
+
return getStringArray(documentRoots.generated);
|
|
57
|
+
}
|
|
58
|
+
function createRepoFlowRenderModel(projectRoot) {
|
|
59
|
+
const mustflowConfig = readMustflowConfig(projectRoot);
|
|
60
|
+
const commandsConfig = readCommandsConfig(projectRoot);
|
|
61
|
+
const presentInputs = getPresentInputs(projectRoot);
|
|
62
|
+
const configuredCommandIntents = getConfiguredCommandIntents(commandsConfig);
|
|
63
|
+
const configuredReadOrder = getStringArray(mustflowConfig.read_order);
|
|
64
|
+
const configuredOptionalReadOrder = getStringArray(mustflowConfig.optional_read_order);
|
|
65
|
+
const generatedDocuments = getGeneratedDocuments(mustflowConfig);
|
|
66
|
+
const flowIds = [...FLOW_IDS];
|
|
67
|
+
const sourceFingerprint = getRepoFlowSourceFingerprint({
|
|
68
|
+
presentInputs,
|
|
69
|
+
configuredCommandIntents,
|
|
70
|
+
configuredReadOrder,
|
|
71
|
+
configuredOptionalReadOrder,
|
|
72
|
+
generatedDocuments,
|
|
73
|
+
flowIds,
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
presentInputs,
|
|
77
|
+
configuredCommandIntents,
|
|
78
|
+
configuredReadOrder,
|
|
79
|
+
configuredOptionalReadOrder,
|
|
80
|
+
generatedDocuments,
|
|
81
|
+
flowIds,
|
|
82
|
+
sourceFingerprint,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function renderList(values, fallback) {
|
|
86
|
+
return values.length > 0 ? values.map((value) => `- \`${value}\``) : [fallback];
|
|
87
|
+
}
|
|
88
|
+
function renderCommandIntentSummary(intentNames) {
|
|
89
|
+
const notableIntents = [
|
|
90
|
+
'mustflow_doctor',
|
|
91
|
+
'mustflow_check',
|
|
92
|
+
'lint',
|
|
93
|
+
'build',
|
|
94
|
+
'test_related',
|
|
95
|
+
'docs_validate_fast',
|
|
96
|
+
'test_release',
|
|
97
|
+
'repo_map',
|
|
98
|
+
'repo_flow',
|
|
99
|
+
'changes_status',
|
|
100
|
+
'changes_diff_summary',
|
|
101
|
+
].filter((intentName) => intentNames.includes(intentName));
|
|
102
|
+
return renderList(notableIntents, 'No configured command intents were discovered.');
|
|
103
|
+
}
|
|
104
|
+
export function getExpectedRepoFlowSourceFingerprint(projectRoot) {
|
|
105
|
+
return createRepoFlowRenderModel(projectRoot).sourceFingerprint;
|
|
106
|
+
}
|
|
107
|
+
export function generateRepoFlow(projectRoot) {
|
|
108
|
+
const model = createRepoFlowRenderModel(projectRoot);
|
|
109
|
+
return [
|
|
110
|
+
...renderRepoFlowFrontmatter(model.flowIds.length, model.sourceFingerprint),
|
|
111
|
+
'# REPO_FLOW.md',
|
|
112
|
+
'',
|
|
113
|
+
'This file is a generated design-flow map for the current mustflow root. It is not command authority, architecture authority, or a replacement for `AGENTS.md`, `.mustflow/config/commands.toml`, or current source files.',
|
|
114
|
+
'Regenerate it with `mf flow --write` instead of editing it by hand.',
|
|
115
|
+
'',
|
|
116
|
+
'## How To Use',
|
|
117
|
+
'',
|
|
118
|
+
'- Use this file to understand how work moves through the repository before choosing where to read or edit.',
|
|
119
|
+
'- Use `REPO_MAP.md` for file and anchor discovery.',
|
|
120
|
+
'- Use `AGENTS.md` and `.mustflow/config/commands.toml` for binding workflow and command execution rules.',
|
|
121
|
+
'- Use current source, tests, and docs as the source of truth for implementation details.',
|
|
122
|
+
'',
|
|
123
|
+
'## One-Screen Mental Model',
|
|
124
|
+
'',
|
|
125
|
+
'```mermaid',
|
|
126
|
+
'flowchart TD',
|
|
127
|
+
' UserTask["User task"] --> Rules["AGENTS.md and workflow policy"]',
|
|
128
|
+
' Rules --> Skills["Skill selection"]',
|
|
129
|
+
' Skills --> Files["Current source, tests, docs"]',
|
|
130
|
+
' Files --> Change["Scoped change"]',
|
|
131
|
+
' Change --> Verify["Configured mf run intents"]',
|
|
132
|
+
' Verify --> Evidence["Run receipts and final report"]',
|
|
133
|
+
'```',
|
|
134
|
+
'',
|
|
135
|
+
'## Agent Work Flow',
|
|
136
|
+
'',
|
|
137
|
+
'```mermaid',
|
|
138
|
+
'flowchart LR',
|
|
139
|
+
' A["Read AGENTS.md"] --> B["Read workflow and config"]',
|
|
140
|
+
' B --> C["Select matching skill"]',
|
|
141
|
+
' C --> D["Read task source files"]',
|
|
142
|
+
' D --> E["Edit the narrowest safe scope"]',
|
|
143
|
+
' E --> F["Verify with configured intents"]',
|
|
144
|
+
'```',
|
|
145
|
+
'',
|
|
146
|
+
'### Read Order Inputs',
|
|
147
|
+
'',
|
|
148
|
+
...renderList(model.configuredReadOrder, 'No read_order entries were found in `.mustflow/config/mustflow.toml`.'),
|
|
149
|
+
'',
|
|
150
|
+
'### Optional Navigation Inputs',
|
|
151
|
+
'',
|
|
152
|
+
...renderList(model.configuredOptionalReadOrder, 'No optional_read_order entries were found in `.mustflow/config/mustflow.toml`.'),
|
|
153
|
+
'',
|
|
154
|
+
'## Command Execution Flow',
|
|
155
|
+
'',
|
|
156
|
+
'```mermaid',
|
|
157
|
+
'flowchart TD',
|
|
158
|
+
' Need["Need verification or generation"] --> Contract[".mustflow/config/commands.toml"]',
|
|
159
|
+
' Contract --> Eligible["configured + oneshot + agent_allowed"]',
|
|
160
|
+
' Eligible --> Run["mf run <intent>"]',
|
|
161
|
+
' Run --> Receipt[".mustflow/state/runs/ receipt"]',
|
|
162
|
+
'```',
|
|
163
|
+
'',
|
|
164
|
+
'### Notable Configured Intents',
|
|
165
|
+
'',
|
|
166
|
+
...renderCommandIntentSummary(model.configuredCommandIntents),
|
|
167
|
+
'',
|
|
168
|
+
'## Generated and Receipt Flow',
|
|
169
|
+
'',
|
|
170
|
+
'```mermaid',
|
|
171
|
+
'flowchart LR',
|
|
172
|
+
' Source["Current repository inputs"] --> Map["REPO_MAP.md"]',
|
|
173
|
+
' Source --> Flow["REPO_FLOW.md"]',
|
|
174
|
+
' Commands["mf run intents"] --> Receipts[".mustflow/state/runs/"]',
|
|
175
|
+
' Map --> Check["mf check --strict"]',
|
|
176
|
+
' Flow --> Check',
|
|
177
|
+
' Receipts --> Evidence["Evidence review"]',
|
|
178
|
+
'```',
|
|
179
|
+
'',
|
|
180
|
+
'### Generated Surfaces',
|
|
181
|
+
'',
|
|
182
|
+
...renderList(model.generatedDocuments, 'No generated document roots were declared.'),
|
|
183
|
+
'',
|
|
184
|
+
'## Public Contract Surfaces',
|
|
185
|
+
'',
|
|
186
|
+
'- CLI commands and options live in `src/cli/commands/` and `src/cli/lib/command-registry.ts`.',
|
|
187
|
+
'- Human-readable CLI strings live in `src/cli/i18n/`.',
|
|
188
|
+
'- Strict workflow validation lives in `src/cli/lib/validation/`.',
|
|
189
|
+
'- User-facing command docs live in `docs-site/src/content/docs/*/commands/`.',
|
|
190
|
+
'- File-role docs live in `docs-site/src/content/docs/*/files/`.',
|
|
191
|
+
'- Release-sensitive package metadata starts at `package.json`.',
|
|
192
|
+
'',
|
|
193
|
+
'## Where To Edit First',
|
|
194
|
+
'',
|
|
195
|
+
'- CLI behavior: start at the matching file under `src/cli/commands/`, then sync registry, i18n, tests, and docs.',
|
|
196
|
+
'- Generated Markdown: start at the generator under `src/cli/lib/`, then sync strict validation and file-role docs.',
|
|
197
|
+
'- Command authority: start at `.mustflow/config/commands.toml`, then sync docs and command-contract tests.',
|
|
198
|
+
'- Workflow or skill behavior: start at `.mustflow/skills/router.toml` or the matching `SKILL.md`, then sync route metadata and validation.',
|
|
199
|
+
'- Release metadata: locate version sources before editing version files.',
|
|
200
|
+
'',
|
|
201
|
+
'## Present Flow Inputs',
|
|
202
|
+
'',
|
|
203
|
+
...renderList(model.presentInputs, 'No flow input files were found.'),
|
|
204
|
+
'',
|
|
205
|
+
].join('\n');
|
|
206
|
+
}
|
|
207
|
+
export function writeRepoFlow(projectRoot, content) {
|
|
208
|
+
writeUtf8FileInsideWithoutSymlinks(projectRoot, path.join(projectRoot, REPO_FLOW_PATH), content);
|
|
209
|
+
}
|
package/dist/cli/lib/repo-map.js
CHANGED
|
@@ -23,6 +23,7 @@ const EXCLUDED_PREFIXES = ['.mustflow/backups/'];
|
|
|
23
23
|
const GENERATED_FILES = new Set(['REPO_MAP.md']);
|
|
24
24
|
const DEFAULT_PRIORITY_PATHS = [
|
|
25
25
|
'AGENTS.md',
|
|
26
|
+
'REPO_FLOW.md',
|
|
26
27
|
'.mustflow/docs/agent-workflow.md',
|
|
27
28
|
'.mustflow/config/mustflow.toml',
|
|
28
29
|
'.mustflow/config/commands.toml',
|
|
@@ -76,6 +77,7 @@ const MACHINE_CONTRACT_ANCHOR_FILE_SET = new Set(MACHINE_CONTRACT_ANCHOR_FILES);
|
|
|
76
77
|
const DEFAULT_NESTED_ANCHOR_FILES = [
|
|
77
78
|
'AGENTS.md',
|
|
78
79
|
'REPO_MAP.md',
|
|
80
|
+
'REPO_FLOW.md',
|
|
79
81
|
'.gitattributes',
|
|
80
82
|
'.editorconfig',
|
|
81
83
|
'.mustflow/config/mustflow.toml',
|
|
@@ -131,6 +133,7 @@ const NESTED_ROOT_DOC_LABELS = new Map([
|
|
|
131
133
|
]);
|
|
132
134
|
const EXACT_ANCHOR_DESCRIPTIONS = new Map([
|
|
133
135
|
['AGENTS.md', 'Root agent operating rules. Read this before changing files.'],
|
|
136
|
+
['REPO_FLOW.md', 'Generated design-flow map. Use it to understand how work moves through the root.'],
|
|
134
137
|
['.gitattributes', 'Git text, binary, and line-ending policy. Check before normalizing files.'],
|
|
135
138
|
['.editorconfig', 'Editor formatting defaults such as indentation, charset, and final newline.'],
|
|
136
139
|
['README.md', 'Human-facing project overview. Use it as context, not as agent policy.'],
|
package/dist/cli/lib/run-plan.js
CHANGED
|
@@ -11,6 +11,7 @@ import { checkRepoApprovalGate } from '../../core/repo-approval-gate.js';
|
|
|
11
11
|
import { normalizeSuccessExitCodes } from '../../core/success-exit-codes.js';
|
|
12
12
|
import { normalizeSafeTestTargetPath, TEST_TARGET_PATH_ERROR } from '../../core/test-target-paths.js';
|
|
13
13
|
import { evaluateCommandPreconditions, } from '../../core/command-preconditions.js';
|
|
14
|
+
import { isWindowsCommandScriptPath } from '../commands/run/windows-command-script.js';
|
|
14
15
|
import { t } from './i18n.js';
|
|
15
16
|
function getSuccessExitCodes(intent) {
|
|
16
17
|
return normalizeSuccessExitCodes(intent.success_exit_codes);
|
|
@@ -47,8 +48,8 @@ function normalizeTestTargets(values) {
|
|
|
47
48
|
function commandAcceptsTestTargets(intent) {
|
|
48
49
|
return isRecord(intent.selection) && intent.selection.accepts_test_targets === true;
|
|
49
50
|
}
|
|
50
|
-
function
|
|
51
|
-
return process.platform === 'win32' && executablePath
|
|
51
|
+
function isResolvedWindowsCommandScript(executablePath) {
|
|
52
|
+
return process.platform === 'win32' && isWindowsCommandScriptPath(executablePath);
|
|
52
53
|
}
|
|
53
54
|
export function isMustflowBuiltinIntent(intent) {
|
|
54
55
|
return readString(intent, 'kind') === 'mustflow_builtin';
|
|
@@ -66,6 +67,7 @@ function resolveArgvCommand(projectRoot, contract, intent, commandArgv) {
|
|
|
66
67
|
executable: process.execPath,
|
|
67
68
|
args: [entrypoint, ...args],
|
|
68
69
|
shell: false,
|
|
70
|
+
windowsCommandScript: false,
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
73
|
}
|
|
@@ -74,13 +76,15 @@ function resolveArgvCommand(projectRoot, contract, intent, commandArgv) {
|
|
|
74
76
|
return {
|
|
75
77
|
executable: localBinExecutable,
|
|
76
78
|
args,
|
|
77
|
-
shell:
|
|
79
|
+
shell: false,
|
|
80
|
+
windowsCommandScript: isResolvedWindowsCommandScript(localBinExecutable),
|
|
78
81
|
};
|
|
79
82
|
}
|
|
80
83
|
return {
|
|
81
84
|
executable: command,
|
|
82
85
|
args,
|
|
83
|
-
shell:
|
|
86
|
+
shell: false,
|
|
87
|
+
windowsCommandScript: isResolvedWindowsCommandScript(command),
|
|
84
88
|
};
|
|
85
89
|
}
|
|
86
90
|
function getRunPlanMode(commandArgv, intent) {
|
|
@@ -203,6 +203,14 @@ export const REPO_MAP_PRIVACY_MODE = 'minimal';
|
|
|
203
203
|
export const REPO_MAP_SOURCE_FINGERPRINT_PATTERN = /^sha256:[a-f0-9]{64}$/u;
|
|
204
204
|
export const ALLOWED_REPO_MAP_DEGRADED_VALUES = new Set(['true', 'false']);
|
|
205
205
|
export const ALLOWED_REPO_MAP_GIT_LS_FILES_STATUSES = new Set(['ok', 'timeout', 'max_buffer', 'error']);
|
|
206
|
+
export const REPO_FLOW_DOC_ID = 'repo-flow';
|
|
207
|
+
export const REPO_FLOW_LIFECYCLE = 'generated';
|
|
208
|
+
export const REPO_FLOW_GENERATOR = 'mustflow';
|
|
209
|
+
export const REPO_FLOW_RELATIVE_ROOT = '.';
|
|
210
|
+
export const REPO_FLOW_SOURCE_POLICY = 'flow_contract';
|
|
211
|
+
export const REPO_FLOW_PRIVACY_MODE = 'minimal';
|
|
212
|
+
export const REPO_FLOW_SOURCE_FINGERPRINT_PATTERN = /^sha256:[a-f0-9]{64}$/u;
|
|
213
|
+
export const ALLOWED_REPO_FLOW_DEGRADED_VALUES = new Set(['true', 'false']);
|
|
206
214
|
export const SKILL_RESOURCE_MANIFEST = 'resources.toml';
|
|
207
215
|
export const SKILL_RESOURCE_ROOTS = new Set(['references', 'assets', 'scripts']);
|
|
208
216
|
export const ALLOWED_SKILL_RESOURCE_TYPES = new Set(['reference', 'asset', 'script']);
|
|
@@ -226,6 +234,8 @@ export const REPO_MAP_REMOTE_OR_BRANCH_PATTERNS = [
|
|
|
226
234
|
/\bgit@/iu,
|
|
227
235
|
/^\s*(?:Remote|Branch):/imu,
|
|
228
236
|
];
|
|
237
|
+
export const VOLATILE_REPO_FLOW_PATTERNS = VOLATILE_REPO_MAP_PATTERNS;
|
|
238
|
+
export const REPO_FLOW_REMOTE_OR_BRANCH_PATTERNS = REPO_MAP_REMOTE_OR_BRANCH_PATTERNS;
|
|
229
239
|
export const LOCAL_ABSOLUTE_PATH_PATTERNS = [
|
|
230
240
|
/\b[A-Za-z]:\\(?:Users|Documents and Settings)\\/iu,
|
|
231
241
|
/(?:^|[\s"'(])\/(?:Users|home)\/[A-Za-z0-9._-]+\/[^\s)"']*/imu,
|
|
@@ -11,6 +11,7 @@ import { validateSourceAnchorsInProject } from '../../../core/source-anchor-vali
|
|
|
11
11
|
import { listFilesRecursive, toPosixPath } from '../filesystem.js';
|
|
12
12
|
import { readGitChangedFiles } from '../git-changes.js';
|
|
13
13
|
import { inspectManifestLock } from '../manifest-lock.js';
|
|
14
|
+
import { getExpectedRepoFlowSourceFingerprint } from '../repo-flow.js';
|
|
14
15
|
import { getExpectedRepoMapSourceFingerprint } from '../repo-map.js';
|
|
15
16
|
import { parseTomlText, readMustflowTomlFile } from '../toml.js';
|
|
16
17
|
import { MUSTFLOW_JSON_MAX_BYTES } from '../mustflow-read.js';
|
|
@@ -19,7 +20,7 @@ import { VERSIONING_CONFIG_PATH, detectVersionSourcePaths, readDeclaredVersionSo
|
|
|
19
20
|
import { normalizeTechnologyPreferencesTable, TECHNOLOGY_CONFIG_RELATIVE_PATH, } from '../../../core/technology-preferences.js';
|
|
20
21
|
import { isPromptCacheStableLeafSkillSurface, measurePromptCacheReferenceBlockBytes, } from '../../../core/prompt-cache-rendering.js';
|
|
21
22
|
import { validateSkillRouteFixtures } from '../../../core/skill-route-fixtures.js';
|
|
22
|
-
import { ALLOWED_APPROVAL_ACTIONS, ALLOWED_APPROVAL_GATES, ALLOWED_BUDGET_LIMIT_ACTIONS, ALLOWED_CAPABILITY_STATES, ALLOWED_COMMIT_MESSAGE_STYLES, ALLOWED_COMPACTION_CATEGORIES, ALLOWED_COMPACTION_LONG_LIMIT_ACTIONS, ALLOWED_COMPACTION_RAW_LIMIT_ACTIONS, ALLOWED_COMPACTION_STATE_STORES, ALLOWED_COMPACTION_STRATEGIES, ALLOWED_CONTEXT_AUTHORITIES, ALLOWED_CONTEXT_DOCUMENT_AUTHORITIES, ALLOWED_CONTEXT_READ_POLICIES, ALLOWED_HANDOFF_MODES, ALLOWED_HARNESS_FRESH_CONTEXT_MODES, ALLOWED_HARNESS_MODES, ALLOWED_HARNESS_PHASES, ALLOWED_ISOLATION_PREFERENCES, ALLOWED_MAP_MODES, ALLOWED_MAP_PRIVACY_LEVELS, ALLOWED_PROJECT_PROFILES, ALLOWED_REPO_MAP_DEGRADED_VALUES, ALLOWED_REPO_MAP_GIT_LS_FILES_STATUSES, ALLOWED_PROMPT_CACHE_STABLE_PREFIX_POLICIES, ALLOWED_PROMPT_CACHE_STRATEGIES, ALLOWED_PROMPT_CACHE_TASK_READ_POLICIES, ALLOWED_REFRESH_CHECKPOINTS, ALLOWED_REFRESH_METHODS, ALLOWED_REFRESH_MODES, ALLOWED_REFRESH_STATE_STORES, ALLOWED_SKILL_RESOURCE_TYPES, ALLOWED_SKILL_ROUTE_CATEGORIES, ALLOWED_SKILL_ROUTE_PROFILES, ALLOWED_SKILL_ROUTE_TYPES, ALLOWED_STALE_TEST_ACTIONS, ALLOWED_TEST_AUTHORING_POLICIES, ALLOWED_TEST_DELETION_REASONS, ALLOWED_TESTING_POLICIES, ALLOWED_TRANSLATION_POLICIES, ALLOWED_VERIFICATION_SELECTION_STRATEGIES, ALLOWED_VERSION_SOURCE_AUTHORITIES, ALLOWED_VERSION_SOURCE_KINDS, CAPABILITY_BOOLEAN_FIELDS, CAPABILITY_STATE_FIELDS, CONTEXT_AUTHORITY_DRIFT_PATTERNS, DESIGN_TOKEN_DEFINITION_PATTERNS, FORBIDDEN_RELEASE_VERSIONING_CONTRACT_FIELDS, FORBIDDEN_TEST_DELETION_REASONS, FORBIDDEN_VERIFICATION_SELECTION_AUTHORITY_FIELDS, LOCAL_ABSOLUTE_PATH_PATTERNS, LOCAL_TASK_STATE_ROOTS, RAW_COMMAND_FENCE_PATTERN, RELEASE_VERSIONING_BOOLEAN_FIELDS, REPO_MAP_DOC_ID, REPO_MAP_GENERATOR, REPO_MAP_LIFECYCLE, REPO_MAP_PRIVACY_MODE, REPO_MAP_RELATIVE_ROOT, REPO_MAP_REMOTE_OR_BRANCH_PATTERNS, REPO_MAP_SOURCE_FINGERPRINT_PATTERN, REPO_MAP_SOURCE_POLICY, REQUIRED_AGENT_LOOP_PHASES, REQUIRED_SKILL_SCRIPT_RUN_POLICY, REQUIRED_SKILL_SECTION_IDS, ROUTER_INDEX_FILES, ROUTER_INDEX_PROCEDURE_SECTION_PATTERN, SECRET_LIKE_CONTEXT_PATTERNS, SKILL_COMMAND_PERMISSION_CLAIM_PATTERNS, SKILL_INDEX_PATH, SKILL_PACK_ID_PATTERN, SKILL_RESOURCE_MANIFEST, SKILL_RESOURCE_ROOTS, SKILL_RESOURCE_TYPE_BY_ROOT, SKILL_ROUTE_CATEGORY_LABELS, SKILL_ROUTES_METADATA_PATH, SUPPORTED_SKILL_SCHEMA_VERSION, TEST_AUTHORING_BOOLEAN_FIELDS, VERIFICATION_SELECTION_BOOLEAN_FIELDS, VOLATILE_REPO_MAP_PATTERNS } from './constants.js';
|
|
23
|
+
import { ALLOWED_APPROVAL_ACTIONS, ALLOWED_APPROVAL_GATES, ALLOWED_BUDGET_LIMIT_ACTIONS, ALLOWED_CAPABILITY_STATES, ALLOWED_COMMIT_MESSAGE_STYLES, ALLOWED_COMPACTION_CATEGORIES, ALLOWED_COMPACTION_LONG_LIMIT_ACTIONS, ALLOWED_COMPACTION_RAW_LIMIT_ACTIONS, ALLOWED_COMPACTION_STATE_STORES, ALLOWED_COMPACTION_STRATEGIES, ALLOWED_CONTEXT_AUTHORITIES, ALLOWED_CONTEXT_DOCUMENT_AUTHORITIES, ALLOWED_CONTEXT_READ_POLICIES, ALLOWED_HANDOFF_MODES, ALLOWED_HARNESS_FRESH_CONTEXT_MODES, ALLOWED_HARNESS_MODES, ALLOWED_HARNESS_PHASES, ALLOWED_ISOLATION_PREFERENCES, ALLOWED_MAP_MODES, ALLOWED_MAP_PRIVACY_LEVELS, ALLOWED_PROJECT_PROFILES, ALLOWED_REPO_MAP_DEGRADED_VALUES, ALLOWED_REPO_MAP_GIT_LS_FILES_STATUSES, ALLOWED_REPO_FLOW_DEGRADED_VALUES, ALLOWED_PROMPT_CACHE_STABLE_PREFIX_POLICIES, ALLOWED_PROMPT_CACHE_STRATEGIES, ALLOWED_PROMPT_CACHE_TASK_READ_POLICIES, ALLOWED_REFRESH_CHECKPOINTS, ALLOWED_REFRESH_METHODS, ALLOWED_REFRESH_MODES, ALLOWED_REFRESH_STATE_STORES, ALLOWED_SKILL_RESOURCE_TYPES, ALLOWED_SKILL_ROUTE_CATEGORIES, ALLOWED_SKILL_ROUTE_PROFILES, ALLOWED_SKILL_ROUTE_TYPES, ALLOWED_STALE_TEST_ACTIONS, ALLOWED_TEST_AUTHORING_POLICIES, ALLOWED_TEST_DELETION_REASONS, ALLOWED_TESTING_POLICIES, ALLOWED_TRANSLATION_POLICIES, ALLOWED_VERIFICATION_SELECTION_STRATEGIES, ALLOWED_VERSION_SOURCE_AUTHORITIES, ALLOWED_VERSION_SOURCE_KINDS, CAPABILITY_BOOLEAN_FIELDS, CAPABILITY_STATE_FIELDS, CONTEXT_AUTHORITY_DRIFT_PATTERNS, DESIGN_TOKEN_DEFINITION_PATTERNS, FORBIDDEN_RELEASE_VERSIONING_CONTRACT_FIELDS, FORBIDDEN_TEST_DELETION_REASONS, FORBIDDEN_VERIFICATION_SELECTION_AUTHORITY_FIELDS, LOCAL_ABSOLUTE_PATH_PATTERNS, LOCAL_TASK_STATE_ROOTS, RAW_COMMAND_FENCE_PATTERN, RELEASE_VERSIONING_BOOLEAN_FIELDS, REPO_MAP_DOC_ID, REPO_MAP_GENERATOR, REPO_MAP_LIFECYCLE, REPO_MAP_PRIVACY_MODE, REPO_MAP_RELATIVE_ROOT, REPO_MAP_REMOTE_OR_BRANCH_PATTERNS, REPO_MAP_SOURCE_FINGERPRINT_PATTERN, REPO_MAP_SOURCE_POLICY, REPO_FLOW_DOC_ID, REPO_FLOW_GENERATOR, REPO_FLOW_LIFECYCLE, REPO_FLOW_PRIVACY_MODE, REPO_FLOW_RELATIVE_ROOT, REPO_FLOW_REMOTE_OR_BRANCH_PATTERNS, REPO_FLOW_SOURCE_FINGERPRINT_PATTERN, REPO_FLOW_SOURCE_POLICY, REQUIRED_AGENT_LOOP_PHASES, REQUIRED_SKILL_SCRIPT_RUN_POLICY, REQUIRED_SKILL_SECTION_IDS, ROUTER_INDEX_FILES, ROUTER_INDEX_PROCEDURE_SECTION_PATTERN, SECRET_LIKE_CONTEXT_PATTERNS, SKILL_COMMAND_PERMISSION_CLAIM_PATTERNS, SKILL_INDEX_PATH, SKILL_PACK_ID_PATTERN, SKILL_RESOURCE_MANIFEST, SKILL_RESOURCE_ROOTS, SKILL_RESOURCE_TYPE_BY_ROOT, SKILL_ROUTE_CATEGORY_LABELS, SKILL_ROUTES_METADATA_PATH, SUPPORTED_SKILL_SCHEMA_VERSION, TEST_AUTHORING_BOOLEAN_FIELDS, VERIFICATION_SELECTION_BOOLEAN_FIELDS, VOLATILE_REPO_FLOW_PATTERNS, VOLATILE_REPO_MAP_PATTERNS } from './constants.js';
|
|
23
24
|
import { hasOwn, isPositiveInteger, isSafeRelativePath, pushStrictIssue, pushStrictWarning, validateAllowedStringField, validateBooleanField, validateExactStringArrayField, validateNestedTable, validatePathArrayField, validatePathField, validatePositiveIntegerField, validateRequiredFiles, validateRequiredPathField, validateRequiredStringField, validateStringArrayField, validateStringArrayMembers, validateStringField, validateTable, validateToml, validateWorkspaceRoots } from './primitives.js';
|
|
24
25
|
import { isConfiguredCommandIntent, isDeclaredCommandIntent } from './command-intents.js';
|
|
25
26
|
import { parseSimpleFrontmatter, readFrontmatterList, readSkillSectionIds } from './frontmatter.js';
|
|
@@ -1476,6 +1477,57 @@ function validateStrictRepoMap(projectRoot, issues) {
|
|
|
1476
1477
|
pushStrictIssue(issues, 'REPO_MAP.md contains remote URL or branch metadata');
|
|
1477
1478
|
}
|
|
1478
1479
|
}
|
|
1480
|
+
function validateStrictRepoFlow(projectRoot, issues) {
|
|
1481
|
+
const repoFlowPath = path.join(projectRoot, 'REPO_FLOW.md');
|
|
1482
|
+
if (!existsSync(repoFlowPath)) {
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
const content = readStrictMustflowText(projectRoot, 'REPO_FLOW.md', issues);
|
|
1486
|
+
if (content === undefined) {
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
const frontmatter = parseSimpleFrontmatter(content);
|
|
1490
|
+
if (frontmatter.mustflow_doc !== REPO_FLOW_DOC_ID) {
|
|
1491
|
+
pushStrictIssue(issues, `REPO_FLOW.md frontmatter mustflow_doc must be "${REPO_FLOW_DOC_ID}"`);
|
|
1492
|
+
}
|
|
1493
|
+
if (frontmatter.lifecycle !== REPO_FLOW_LIFECYCLE) {
|
|
1494
|
+
pushStrictIssue(issues, `REPO_FLOW.md frontmatter lifecycle must be "${REPO_FLOW_LIFECYCLE}"`);
|
|
1495
|
+
}
|
|
1496
|
+
if (frontmatter.generated_by !== REPO_FLOW_GENERATOR) {
|
|
1497
|
+
pushStrictIssue(issues, `REPO_FLOW.md frontmatter generated_by must be "${REPO_FLOW_GENERATOR}"`);
|
|
1498
|
+
}
|
|
1499
|
+
if (frontmatter.relative_root !== REPO_FLOW_RELATIVE_ROOT) {
|
|
1500
|
+
pushStrictIssue(issues, `REPO_FLOW.md frontmatter relative_root must be "${REPO_FLOW_RELATIVE_ROOT}"`);
|
|
1501
|
+
}
|
|
1502
|
+
if (frontmatter.source_policy !== REPO_FLOW_SOURCE_POLICY) {
|
|
1503
|
+
pushStrictIssue(issues, `REPO_FLOW.md frontmatter source_policy must be "${REPO_FLOW_SOURCE_POLICY}"`);
|
|
1504
|
+
}
|
|
1505
|
+
if (frontmatter.privacy_mode !== REPO_FLOW_PRIVACY_MODE) {
|
|
1506
|
+
pushStrictIssue(issues, `REPO_FLOW.md frontmatter privacy_mode must be "${REPO_FLOW_PRIVACY_MODE}"`);
|
|
1507
|
+
}
|
|
1508
|
+
if (!/^[1-9]\d*$/u.test(frontmatter.flow_count ?? '')) {
|
|
1509
|
+
pushStrictIssue(issues, 'REPO_FLOW.md frontmatter flow_count must be a positive integer');
|
|
1510
|
+
}
|
|
1511
|
+
if (!ALLOWED_REPO_FLOW_DEGRADED_VALUES.has(frontmatter.degraded ?? '')) {
|
|
1512
|
+
pushStrictIssue(issues, 'REPO_FLOW.md frontmatter degraded must be true or false');
|
|
1513
|
+
}
|
|
1514
|
+
if (!REPO_FLOW_SOURCE_FINGERPRINT_PATTERN.test(frontmatter.source_fingerprint ?? '')) {
|
|
1515
|
+
pushStrictIssue(issues, 'REPO_FLOW.md frontmatter source_fingerprint must be sha256:<64 lowercase hex characters>');
|
|
1516
|
+
}
|
|
1517
|
+
else {
|
|
1518
|
+
const currentSourceFingerprint = frontmatter.source_fingerprint;
|
|
1519
|
+
const expectedSourceFingerprint = getExpectedRepoFlowSourceFingerprint(projectRoot);
|
|
1520
|
+
if (expectedSourceFingerprint && currentSourceFingerprint !== expectedSourceFingerprint) {
|
|
1521
|
+
pushStrictIssue(issues, 'REPO_FLOW.md source_fingerprint is stale; regenerate with mf flow --write');
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
if (VOLATILE_REPO_FLOW_PATTERNS.some((pattern) => pattern.test(content))) {
|
|
1525
|
+
pushStrictIssue(issues, 'REPO_FLOW.md contains volatile generated metadata');
|
|
1526
|
+
}
|
|
1527
|
+
if (REPO_FLOW_REMOTE_OR_BRANCH_PATTERNS.some((pattern) => pattern.test(content))) {
|
|
1528
|
+
pushStrictIssue(issues, 'REPO_FLOW.md contains remote URL or branch metadata');
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1479
1531
|
function validateStrictContextDocuments(projectRoot, limits, issues) {
|
|
1480
1532
|
const contextRoot = path.join(projectRoot, '.mustflow', 'context');
|
|
1481
1533
|
const contextFiles = listFilesRecursive(contextRoot).filter((relativePath) => relativePath.endsWith('.md'));
|
|
@@ -1590,6 +1642,7 @@ function validateStrict(projectRoot, parsed, issues) {
|
|
|
1590
1642
|
validateStrictSkills(projectRoot, parsed.commandsToml, issues);
|
|
1591
1643
|
validateStrictTemplateSkillProfiles(issues);
|
|
1592
1644
|
validateStrictRepoMap(projectRoot, issues);
|
|
1645
|
+
validateStrictRepoFlow(projectRoot, issues);
|
|
1593
1646
|
validateStrictContextDocuments(projectRoot, retentionLimits, issues);
|
|
1594
1647
|
validateStrictSourceAnchors(projectRoot, issues);
|
|
1595
1648
|
validateStrictRunReceipt(projectRoot, issues);
|
|
@@ -8,6 +8,7 @@ export const GENERATED_BOUNDARY_SCRIPT_ID = 'generated-boundary';
|
|
|
8
8
|
export const GENERATED_BOUNDARY_SCRIPT_REF = `${GENERATED_BOUNDARY_PACK_ID}/${GENERATED_BOUNDARY_SCRIPT_ID}`;
|
|
9
9
|
const BUILTIN_GENERATED_PATTERNS = [
|
|
10
10
|
'REPO_MAP.md',
|
|
11
|
+
'REPO_FLOW.md',
|
|
11
12
|
'.mustflow/config/manifest.lock.toml',
|
|
12
13
|
'.mustflow/state/**',
|
|
13
14
|
'.mustflow/cache/**',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mustflow",
|
|
3
|
-
"version": "2.103.
|
|
3
|
+
"version": "2.103.31",
|
|
4
4
|
"description": "Agent workflow documents and CLI for mustflow repository roots.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT-0",
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"llm",
|
|
71
71
|
"codex",
|
|
72
72
|
"mustflow",
|
|
73
|
+
"repo-flow",
|
|
73
74
|
"repo-map",
|
|
74
75
|
"repository-template",
|
|
75
76
|
"toml",
|
|
@@ -62,7 +62,7 @@ translations = {}
|
|
|
62
62
|
[documents."skills.index"]
|
|
63
63
|
source = "locales/en/.mustflow/skills/INDEX.md"
|
|
64
64
|
source_locale = "en"
|
|
65
|
-
revision =
|
|
65
|
+
revision = 197
|
|
66
66
|
translations = {}
|
|
67
67
|
|
|
68
68
|
[documents."skill.adapter-boundary"]
|
|
@@ -583,7 +583,19 @@ translations = {}
|
|
|
583
583
|
[documents."skill.astro-code-change"]
|
|
584
584
|
source = "locales/en/.mustflow/skills/astro-code-change/SKILL.md"
|
|
585
585
|
source_locale = "en"
|
|
586
|
-
revision =
|
|
586
|
+
revision = 5
|
|
587
|
+
translations = {}
|
|
588
|
+
|
|
589
|
+
[documents."skill.axum-code-change"]
|
|
590
|
+
source = "locales/en/.mustflow/skills/axum-code-change/SKILL.md"
|
|
591
|
+
source_locale = "en"
|
|
592
|
+
revision = 1
|
|
593
|
+
translations = {}
|
|
594
|
+
|
|
595
|
+
[documents."skill.babylon-code-change"]
|
|
596
|
+
source = "locales/en/.mustflow/skills/babylon-code-change/SKILL.md"
|
|
597
|
+
source_locale = "en"
|
|
598
|
+
revision = 1
|
|
587
599
|
translations = {}
|
|
588
600
|
|
|
589
601
|
[documents."skill.auth-permission-change"]
|
|
@@ -613,7 +625,7 @@ translations = {}
|
|
|
613
625
|
[documents."skill.bun-code-change"]
|
|
614
626
|
source = "locales/en/.mustflow/skills/bun-code-change/SKILL.md"
|
|
615
627
|
source_locale = "en"
|
|
616
|
-
revision =
|
|
628
|
+
revision = 2
|
|
617
629
|
translations = {}
|
|
618
630
|
|
|
619
631
|
[documents."skill.cpp-code-change"]
|
|
@@ -643,7 +655,7 @@ translations = {}
|
|
|
643
655
|
[documents."skill.elysia-code-change"]
|
|
644
656
|
source = "locales/en/.mustflow/skills/elysia-code-change/SKILL.md"
|
|
645
657
|
source_locale = "en"
|
|
646
|
-
revision =
|
|
658
|
+
revision = 3
|
|
647
659
|
translations = {}
|
|
648
660
|
|
|
649
661
|
[documents."skill.flutter-code-change"]
|
|
@@ -658,10 +670,16 @@ source_locale = "en"
|
|
|
658
670
|
revision = 4
|
|
659
671
|
translations = {}
|
|
660
672
|
|
|
673
|
+
[documents."skill.godot-code-change"]
|
|
674
|
+
source = "locales/en/.mustflow/skills/godot-code-change/SKILL.md"
|
|
675
|
+
source_locale = "en"
|
|
676
|
+
revision = 1
|
|
677
|
+
translations = {}
|
|
678
|
+
|
|
661
679
|
[documents."skill.hono-code-change"]
|
|
662
680
|
source = "locales/en/.mustflow/skills/hono-code-change/SKILL.md"
|
|
663
681
|
source_locale = "en"
|
|
664
|
-
revision =
|
|
682
|
+
revision = 2
|
|
665
683
|
translations = {}
|
|
666
684
|
|
|
667
685
|
[documents."skill.html-code-change"]
|
|
@@ -688,6 +706,12 @@ source_locale = "en"
|
|
|
688
706
|
revision = 2
|
|
689
707
|
translations = {}
|
|
690
708
|
|
|
709
|
+
[documents."skill.vue-code-change"]
|
|
710
|
+
source = "locales/en/.mustflow/skills/vue-code-change/SKILL.md"
|
|
711
|
+
source_locale = "en"
|
|
712
|
+
revision = 1
|
|
713
|
+
translations = {}
|
|
714
|
+
|
|
691
715
|
[documents."skill.python-code-change"]
|
|
692
716
|
source = "locales/en/.mustflow/skills/python-code-change/SKILL.md"
|
|
693
717
|
source_locale = "en"
|
|
@@ -739,7 +763,7 @@ translations = {}
|
|
|
739
763
|
[documents."skill.svelte-code-change"]
|
|
740
764
|
source = "locales/en/.mustflow/skills/svelte-code-change/SKILL.md"
|
|
741
765
|
source_locale = "en"
|
|
742
|
-
revision =
|
|
766
|
+
revision = 3
|
|
743
767
|
translations = {}
|
|
744
768
|
|
|
745
769
|
[documents."skill.tailwind-code-change"]
|