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.
Files changed (34) hide show
  1. package/README.md +5 -2
  2. package/dist/cli/commands/flow.js +93 -0
  3. package/dist/cli/commands/run/executor.js +28 -3
  4. package/dist/cli/commands/run/windows-command-script.js +23 -0
  5. package/dist/cli/i18n/en.js +11 -0
  6. package/dist/cli/i18n/es.js +11 -0
  7. package/dist/cli/i18n/fr.js +11 -0
  8. package/dist/cli/i18n/hi.js +11 -0
  9. package/dist/cli/i18n/ko.js +11 -0
  10. package/dist/cli/i18n/zh.js +11 -0
  11. package/dist/cli/index.js +1 -0
  12. package/dist/cli/lib/active-command-lock.js +4 -0
  13. package/dist/cli/lib/command-registry.js +7 -0
  14. package/dist/cli/lib/repo-flow-frontmatter.js +35 -0
  15. package/dist/cli/lib/repo-flow.js +209 -0
  16. package/dist/cli/lib/repo-map.js +3 -0
  17. package/dist/cli/lib/run-plan.js +8 -4
  18. package/dist/cli/lib/validation/constants.js +10 -0
  19. package/dist/cli/lib/validation/index.js +54 -1
  20. package/dist/core/generated-boundary.js +1 -0
  21. package/package.json +2 -1
  22. package/templates/default/i18n.toml +30 -6
  23. package/templates/default/locales/en/.mustflow/skills/INDEX.md +29 -6
  24. package/templates/default/locales/en/.mustflow/skills/astro-code-change/SKILL.md +95 -23
  25. package/templates/default/locales/en/.mustflow/skills/axum-code-change/SKILL.md +219 -0
  26. package/templates/default/locales/en/.mustflow/skills/babylon-code-change/SKILL.md +318 -0
  27. package/templates/default/locales/en/.mustflow/skills/bun-code-change/SKILL.md +27 -12
  28. package/templates/default/locales/en/.mustflow/skills/elysia-code-change/SKILL.md +74 -20
  29. package/templates/default/locales/en/.mustflow/skills/godot-code-change/SKILL.md +272 -0
  30. package/templates/default/locales/en/.mustflow/skills/hono-code-change/SKILL.md +37 -23
  31. package/templates/default/locales/en/.mustflow/skills/routes.toml +28 -4
  32. package/templates/default/locales/en/.mustflow/skills/svelte-code-change/SKILL.md +65 -40
  33. package/templates/default/locales/en/.mustflow/skills/vue-code-change/SKILL.md +305 -0
  34. 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
+ }
@@ -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.'],
@@ -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 shouldUseShellForArgvExecutable(executablePath) {
51
- return process.platform === 'win32' && executablePath.toLowerCase().endsWith('.cmd');
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: shouldUseShellForArgvExecutable(localBinExecutable),
79
+ shell: false,
80
+ windowsCommandScript: isResolvedWindowsCommandScript(localBinExecutable),
78
81
  };
79
82
  }
80
83
  return {
81
84
  executable: command,
82
85
  args,
83
- shell: shouldUseShellForArgvExecutable(command),
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.22",
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 = 189
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 = 4
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 = 1
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 = 2
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 = 1
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 = 2
766
+ revision = 3
743
767
  translations = {}
744
768
 
745
769
  [documents."skill.tailwind-code-change"]