mustflow 2.112.10 → 2.112.13

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 (32) hide show
  1. package/dist/cli/commands/contract-lint.js +3 -13
  2. package/dist/cli/commands/impact.js +2 -12
  3. package/dist/cli/commands/init.js +1 -13
  4. package/dist/cli/commands/onboard.js +3 -13
  5. package/dist/cli/commands/version-sources.js +2 -12
  6. package/dist/cli/lib/agent-context.js +2 -1
  7. package/dist/core/preferences.js +79 -0
  8. package/dist/core/repo-version-source.js +9 -18
  9. package/package.json +1 -1
  10. package/templates/default/i18n.toml +19 -19
  11. package/templates/default/locales/en/.mustflow/docs/agent-workflow.md +10 -4
  12. package/templates/default/locales/en/.mustflow/skills/INDEX.md +4 -4
  13. package/templates/default/locales/en/.mustflow/skills/async-timing-boundary-review/SKILL.md +19 -5
  14. package/templates/default/locales/en/.mustflow/skills/backend-log-evidence-review/SKILL.md +10 -3
  15. package/templates/default/locales/en/.mustflow/skills/cache-integrity-review/SKILL.md +63 -21
  16. package/templates/default/locales/en/.mustflow/skills/concurrency-invariant-review/SKILL.md +13 -3
  17. package/templates/default/locales/en/.mustflow/skills/cross-platform-filesystem-safety/SKILL.md +10 -9
  18. package/templates/default/locales/en/.mustflow/skills/dependency-upgrade-review/SKILL.md +8 -3
  19. package/templates/default/locales/en/.mustflow/skills/memory-lifetime-review/SKILL.md +19 -3
  20. package/templates/default/locales/en/.mustflow/skills/observability-debuggability-review/SKILL.md +31 -21
  21. package/templates/default/locales/en/.mustflow/skills/race-condition-review/SKILL.md +38 -25
  22. package/templates/default/locales/en/.mustflow/skills/repro-first-debug/SKILL.md +43 -10
  23. package/templates/default/locales/en/.mustflow/skills/routes.toml +4 -4
  24. package/templates/default/locales/en/.mustflow/skills/security-flow-review/SKILL.md +19 -4
  25. package/templates/default/locales/en/.mustflow/skills/security-privacy-review/SKILL.md +8 -3
  26. package/templates/default/locales/en/AGENTS.md +9 -1
  27. package/templates/default/locales/es/AGENTS.md +2 -0
  28. package/templates/default/locales/fr/AGENTS.md +2 -0
  29. package/templates/default/locales/hi/AGENTS.md +2 -0
  30. package/templates/default/locales/ko/AGENTS.md +3 -1
  31. package/templates/default/locales/zh/AGENTS.md +2 -0
  32. package/templates/default/manifest.toml +1 -1
@@ -1,13 +1,11 @@
1
- import { existsSync } from 'node:fs';
2
- import path from 'node:path';
3
1
  import { lintCommandContract } from '../../core/contract-lint.js';
4
- import { readCommandContract, isRecord } from '../../core/config-loading.js';
2
+ import { readCommandContract } from '../../core/config-loading.js';
3
+ import { readEffectivePreferencesToml } from '../../core/preferences.js';
5
4
  import { releaseVersioningIsEnabled } from '../../core/version-sources.js';
6
5
  import { printUsageError, renderHelp } from '../lib/cli-output.js';
7
6
  import { t } from '../lib/i18n.js';
8
7
  import { formatCliOptionParseError, hasCliOptionToken, hasParsedCliOption, parseCliOptions, } from '../lib/option-parser.js';
9
8
  import { resolveMustflowRoot } from '../lib/project-root.js';
10
- import { readMustflowTomlFile } from '../lib/toml.js';
11
9
  const CONTRACT_LINT_SCHEMA_VERSION = '1';
12
10
  const CONTRACT_LINT_OPTIONS = [
13
11
  { name: '--coverage', kind: 'boolean' },
@@ -31,14 +29,6 @@ export function getContractLintHelp(lang = 'en') {
31
29
  ],
32
30
  }, lang);
33
31
  }
34
- function readPreferences(projectRoot) {
35
- const preferencesPath = path.join(projectRoot, '.mustflow', 'config', 'preferences.toml');
36
- if (!existsSync(preferencesPath)) {
37
- return undefined;
38
- }
39
- const preferences = readMustflowTomlFile(projectRoot, '.mustflow/config/preferences.toml');
40
- return isRecord(preferences) ? preferences : undefined;
41
- }
42
32
  function createContractLintOutput(projectRoot, coverage, suggest) {
43
33
  return {
44
34
  schema_version: CONTRACT_LINT_SCHEMA_VERSION,
@@ -48,7 +38,7 @@ function createContractLintOutput(projectRoot, coverage, suggest) {
48
38
  coverage,
49
39
  suggest,
50
40
  projectRoot,
51
- releaseVersioningEnabled: releaseVersioningIsEnabled(readPreferences(projectRoot)),
41
+ releaseVersioningEnabled: releaseVersioningIsEnabled(readEffectivePreferencesToml(projectRoot)),
52
42
  }),
53
43
  };
54
44
  }
@@ -1,12 +1,11 @@
1
1
  import { createChangeClassificationReport } from '../../core/change-classification.js';
2
+ import { readEffectivePreferencesToml } from '../../core/preferences.js';
2
3
  import { summarizeVersionImpact } from '../../core/version-impact.js';
3
4
  import { printUsageError, renderHelp } from '../lib/cli-output.js';
4
- import { isRecord } from '../lib/command-contract.js';
5
5
  import { requireGitChangedFiles } from '../lib/git-changes.js';
6
6
  import { t } from '../lib/i18n.js';
7
7
  import { formatCliOptionParseError, hasCliOptionToken, hasParsedCliOption, parseCliOptions, } from '../lib/option-parser.js';
8
8
  import { resolveMustflowRoot } from '../lib/project-root.js';
9
- import { readMustflowTomlFile } from '../lib/toml.js';
10
9
  import { detectVersionSources, releaseVersioningIsEnabled, } from '../../core/version-sources.js';
11
10
  const IMPACT_SCHEMA_VERSION = '1';
12
11
  const IMPACT_OPTIONS = [
@@ -38,15 +37,6 @@ function parseImpactArgs(args) {
38
37
  error: parsed.error,
39
38
  };
40
39
  }
41
- function readPreferences(projectRoot) {
42
- try {
43
- const preferences = readMustflowTomlFile(projectRoot, '.mustflow/config/preferences.toml');
44
- return isRecord(preferences) ? preferences : undefined;
45
- }
46
- catch {
47
- return undefined;
48
- }
49
- }
50
40
  function createImpactOutput(projectRoot, parsed) {
51
41
  const source = parsed.changed ? 'changed' : 'paths';
52
42
  const files = parsed.changed ? requireGitChangedFiles(projectRoot) : parsed.paths;
@@ -58,7 +48,7 @@ function createImpactOutput(projectRoot, parsed) {
58
48
  mustflow_root: projectRoot,
59
49
  source,
60
50
  files: classificationReport.files,
61
- versioning_enabled: releaseVersioningIsEnabled(readPreferences(projectRoot)),
51
+ versioning_enabled: releaseVersioningIsEnabled(readEffectivePreferencesToml(projectRoot)),
62
52
  version_sources: versionSources,
63
53
  classification_summary: classificationReport.summary,
64
54
  version_impact: summarizeVersionImpact(classificationReport, versionSources),
@@ -158,7 +158,7 @@ const VERIFICATION_SELECTION_BOOLEAN_FIELDS = new Set([
158
158
  ]);
159
159
  const TEST_AUTHORING_BOOLEAN_FIELDS = new Set(['prefer_existing_tests', 'require_new_test_rationale']);
160
160
  function createPreferenceOverride(key, value, reporter, lang) {
161
- if (key === 'git.auto_stage' || key === 'git.auto_commit') {
161
+ if (key === 'git.auto_stage' || key === 'git.auto_commit' || key === 'git.auto_push') {
162
162
  const parsed = parseBoolean(value);
163
163
  if (parsed === undefined) {
164
164
  reporter.stderr(t(lang, 'init.error.invalidPreferenceValue', { key, value }));
@@ -171,18 +171,6 @@ function createPreferenceOverride(key, value, reporter, lang) {
171
171
  renderedValue: String(parsed),
172
172
  };
173
173
  }
174
- if (key === 'git.auto_push') {
175
- if (value !== 'false') {
176
- reporter.stderr(t(lang, 'init.error.invalidPreferenceValue', { key, value }));
177
- return undefined;
178
- }
179
- return {
180
- key,
181
- section: 'git',
182
- field: 'auto_push',
183
- renderedValue: 'false',
184
- };
185
- }
186
174
  if (key === 'git.commit_message.language') {
187
175
  if (!isSupportedLanguagePreference(value)) {
188
176
  reporter.stderr(t(lang, 'init.error.invalidPreferenceValue', { key, value }));
@@ -1,13 +1,11 @@
1
- import { existsSync } from 'node:fs';
2
- import path from 'node:path';
3
1
  import { lintCommandContract, } from '../../core/contract-lint.js';
4
- import { isRecord, readCommandContract, } from '../../core/config-loading.js';
2
+ import { readCommandContract } from '../../core/config-loading.js';
3
+ import { readEffectivePreferencesToml } from '../../core/preferences.js';
5
4
  import { releaseVersioningIsEnabled } from '../../core/version-sources.js';
6
5
  import { printUsageError, renderHelp } from '../lib/cli-output.js';
7
6
  import { t } from '../lib/i18n.js';
8
7
  import { formatCliOptionParseError, hasCliOptionToken, hasParsedCliOption, parseCliOptions, } from '../lib/option-parser.js';
9
8
  import { resolveMustflowRoot } from '../lib/project-root.js';
10
- import { readMustflowTomlFile } from '../lib/toml.js';
11
9
  const ONBOARD_COMMANDS_SCHEMA_VERSION = '1';
12
10
  const COMMAND_CONTRACT_PATH = '.mustflow/config/commands.toml';
13
11
  const ONBOARD_COMMANDS_OPTIONS = [
@@ -28,14 +26,6 @@ export function getOnboardHelp(lang = 'en') {
28
26
  ],
29
27
  }, lang);
30
28
  }
31
- function readPreferences(projectRoot) {
32
- const preferencesPath = path.join(projectRoot, '.mustflow', 'config', 'preferences.toml');
33
- if (!existsSync(preferencesPath)) {
34
- return undefined;
35
- }
36
- const preferences = readMustflowTomlFile(projectRoot, '.mustflow/config/preferences.toml');
37
- return isRecord(preferences) ? preferences : undefined;
38
- }
39
29
  function countSuggestionsByKind(suggestions, sourceKind) {
40
30
  return suggestions.filter((suggestion) => suggestion.sourceKind === sourceKind).length;
41
31
  }
@@ -56,7 +46,7 @@ function createOnboardCommandsOutput(projectRoot) {
56
46
  const report = lintCommandContract(readCommandContract(projectRoot), {
57
47
  suggest: true,
58
48
  projectRoot,
59
- releaseVersioningEnabled: releaseVersioningIsEnabled(readPreferences(projectRoot)),
49
+ releaseVersioningEnabled: releaseVersioningIsEnabled(readEffectivePreferencesToml(projectRoot)),
60
50
  });
61
51
  const suggestions = report.suggestions ?? [];
62
52
  return {
@@ -1,9 +1,8 @@
1
+ import { readEffectivePreferencesToml } from '../../core/preferences.js';
1
2
  import { printUsageError, renderHelp } from '../lib/cli-output.js';
2
- import { isRecord } from '../lib/command-contract.js';
3
3
  import { t } from '../lib/i18n.js';
4
4
  import { formatCliOptionParseError, hasCliOptionToken, hasParsedCliOption, parseCliOptions, } from '../lib/option-parser.js';
5
5
  import { resolveMustflowRoot } from '../lib/project-root.js';
6
- import { readMustflowTomlFile } from '../lib/toml.js';
7
6
  import { detectVersionSources, releaseVersioningIsEnabled, } from '../../core/version-sources.js';
8
7
  const VERSION_SOURCES_SCHEMA_VERSION = '1';
9
8
  const VERSION_SOURCES_OPTIONS = [
@@ -24,17 +23,8 @@ export function getVersionSourcesHelp(lang = 'en') {
24
23
  ],
25
24
  }, lang);
26
25
  }
27
- function readPreferences(projectRoot) {
28
- try {
29
- const preferences = readMustflowTomlFile(projectRoot, '.mustflow/config/preferences.toml');
30
- return isRecord(preferences) ? preferences : undefined;
31
- }
32
- catch {
33
- return undefined;
34
- }
35
- }
36
26
  function getVersionSourcesOutput(projectRoot) {
37
- const preferences = readPreferences(projectRoot);
27
+ const preferences = readEffectivePreferencesToml(projectRoot);
38
28
  return {
39
29
  schema_version: VERSION_SOURCES_SCHEMA_VERSION,
40
30
  command: 'version-sources',
@@ -10,6 +10,7 @@ import { MUSTFLOW_JSON_MAX_BYTES, readMustflowTextFile, readMustflowTextFileIfEx
10
10
  import { createRunPlan } from './run-plan.js';
11
11
  import { readMustflowTomlFile } from './toml.js';
12
12
  import { normalizeTechnologyPreferencesTable, TECHNOLOGY_CONFIG_RELATIVE_PATH, } from '../../core/technology-preferences.js';
13
+ import { readEffectivePreferencesToml } from '../../core/preferences.js';
13
14
  import { isPromptCacheStableLeafSkillSurface, measurePromptCacheReferenceBlockBytes, renderPromptCacheReferenceBlock, } from '../../core/prompt-cache-rendering.js';
14
15
  import { resolveSkillRoutes } from '../../core/skill-route-resolution.js';
15
16
  const CONTEXT_SCHEMA_VERSION = '1';
@@ -1487,7 +1488,7 @@ export async function getPromptCacheProfileContext(projectRoot, profile, options
1487
1488
  }
1488
1489
  export function getAgentContext(projectRoot) {
1489
1490
  const mustflow = readTomlTableIfExists(projectRoot, MUSTFLOW_RELATIVE_PATH);
1490
- const preferences = readTomlTableIfExists(projectRoot, PREFERENCES_RELATIVE_PATH);
1491
+ const preferences = readEffectivePreferencesToml(projectRoot);
1491
1492
  const authority = isRecord(mustflow?.authority) ? mustflow.authority : undefined;
1492
1493
  const capabilities = isRecord(mustflow?.capabilities) ? mustflow.capabilities : undefined;
1493
1494
  const readOrder = mustflow ? readStringArray(mustflow, 'read_order') ?? [] : [];
@@ -0,0 +1,79 @@
1
+ import { existsSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { isRecord, readMustflowOwnedTomlFile, } from './config-loading.js';
4
+ export const PREFERENCES_CONFIG_RELATIVE_PATH = '.mustflow/config/preferences.toml';
5
+ function hasMustflowMarker(directoryPath) {
6
+ return (existsSync(path.join(directoryPath, '.mustflow', 'config', 'mustflow.toml')) ||
7
+ existsSync(path.join(directoryPath, '.mustflow', 'config', 'commands.toml')));
8
+ }
9
+ function preferencesPath(projectRoot) {
10
+ return path.join(projectRoot, ...PREFERENCES_CONFIG_RELATIVE_PATH.split('/'));
11
+ }
12
+ function readPreferencesAtRoot(projectRoot) {
13
+ if (!existsSync(preferencesPath(projectRoot))) {
14
+ return undefined;
15
+ }
16
+ const parsed = readMustflowOwnedTomlFile(projectRoot, PREFERENCES_CONFIG_RELATIVE_PATH);
17
+ return isRecord(parsed) ? parsed : undefined;
18
+ }
19
+ function parentMustflowRoots(projectRoot) {
20
+ const roots = [];
21
+ let current = path.dirname(path.resolve(projectRoot));
22
+ while (true) {
23
+ if (hasMustflowMarker(current)) {
24
+ roots.push(current);
25
+ }
26
+ const parent = path.dirname(current);
27
+ if (parent === current) {
28
+ return roots;
29
+ }
30
+ current = parent;
31
+ }
32
+ }
33
+ function clonePreferenceValue(value) {
34
+ if (Array.isArray(value)) {
35
+ return value.map((entry) => clonePreferenceValue(entry));
36
+ }
37
+ if (isRecord(value)) {
38
+ return mergePreferenceTables({}, value);
39
+ }
40
+ return value;
41
+ }
42
+ function mergePreferenceTables(base, override) {
43
+ const merged = {};
44
+ for (const [key, value] of Object.entries(base)) {
45
+ merged[key] = clonePreferenceValue(value);
46
+ }
47
+ for (const [key, value] of Object.entries(override)) {
48
+ const existing = merged[key];
49
+ if (isRecord(existing) && isRecord(value)) {
50
+ merged[key] = mergePreferenceTables(existing, value);
51
+ }
52
+ else {
53
+ merged[key] = clonePreferenceValue(value);
54
+ }
55
+ }
56
+ return merged;
57
+ }
58
+ export function readLocalPreferencesToml(projectRoot) {
59
+ return readPreferencesAtRoot(projectRoot);
60
+ }
61
+ /**
62
+ * mf:anchor core.preferences.inheritance
63
+ * purpose: Resolve low-authority workflow preferences across nested mustflow roots.
64
+ * search: preferences inheritance, parent workspace defaults, git auto push, release versioning
65
+ * invariant: Parent preferences are defaults only; child-local values override field by field, and command contracts are never inherited here.
66
+ * risk: config
67
+ */
68
+ export function readEffectivePreferencesToml(projectRoot) {
69
+ const roots = [...parentMustflowRoots(projectRoot).reverse(), path.resolve(projectRoot)];
70
+ let effective;
71
+ for (const root of roots) {
72
+ const preferences = readPreferencesAtRoot(root);
73
+ if (!preferences) {
74
+ continue;
75
+ }
76
+ effective = effective ? mergePreferenceTables(effective, preferences) : mergePreferenceTables({}, preferences);
77
+ }
78
+ return effective;
79
+ }
@@ -1,7 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { existsSync } from 'node:fs';
3
2
  import path from 'node:path';
4
- import { isRecord, readMustflowOwnedTomlFile } from './config-loading.js';
3
+ import { readEffectivePreferencesToml } from './preferences.js';
5
4
  import { detectVersionSources, releaseVersioningIsEnabled, VERSIONING_CONFIG_PATH, } from './version-sources.js';
6
5
  export const REPO_VERSION_SOURCE_PACK_ID = 'repo';
7
6
  export const REPO_VERSION_SOURCE_SCRIPT_ID = 'version-source';
@@ -10,21 +9,6 @@ export const REPO_VERSION_SOURCE_PREFERENCES_PATH = '.mustflow/config/preference
10
9
  function sha256(value) {
11
10
  return `sha256:${createHash('sha256').update(value).digest('hex')}`;
12
11
  }
13
- function readPreferences(projectRoot, issues) {
14
- const preferencesPath = path.join(projectRoot, ...REPO_VERSION_SOURCE_PREFERENCES_PATH.split('/'));
15
- if (!existsSync(preferencesPath)) {
16
- return undefined;
17
- }
18
- try {
19
- const parsed = readMustflowOwnedTomlFile(projectRoot, REPO_VERSION_SOURCE_PREFERENCES_PATH);
20
- return isRecord(parsed) ? parsed : undefined;
21
- }
22
- catch (error) {
23
- const message = error instanceof Error ? error.message : String(error);
24
- issues.push(`Could not read ${REPO_VERSION_SOURCE_PREFERENCES_PATH}: ${message}`);
25
- return undefined;
26
- }
27
- }
28
12
  function countSources(sources) {
29
13
  return {
30
14
  sources: sources.length,
@@ -40,7 +24,14 @@ function createInputHash(reportInput) {
40
24
  export function inspectRepoVersionSource(projectRoot) {
41
25
  const root = path.resolve(projectRoot);
42
26
  const issues = [];
43
- const preferences = readPreferences(root, issues);
27
+ let preferences;
28
+ try {
29
+ preferences = readEffectivePreferencesToml(root);
30
+ }
31
+ catch (error) {
32
+ const message = error instanceof Error ? error.message : String(error);
33
+ issues.push(`Could not read local or inherited ${REPO_VERSION_SOURCE_PREFERENCES_PATH}: ${message}`);
34
+ }
44
35
  const versioningEnabled = releaseVersioningIsEnabled(preferences);
45
36
  const sources = detectVersionSources(root);
46
37
  const findings = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mustflow",
3
- "version": "2.112.10",
3
+ "version": "2.112.13",
4
4
  "description": "Agent workflow documents and CLI for mustflow repository roots.",
5
5
  "type": "module",
6
6
  "license": "MIT-0",
@@ -10,12 +10,12 @@ status_values = ["current", "stale", "needs_review", "missing"]
10
10
  [documents."agents.root"]
11
11
  source = "locales/en/AGENTS.md"
12
12
  source_locale = "en"
13
- revision = 20
14
- translations.ko = { path = "locales/ko/AGENTS.md", source_revision = 20, status = "current" }
15
- translations.zh = { path = "locales/zh/AGENTS.md", source_revision = 11, status = "needs_review" }
16
- translations.es = { path = "locales/es/AGENTS.md", source_revision = 11, status = "needs_review" }
17
- translations.fr = { path = "locales/fr/AGENTS.md", source_revision = 11, status = "needs_review" }
18
- translations.hi = { path = "locales/hi/AGENTS.md", source_revision = 11, status = "needs_review" }
13
+ revision = 21
14
+ translations.ko = { path = "locales/ko/AGENTS.md", source_revision = 21, status = "current" }
15
+ translations.zh = { path = "locales/zh/AGENTS.md", source_revision = 21, status = "needs_review" }
16
+ translations.es = { path = "locales/es/AGENTS.md", source_revision = 21, status = "needs_review" }
17
+ translations.fr = { path = "locales/fr/AGENTS.md", source_revision = 21, status = "needs_review" }
18
+ translations.hi = { path = "locales/hi/AGENTS.md", source_revision = 21, status = "needs_review" }
19
19
 
20
20
  [documents."context.index"]
21
21
  source = "locales/en/.mustflow/context/INDEX.md"
@@ -40,7 +40,7 @@ translations.hi = { path = "locales/hi/.mustflow/context/PROJECT.md", source_rev
40
40
  [documents."docs.agent-workflow"]
41
41
  source = "locales/en/.mustflow/docs/agent-workflow.md"
42
42
  source_locale = "en"
43
- revision = 28
43
+ revision = 29
44
44
  translations.ko = { path = "locales/ko/.mustflow/docs/agent-workflow.md", source_revision = 23, status = "needs_review" }
45
45
  translations.zh = { path = "locales/zh/.mustflow/docs/agent-workflow.md", source_revision = 18, status = "needs_review" }
46
46
  translations.es = { path = "locales/es/.mustflow/docs/agent-workflow.md", source_revision = 18, status = "needs_review" }
@@ -224,7 +224,7 @@ translations = {}
224
224
  [documents."skill.memory-lifetime-review"]
225
225
  source = "locales/en/.mustflow/skills/memory-lifetime-review/SKILL.md"
226
226
  source_locale = "en"
227
- revision = 1
227
+ revision = 2
228
228
  translations = {}
229
229
 
230
230
  [documents."skill.desktop-memory-footprint-review"]
@@ -380,7 +380,7 @@ translations = {}
380
380
  [documents."skill.cache-integrity-review"]
381
381
  source = "locales/en/.mustflow/skills/cache-integrity-review/SKILL.md"
382
382
  source_locale = "en"
383
- revision = 2
383
+ revision = 3
384
384
  translations = {}
385
385
 
386
386
  [documents."skill.quadratic-scan-review"]
@@ -398,19 +398,19 @@ translations = {}
398
398
  [documents."skill.race-condition-review"]
399
399
  source = "locales/en/.mustflow/skills/race-condition-review/SKILL.md"
400
400
  source_locale = "en"
401
- revision = 1
401
+ revision = 3
402
402
  translations = {}
403
403
 
404
404
  [documents."skill.async-timing-boundary-review"]
405
405
  source = "locales/en/.mustflow/skills/async-timing-boundary-review/SKILL.md"
406
406
  source_locale = "en"
407
- revision = 1
407
+ revision = 2
408
408
  translations = {}
409
409
 
410
410
  [documents."skill.concurrency-invariant-review"]
411
411
  source = "locales/en/.mustflow/skills/concurrency-invariant-review/SKILL.md"
412
412
  source_locale = "en"
413
- revision = 1
413
+ revision = 2
414
414
  translations = {}
415
415
 
416
416
  [documents."skill.failure-integrity-review"]
@@ -422,13 +422,13 @@ translations = {}
422
422
  [documents."skill.backend-log-evidence-review"]
423
423
  source = "locales/en/.mustflow/skills/backend-log-evidence-review/SKILL.md"
424
424
  source_locale = "en"
425
- revision = 3
425
+ revision = 4
426
426
  translations = {}
427
427
 
428
428
  [documents."skill.observability-debuggability-review"]
429
429
  source = "locales/en/.mustflow/skills/observability-debuggability-review/SKILL.md"
430
430
  source_locale = "en"
431
- revision = 2
431
+ revision = 3
432
432
  translations = {}
433
433
 
434
434
  [documents."skill.incident-triage-review"]
@@ -595,7 +595,7 @@ translations = {}
595
595
  [documents."skill.dependency-upgrade-review"]
596
596
  source = "locales/en/.mustflow/skills/dependency-upgrade-review/SKILL.md"
597
597
  source_locale = "en"
598
- revision = 5
598
+ revision = 6
599
599
  translations = {}
600
600
 
601
601
  [documents."skill.version-freshness-check"]
@@ -679,7 +679,7 @@ translations = {}
679
679
  [documents."skill.security-flow-review"]
680
680
  source = "locales/en/.mustflow/skills/security-flow-review/SKILL.md"
681
681
  source_locale = "en"
682
- revision = 1
682
+ revision = 2
683
683
  translations = {}
684
684
 
685
685
  [documents."skill.config-env-change"]
@@ -961,7 +961,7 @@ translations = {}
961
961
  [documents."skill.cross-platform-filesystem-safety"]
962
962
  source = "locales/en/.mustflow/skills/cross-platform-filesystem-safety/SKILL.md"
963
963
  source_locale = "en"
964
- revision = 6
964
+ revision = 7
965
965
  translations = {}
966
966
 
967
967
  [documents."skill.pure-core-imperative-shell"]
@@ -1116,7 +1116,7 @@ translations = {}
1116
1116
  [documents."skill.repro-first-debug"]
1117
1117
  source = "locales/en/.mustflow/skills/repro-first-debug/SKILL.md"
1118
1118
  source_locale = "en"
1119
- revision = 3
1119
+ revision = 5
1120
1120
  translations = {}
1121
1121
 
1122
1122
  [documents."skill.source-freshness-check"]
@@ -1164,7 +1164,7 @@ translations = {}
1164
1164
  [documents."skill.security-privacy-review"]
1165
1165
  source = "locales/en/.mustflow/skills/security-privacy-review/SKILL.md"
1166
1166
  source_locale = "en"
1167
- revision = 23
1167
+ revision = 24
1168
1168
  translations = {}
1169
1169
 
1170
1170
  [documents."skill.security-regression-tests"]
@@ -2,7 +2,7 @@
2
2
  mustflow_doc: docs.agent-workflow
3
3
  locale: en
4
4
  canonical: true
5
- revision: 28
5
+ revision: 29
6
6
  lifecycle: mustflow-owned
7
7
  authority: workflow-policy
8
8
  ---
@@ -28,7 +28,7 @@ mustflow documents have specific, narrow roles. Do not move a rule into a lower-
28
28
  | `.mustflow/docs/agent-workflow.md` | Shared workflow policy for reading, editing, verifying, reporting, and failure handling. | Expands `AGENTS.md`; does not define executable commands. | mustflow-owned Markdown. |
29
29
  | `.mustflow/config/mustflow.toml` | Machine-readable workflow configuration, document roots, protection, budget, approval, retention, and refresh settings. | Configuration source for mustflow behavior. | mustflow-owned TOML. |
30
30
  | `.mustflow/config/commands.toml` | Command intent contract. | Sole source granting project command execution through configured intents. | Repository-local TOML, edited when command contracts change. |
31
- | `.mustflow/config/preferences.toml` | Repository-level defaults for style, language, Git suggestions, testing tendency, verification selection, and version-impact handling. | Lower-authority preferences; not permissions. | Repository-local TOML, user-customizable. |
31
+ | `.mustflow/config/preferences.toml` | Repository-level defaults for style, language, Git suggestions, testing tendency, verification selection, and version-impact handling. | Lower-authority preferences; not permissions. Child repositories without local preferences may inherit the nearest parent mustflow preferences as defaults. | Repository-local TOML, user-customizable. |
32
32
  | `.mustflow/context/INDEX.md` | Router for task-specific context files. | Selects optional context only; not a policy manual. | mustflow-owned Markdown. |
33
33
  | `.mustflow/context/PROJECT.md` | Cautious project facts, unknowns, and domain conventions. | Contextual reference below user instructions, code, tests, commands, and configured policies. | User-editable context. |
34
34
  | `.mustflow/skills/router.toml` | Stable compact route taxonomy and fallback rules for prompt-cache-friendly first-pass skill selection. | Selection kernel only; procedure detail remains in `SKILL.md`. | mustflow-owned TOML. |
@@ -98,6 +98,12 @@ Treat user instructions, local files, command contracts, and generated reports a
98
98
  - Direct user instructions take priority.
99
99
  - The nearest `AGENTS.md` takes precedence over broader parent rules.
100
100
  - `.mustflow/config/preferences.toml` contains defaults, not mandatory requirements.
101
+ - If a child repository has no local `.mustflow/config/preferences.toml`, apply the nearest parent
102
+ mustflow root's preferences as inherited defaults. Inherited preferences include `[git]`,
103
+ `[git.commit_message]`, `[release.versioning]`, verification, testing, language, reporting, and
104
+ other preference sections. Child-local preference values override inherited values field by field.
105
+ - Never inherit `.mustflow/config/commands.toml`; command execution authority stays with the nearest
106
+ repository command contract.
101
107
  - Generated files such as `REPO_MAP.md`, `.mustflow/cache/**`, and `.mustflow/state/**` may become stale.
102
108
  - Compacted summaries are derived representations of state. Current code, configuration, command records, and current user instructions override them.
103
109
 
@@ -136,7 +142,7 @@ Do not collapse every instruction into a single priority list. Resolve conflicts
136
142
  - Repository work rules: use the nearest `AGENTS.md` plus `.mustflow/config/*.toml`.
137
143
  - Command execution: `.mustflow/config/commands.toml` is the project command contract.
138
144
  - Verification evidence: `mf run` receipts and current files outrank direct host shell output.
139
- - Context and preferences: `.mustflow/context/*`, `preferences.toml`, and generated maps are lower-authority defaults.
145
+ - Context and preferences: `.mustflow/context/*`, local or inherited `preferences.toml`, and generated maps are lower-authority defaults.
140
146
  - Session and cache state: host summaries, `.mustflow/cache/**`, and `.mustflow/state/**` never override current files or current user instructions.
141
147
 
142
148
  Allowed action sets narrow by intersection. Denied actions, approval requirements, privacy rules, and destructive-command rules accumulate. When the effective rule is unclear, stop and report the conflict instead of guessing.
@@ -214,7 +220,7 @@ Git operations that modify state or history are denied by default.
214
220
  - `git.auto_commit = false`: do not commit without a user request.
215
221
  - `git.auto_push = false`: do not push without a user request.
216
222
 
217
- These values are repository preferences, not permissions. They do not override direct user instructions, `.mustflow/config/commands.toml`, or approval policy in `.mustflow/config/mustflow.toml`. In particular, `git.auto_commit = true` does not grant push permission, and `git.auto_push = true` cannot be enabled through `mf init`.
223
+ These values are repository preferences, not permissions. They do not override direct user instructions, `.mustflow/config/commands.toml`, or approval policy in `.mustflow/config/mustflow.toml`. In particular, `git.auto_commit = true` does not grant push permission, and `git.auto_push = true` still requires an explicit user request and any host approval required for push operations.
218
224
 
219
225
  ## Version Impact Policy
220
226