mustflow 2.22.9 → 2.22.12

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.
@@ -1,7 +1,7 @@
1
1
  import { printUsageError, renderHelp } from '../lib/cli-output.js';
2
2
  import { t } from '../lib/i18n.js';
3
3
  import { resolveMustflowRoot } from '../lib/project-root.js';
4
- import { checkMustflowProjectReport, describeCheckIssues } from '../lib/validation.js';
4
+ import { checkMustflowProjectReport } from '../lib/validation.js';
5
5
  export function getCheckHelp(lang = 'en') {
6
6
  return renderHelp({
7
7
  usage: 'mf check [options]',
@@ -51,7 +51,7 @@ export function runCheck(args, reporter, lang = 'en') {
51
51
  issues,
52
52
  warningCount: warnings.length,
53
53
  warnings,
54
- issueDetails: describeCheckIssues([...issues, ...warnings]),
54
+ issueDetails: report.issueDetails,
55
55
  }, null, 2));
56
56
  return ok ? 0 : 1;
57
57
  }
@@ -1,11 +1,9 @@
1
1
  import { printUsageError, renderCliError, renderHelp } from '../lib/cli-output.js';
2
+ import { isRecord } from '../lib/command-contract.js';
2
3
  import { t } from '../lib/i18n.js';
3
4
  import { readMustflowTextFileIfExists } from '../lib/mustflow-read.js';
4
5
  import { resolveMustflowRoot } from '../lib/project-root.js';
5
6
  import { readMustflowTomlFile } from '../lib/toml.js';
6
- function isRecord(value) {
7
- return typeof value === 'object' && value !== null && !Array.isArray(value);
8
- }
9
7
  function readTextIfExists(projectRoot, relativePath) {
10
8
  return readMustflowTextFileIfExists(projectRoot, relativePath) ?? undefined;
11
9
  }
@@ -0,0 +1,33 @@
1
+ import path from 'node:path';
2
+ import { createStateRunId } from '../../../core/atomic-state-write.js';
3
+ const RUN_STATE_DIR = path.join('.mustflow', 'state', 'runs');
4
+ const LATEST_RUN_RECEIPT_PATH = path.join(RUN_STATE_DIR, 'latest.json');
5
+ export function createVerifyRunStatePaths(projectRoot) {
6
+ const runDir = toPosixPath(path.join(RUN_STATE_DIR, createStateRunId('verify')));
7
+ const manifestPath = toPosixPath(path.join(runDir, 'manifest.json'));
8
+ const absoluteRunDir = path.join(projectRoot, runDir);
9
+ return {
10
+ runDir,
11
+ manifestPath,
12
+ absoluteRunDir,
13
+ absoluteIntentDir: path.join(absoluteRunDir, 'intents'),
14
+ absoluteManifestPath: path.join(projectRoot, manifestPath),
15
+ };
16
+ }
17
+ export function createVerifyIntentReceiptPath(statePaths, ordinal, intent) {
18
+ const fileName = `${String(ordinal).padStart(3, '0')}-${sanitizeIntentFilePart(intent)}.json`;
19
+ return {
20
+ receiptPath: toPosixPath(path.join(statePaths.runDir, 'intents', fileName)),
21
+ absoluteReceiptPath: path.join(statePaths.absoluteIntentDir, fileName),
22
+ };
23
+ }
24
+ export function resolveLatestVerifyRunReceiptPath(projectRoot) {
25
+ return path.join(projectRoot, LATEST_RUN_RECEIPT_PATH);
26
+ }
27
+ function toPosixPath(value) {
28
+ return value.split(path.sep).join('/');
29
+ }
30
+ function sanitizeIntentFilePart(value) {
31
+ const sanitized = value.replace(/[^A-Za-z0-9._-]+/g, '_').replace(/^_+|_+$/g, '');
32
+ return sanitized.length > 0 ? sanitized.slice(0, 80) : 'intent';
33
+ }
@@ -1,11 +1,9 @@
1
1
  import { createHash } from 'node:crypto';
2
- import path from 'node:path';
3
2
  import { runRun } from './run.js';
4
3
  import { createChangeVerificationReport, } from '../../core/change-verification.js';
5
4
  import { createCorrelationId } from '../../core/correlation-id.js';
6
5
  import { readUtf8FileInsideWithoutSymlinks, writeJsonFileInsideWithoutSymlinks } from '../../core/safe-filesystem.js';
7
6
  import { createVerifyCompletionVerdict, } from '../../core/completion-verdict.js';
8
- import { createStateRunId } from '../../core/atomic-state-write.js';
9
7
  import { createExternalEvidenceRisks, } from '../../core/external-evidence.js';
10
8
  import { createRepeatedFailureRisks, createVerificationFailureFingerprint, updateRepeatedFailureState, } from '../../core/repeated-failure.js';
11
9
  import { countReproEvidenceVerdictEffects, createReproEvidenceRisks, } from '../../core/repro-evidence.js';
@@ -17,14 +15,13 @@ import { readCommandContract } from '../../core/config-loading.js';
17
15
  import { DEFAULT_VERIFY_PARALLELISM, parseVerifyArgs, resolveVerifyParallelism, } from './verify/args.js';
18
16
  import { createInputFromChanged, createSyntheticClassificationReport, planErrorMessageKey, readInputFromClassificationReport, resolveVerifyInputPath, writeChangedPlan, } from './verify/input.js';
19
17
  import { readExternalEvidenceFile, readReproEvidenceFile } from './verify/evidence-input.js';
18
+ import { createVerifyIntentReceiptPath, createVerifyRunStatePaths, resolveLatestVerifyRunReceiptPath, } from './verify/state-paths.js';
20
19
  import { printUsageError, renderHelp } from '../lib/cli-output.js';
21
20
  import { t } from '../lib/i18n.js';
22
21
  import { readLocalCommandEffectGraphs, readLocalPathSurfaces, readLocalSourceAnchorVerdictRisks, } from '../lib/local-index.js';
23
22
  import { resolveMustflowRoot } from '../lib/project-root.js';
24
23
  export { planErrorMessageKey, readInputFromClassificationReport } from './verify/input.js';
25
24
  const VERIFY_SCHEMA_VERSION = '1';
26
- const RUN_STATE_DIR = path.join('.mustflow', 'state', 'runs');
27
- const LATEST_RUN_RECEIPT_PATH = path.join(RUN_STATE_DIR, 'latest.json');
28
25
  function createBufferedOutput() {
29
26
  const stdout = [];
30
27
  const stderr = [];
@@ -80,25 +77,6 @@ export function getVerifyHelp(lang = 'en') {
80
77
  function uniqueStrings(values) {
81
78
  return [...new Set(values.map((value) => value.trim()).filter((value) => value.length > 0))];
82
79
  }
83
- function toPosixPath(value) {
84
- return value.split(path.sep).join('/');
85
- }
86
- function createVerifyRunStatePaths(projectRoot) {
87
- const runDir = toPosixPath(path.join(RUN_STATE_DIR, createStateRunId('verify')));
88
- const manifestPath = toPosixPath(path.join(runDir, 'manifest.json'));
89
- const absoluteRunDir = path.join(projectRoot, runDir);
90
- return {
91
- runDir,
92
- manifestPath,
93
- absoluteRunDir,
94
- absoluteIntentDir: path.join(absoluteRunDir, 'intents'),
95
- absoluteManifestPath: path.join(projectRoot, manifestPath),
96
- };
97
- }
98
- function sanitizeIntentFilePart(value) {
99
- const sanitized = value.replace(/[^A-Za-z0-9._-]+/g, '_').replace(/^_+|_+$/g, '');
100
- return sanitized.length > 0 ? sanitized.slice(0, 80) : 'intent';
101
- }
102
80
  function skippedResult(candidate) {
103
81
  return {
104
82
  intent: candidate.intent || null,
@@ -572,7 +550,7 @@ function readVerificationFailureFingerprint(value) {
572
550
  }
573
551
  function readPreviousVerifyLatestSummary(projectRoot) {
574
552
  try {
575
- const parsed = JSON.parse(readUtf8FileInsideWithoutSymlinks(projectRoot, path.join(projectRoot, LATEST_RUN_RECEIPT_PATH)));
553
+ const parsed = JSON.parse(readUtf8FileInsideWithoutSymlinks(projectRoot, resolveLatestVerifyRunReceiptPath(projectRoot)));
576
554
  if (parsed.command !== 'verify' ||
577
555
  parsed.kind !== 'verify_run_summary' ||
578
556
  typeof parsed.verification_plan_id !== 'string' ||
@@ -652,9 +630,8 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
652
630
  let receiptSha256 = null;
653
631
  let receipt = result.receipt;
654
632
  if (result.intent && result.receipt) {
655
- const fileName = `${String(index + 1).padStart(3, '0')}-${sanitizeIntentFilePart(result.intent)}.json`;
656
- const absoluteReceiptPath = path.join(statePaths.absoluteIntentDir, fileName);
657
- receiptPath = toPosixPath(path.join(statePaths.runDir, 'intents', fileName));
633
+ const receiptStatePath = createVerifyIntentReceiptPath(statePaths, index + 1, result.intent);
634
+ receiptPath = receiptStatePath.receiptPath;
658
635
  receipt = {
659
636
  ...result.receipt,
660
637
  verification_plan_id: output.verification_plan_id,
@@ -662,7 +639,7 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
662
639
  };
663
640
  const receiptContent = `${JSON.stringify(receipt, null, 2)}\n`;
664
641
  receiptSha256 = hashTextSha256(receiptContent);
665
- writeJsonFileInsideWithoutSymlinks(projectRoot, absoluteReceiptPath, receipt);
642
+ writeJsonFileInsideWithoutSymlinks(projectRoot, receiptStatePath.absoluteReceiptPath, receipt);
666
643
  }
667
644
  receipts.push({
668
645
  intent: result.intent,
@@ -791,7 +768,7 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
791
768
  run_dir: statePaths.runDir,
792
769
  manifest_path: statePaths.manifestPath,
793
770
  };
794
- writeJsonFileInsideWithoutSymlinks(projectRoot, path.join(projectRoot, LATEST_RUN_RECEIPT_PATH), latest);
771
+ writeJsonFileInsideWithoutSymlinks(projectRoot, resolveLatestVerifyRunReceiptPath(projectRoot), latest);
795
772
  return outputWithReceiptPaths;
796
773
  }
797
774
  async function createVerifyOutput(input, planSource, projectRoot, lang, reproEvidence = null, externalChecks = [], parallelism = DEFAULT_VERIFY_PARALLELISM, parallelismReport = null) {
@@ -2,14 +2,12 @@ import { existsSync } from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { triageDocReview } from '../../core/doc-review-triage.js';
4
4
  import { ensureInside, ensureInsideWithoutSymlinks, readUtf8FileInsideWithoutSymlinks, toPosixPath, writeUtf8FileInsideWithoutSymlinks, } from './filesystem.js';
5
+ import { isRecord } from './command-contract.js';
5
6
  import { parseTomlText, stringifyToml } from './toml.js';
6
7
  export const DOC_REVIEW_LEDGER_RELATIVE_PATH = '.mustflow/review/docs.toml';
7
8
  export const DOC_REVIEW_STATUSES = ['pending', 'in_review', 'changes_made', 'approved', 'needs_human', 'ignored'];
8
9
  export const DOC_REVIEW_ACTIVE_STATUSES = ['pending', 'in_review', 'changes_made', 'needs_human'];
9
10
  export const REVIEWER_KINDS = ['human', 'llm', 'tool', 'external'];
10
- function isRecord(value) {
11
- return typeof value === 'object' && value !== null && !Array.isArray(value);
12
- }
13
11
  function readOptionalString(value) {
14
12
  return typeof value === 'string' && value.trim().length > 0 ? value : undefined;
15
13
  }
@@ -2,11 +2,9 @@ import { createHash } from 'node:crypto';
2
2
  import { existsSync } from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { ensureFileTargetInsideWithoutSymlinks, ensureInside, readFileInsideWithoutSymlinks, readUtf8FileInsideWithoutSymlinks, writeUtf8FileInsideWithoutSymlinks, } from './filesystem.js';
5
+ import { isRecord } from './command-contract.js';
5
6
  import { parseTomlText, stringifyToml } from './toml.js';
6
7
  export const MANIFEST_LOCK_RELATIVE_PATH = '.mustflow/config/manifest.lock.toml';
7
- function isRecord(value) {
8
- return typeof value === 'object' && value !== null && !Array.isArray(value);
9
- }
10
8
  function readString(table, key, label) {
11
9
  const value = table[key];
12
10
  if (typeof value !== 'string' || value.trim().length === 0) {
@@ -0,0 +1,53 @@
1
+ import { createHash } from 'node:crypto';
2
+ const REPO_MAP_DOC_ID = 'repo-map';
3
+ const REPO_MAP_LIFECYCLE = 'generated';
4
+ const REPO_MAP_GENERATOR = 'mustflow';
5
+ const REPO_MAP_RELATIVE_ROOT = '.';
6
+ const REPO_MAP_SOURCE_POLICY = 'anchors_only';
7
+ const REPO_MAP_PRIVACY_MODE = 'minimal';
8
+ export function getRepoMapSourceFingerprint(input) {
9
+ const payload = {
10
+ depth: input.depth,
11
+ includeNested: input.includeNested,
12
+ gitLsFilesStatus: input.gitLsFilesStatus,
13
+ priorityPaths: [...input.configuredPriorityPaths].sort(),
14
+ anchors: input.anchors.map((anchor) => anchor.relativePath).sort(),
15
+ nestedRepositories: input.nestedRepositories
16
+ .map((repository) => ({
17
+ relativePath: repository.relativePath,
18
+ mustflow: repository.mustflow,
19
+ agentRules: repository.agentRules,
20
+ repoMap: repository.repoMap,
21
+ mustflowConfig: repository.mustflowConfig,
22
+ commandContract: repository.commandContract,
23
+ contextIndex: repository.contextIndex,
24
+ skillIndex: repository.skillIndex,
25
+ rootDocuments: repository.rootDocuments.map((document) => document.relativePath).sort(),
26
+ machineContracts: [...repository.machineContracts].sort(),
27
+ manifests: [...repository.manifests].sort(),
28
+ commandAdapters: [...repository.commandAdapters].sort(),
29
+ editingPolicies: [...repository.editingPolicies].sort(),
30
+ }))
31
+ .sort((left, right) => left.relativePath.localeCompare(right.relativePath)),
32
+ };
33
+ const digest = createHash('sha256').update(JSON.stringify(payload)).digest('hex');
34
+ return `sha256:${digest}`;
35
+ }
36
+ export function renderRepoMapFrontmatter(anchorCount, sourceFingerprint, gitLsFilesStatus) {
37
+ const degraded = gitLsFilesStatus !== 'ok';
38
+ return [
39
+ '---',
40
+ `mustflow_doc: ${REPO_MAP_DOC_ID}`,
41
+ `lifecycle: ${REPO_MAP_LIFECYCLE}`,
42
+ `generated_by: ${REPO_MAP_GENERATOR}`,
43
+ `relative_root: "${REPO_MAP_RELATIVE_ROOT}"`,
44
+ `source_policy: ${REPO_MAP_SOURCE_POLICY}`,
45
+ `privacy_mode: ${REPO_MAP_PRIVACY_MODE}`,
46
+ `anchor_count: ${anchorCount}`,
47
+ `degraded: ${degraded ? 'true' : 'false'}`,
48
+ `git_ls_files_status: ${gitLsFilesStatus}`,
49
+ `source_fingerprint: "${sourceFingerprint}"`,
50
+ '---',
51
+ '',
52
+ ];
53
+ }
@@ -1,17 +1,12 @@
1
1
  import { spawnSync } from 'node:child_process';
2
- import { createHash } from 'node:crypto';
3
2
  import { existsSync, lstatSync, readdirSync, realpathSync, statSync } from 'node:fs';
4
3
  import path from 'node:path';
5
4
  import { toPosixPath } from './filesystem.js';
5
+ import { getRepoMapSourceFingerprint, renderRepoMapFrontmatter, } from './repo-map-frontmatter.js';
6
6
  import { writeUtf8FileInsideWithoutSymlinks } from '../../core/safe-filesystem.js';
7
+ import { isRecord } from './command-contract.js';
7
8
  import { readMustflowTomlFile } from './toml.js';
8
9
  const DEFAULT_DEPTH = 3;
9
- const REPO_MAP_DOC_ID = 'repo-map';
10
- const REPO_MAP_LIFECYCLE = 'generated';
11
- const REPO_MAP_GENERATOR = 'mustflow';
12
- const REPO_MAP_RELATIVE_ROOT = '.';
13
- const REPO_MAP_SOURCE_POLICY = 'anchors_only';
14
- const REPO_MAP_PRIVACY_MODE = 'minimal';
15
10
  const GIT_LS_FILES_TIMEOUT_MS = 5_000;
16
11
  const GIT_LS_FILES_MAX_BUFFER_BYTES = 1_048_576;
17
12
  const EXCLUDED_SEGMENTS = new Set([
@@ -196,9 +191,6 @@ const EXACT_ANCHOR_DESCRIPTIONS = new Map([
196
191
  ['.mustflow/docs/agent-workflow.md', 'Shared workflow policy for agent work.'],
197
192
  ['.mustflow/skills/INDEX.md', 'Index of available procedural skills.'],
198
193
  ]);
199
- function isRecord(value) {
200
- return typeof value === 'object' && value !== null && !Array.isArray(value);
201
- }
202
194
  function getStringArray(value) {
203
195
  return Array.isArray(value) ? value.filter((entry) => typeof entry === 'string') : [];
204
196
  }
@@ -624,52 +616,6 @@ function countNestedEntrypoints(repository) {
624
616
  ...repository.editingPolicies,
625
617
  ].filter(Boolean).length;
626
618
  }
627
- function getSourceFingerprint(depth, includeNested, configuredPriorityPaths, gitLsFilesStatus, anchors, nestedRepositories) {
628
- const payload = {
629
- depth,
630
- includeNested,
631
- gitLsFilesStatus,
632
- priorityPaths: [...configuredPriorityPaths].sort(),
633
- anchors: anchors.map((anchor) => anchor.relativePath).sort(),
634
- nestedRepositories: nestedRepositories
635
- .map((repository) => ({
636
- relativePath: repository.relativePath,
637
- mustflow: repository.mustflow,
638
- agentRules: repository.agentRules,
639
- repoMap: repository.repoMap,
640
- mustflowConfig: repository.mustflowConfig,
641
- commandContract: repository.commandContract,
642
- contextIndex: repository.contextIndex,
643
- skillIndex: repository.skillIndex,
644
- rootDocuments: repository.rootDocuments.map((document) => document.relativePath).sort(),
645
- machineContracts: [...repository.machineContracts].sort(),
646
- manifests: [...repository.manifests].sort(),
647
- commandAdapters: [...repository.commandAdapters].sort(),
648
- editingPolicies: [...repository.editingPolicies].sort(),
649
- }))
650
- .sort((left, right) => left.relativePath.localeCompare(right.relativePath)),
651
- };
652
- const digest = createHash('sha256').update(JSON.stringify(payload)).digest('hex');
653
- return `sha256:${digest}`;
654
- }
655
- function renderRepoMapFrontmatter(anchorCount, sourceFingerprint, gitLsFilesStatus) {
656
- const degraded = gitLsFilesStatus !== 'ok';
657
- return [
658
- '---',
659
- `mustflow_doc: ${REPO_MAP_DOC_ID}`,
660
- `lifecycle: ${REPO_MAP_LIFECYCLE}`,
661
- `generated_by: ${REPO_MAP_GENERATOR}`,
662
- `relative_root: "${REPO_MAP_RELATIVE_ROOT}"`,
663
- `source_policy: ${REPO_MAP_SOURCE_POLICY}`,
664
- `privacy_mode: ${REPO_MAP_PRIVACY_MODE}`,
665
- `anchor_count: ${anchorCount}`,
666
- `degraded: ${degraded ? 'true' : 'false'}`,
667
- `git_ls_files_status: ${gitLsFilesStatus}`,
668
- `source_fingerprint: "${sourceFingerprint}"`,
669
- '---',
670
- '',
671
- ];
672
- }
673
619
  function renderSourceQuality(gitLsFilesStatus) {
674
620
  if (gitLsFilesStatus === 'ok') {
675
621
  return [];
@@ -701,7 +647,14 @@ export function generateRepoMap(projectRoot, options = {}) {
701
647
  .filter((anchor) => Boolean(anchor));
702
648
  const otherAnchors = anchors.filter((anchor) => !priorityPathSet.has(anchor.relativePath));
703
649
  const anchorCount = anchors.length + nestedRepositories.reduce((total, repository) => total + countNestedEntrypoints(repository), 0);
704
- const sourceFingerprint = getSourceFingerprint(depth, mapConfig.includeNested, configuredPriorityPaths, gitLsFilesStatus, anchors, nestedRepositories);
650
+ const sourceFingerprint = getRepoMapSourceFingerprint({
651
+ depth,
652
+ includeNested: mapConfig.includeNested,
653
+ configuredPriorityPaths,
654
+ gitLsFilesStatus,
655
+ anchors,
656
+ nestedRepositories,
657
+ });
705
658
  return [
706
659
  ...renderRepoMapFrontmatter(anchorCount, sourceFingerprint, gitLsFilesStatus),
707
660
  '# REPO_MAP.md',
@@ -2,6 +2,7 @@ import { existsSync, readFileSync, statSync } from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { isRecord } from '../command-contract.js';
4
4
  import { validateCommandContractConfig, validateCommandContractStrictDefaults, } from '../../../core/command-contract-validation.js';
5
+ import { describeCheckIssues } from '../../../core/check-issues.js';
5
6
  import { ALLOWED_RETENTION_ON_LIMIT, ALLOWED_RETENTION_STORES, DEFAULT_RETENTION_LIMITS, readNestedRetentionTable, readRetentionTable, resolveRetentionLimits, } from '../../../core/retention-policy.js';
6
7
  import { formatManagedMarkdownLabel, getManagedMarkdownExpectation, } from '../../../core/authority-resolution.js';
7
8
  import { SKILL_INDEX_ROUTE_COLUMN_COUNT, SKILL_INDEX_ROUTE_COLUMNS, SKILL_INDEX_SKILL_PATH_COLUMN_INDEX, findSkillRouteConflictWarnings, findSkillIndexRoutePathColumn, parseSkillIndexRoutes, readBacktickValues, } from '../../../core/skill-route-alignment.js';
@@ -1641,12 +1642,15 @@ function collectCheckIssues(projectRoot, options = {}) {
1641
1642
  }
1642
1643
  export function checkMustflowProjectReport(projectRoot, options = {}) {
1643
1644
  const issues = collectCheckIssues(projectRoot, options);
1644
- const errors = issues.filter((issue) => issue.severity !== 'warning').map((issue) => issue.message);
1645
- const warnings = issues.filter((issue) => issue.severity === 'warning').map((issue) => issue.message);
1645
+ const errorIssues = issues.filter((issue) => issue.severity !== 'warning');
1646
+ const warningIssues = issues.filter((issue) => issue.severity === 'warning');
1647
+ const errors = errorIssues.map((issue) => issue.message);
1648
+ const warnings = warningIssues.map((issue) => issue.message);
1646
1649
  return {
1647
1650
  issues: errors,
1648
1651
  warnings,
1649
1652
  allMessages: [...errors, ...warnings],
1653
+ issueDetails: describeCheckIssues([...errorIssues, ...warningIssues]),
1650
1654
  };
1651
1655
  }
1652
1656
  export function checkMustflowProject(projectRoot, options = {}) {
@@ -86,11 +86,15 @@ export function getCheckIssueId(message) {
86
86
  }
87
87
  return null;
88
88
  }
89
- export function describeCheckIssues(messages) {
90
- return messages.map((message) => ({
91
- id: getCheckIssueId(message),
92
- severity: message.startsWith('Strict warning: ') ? 'warning' : 'error',
93
- mode: message.startsWith('Strict') ? 'strict' : 'base',
94
- message,
95
- }));
89
+ export function describeCheckIssues(issues) {
90
+ return issues.map((issue) => {
91
+ const message = typeof issue === 'string' ? issue : issue.message;
92
+ const severity = message.startsWith('Strict warning: ') ? 'warning' : 'error';
93
+ return {
94
+ id: typeof issue === 'string' ? getCheckIssueId(message) : issue.id ?? getCheckIssueId(message),
95
+ severity: typeof issue === 'string' ? severity : issue.severity ?? severity,
96
+ mode: message.startsWith('Strict') ? 'strict' : 'base',
97
+ message,
98
+ };
99
+ });
96
100
  }
@@ -6,11 +6,11 @@ import { COMMAND_EFFECT_CONCURRENCY, COMMAND_EFFECT_MODES, COMMAND_EFFECT_TYPES,
6
6
  import { commandIntentBlockedCommandPattern, commandIntentHasCommandSource, commandIntentNameIsSafe, } from './command-contract-rules.js';
7
7
  import { MAX_COMMAND_OUTPUT_BYTES, commandMaxOutputBytesLimitMessage } from './command-output-limits.js';
8
8
  import { SUCCESS_EXIT_CODES_CONTRACT_DESCRIPTION, successExitCodesAreValid } from './success-exit-codes.js';
9
- function commandContractIssue(message) {
10
- return { message };
9
+ function commandContractIssue(message, id) {
10
+ return id ? { id, message } : { message };
11
11
  }
12
- function commandContractWarning(message) {
13
- return { message, severity: 'warning' };
12
+ function commandContractWarning(message, id) {
13
+ return id ? { id, message, severity: 'warning' } : { message, severity: 'warning' };
14
14
  }
15
15
  function hasOwn(table, key) {
16
16
  return Object.prototype.hasOwnProperty.call(table, key);
@@ -56,7 +56,7 @@ function validatePositiveIntegerField(table, key, label, issues) {
56
56
  function validateMaxOutputBytesField(table, key, label, issues) {
57
57
  validatePositiveIntegerField(table, key, label, issues);
58
58
  if (isPositiveInteger(table[key]) && Number(table[key]) > MAX_COMMAND_OUTPUT_BYTES) {
59
- issues.push(commandContractIssue(commandMaxOutputBytesLimitMessage(label)));
59
+ issues.push(commandContractIssue(commandMaxOutputBytesLimitMessage(label), 'mustflow.command_contract.max_output_bytes_exceeds_limit'));
60
60
  }
61
61
  }
62
62
  function validateAllowedStringField(table, key, label, allowedValues, issues) {
@@ -115,7 +115,7 @@ function validateCommandIntentEffects(intentName, intent, issues) {
115
115
  return;
116
116
  }
117
117
  if (!Array.isArray(intent.effects) || intent.effects.some((entry) => !isRecord(entry))) {
118
- issues.push(commandContractIssue(`[commands.intents.${intentName}].effects must be an array of tables`));
118
+ issues.push(commandContractIssue(`[commands.intents.${intentName}].effects must be an array of tables`, 'mustflow.command_contract.effects_invalid'));
119
119
  return;
120
120
  }
121
121
  for (const effect of intent.effects) {
@@ -171,39 +171,39 @@ function validateCommandIntent(intentName, intent, issues) {
171
171
  const lifecycle = typeof intent.lifecycle === 'string' ? intent.lifecycle : undefined;
172
172
  const runPolicy = typeof intent.run_policy === 'string' ? intent.run_policy : undefined;
173
173
  if (!lifecycle) {
174
- issues.push(commandContractIssue(`Configured intent ${intentName} must define lifecycle`));
174
+ issues.push(commandContractIssue(`Configured intent ${intentName} must define lifecycle`, 'mustflow.command_contract.configured_missing_lifecycle'));
175
175
  }
176
176
  if (!runPolicy) {
177
- issues.push(commandContractIssue(`Configured intent ${intentName} must define run_policy`));
177
+ issues.push(commandContractIssue(`Configured intent ${intentName} must define run_policy`, 'mustflow.command_contract.configured_missing_run_policy'));
178
178
  }
179
179
  if (lifecycle === 'oneshot') {
180
180
  validatePositiveIntegerField(intent, 'timeout_seconds', `[commands.intents.${intentName}].timeout_seconds`, issues);
181
181
  if (!hasOwn(intent, 'timeout_seconds')) {
182
- issues.push(commandContractIssue(`Oneshot intent ${intentName} must define timeout_seconds`));
182
+ issues.push(commandContractIssue(`Oneshot intent ${intentName} must define timeout_seconds`, 'mustflow.command_contract.oneshot_missing_timeout'));
183
183
  }
184
184
  if (intent.stdin !== 'closed') {
185
- issues.push(commandContractIssue(`Oneshot intent ${intentName} must set stdin = "closed"`));
185
+ issues.push(commandContractIssue(`Oneshot intent ${intentName} must set stdin = "closed"`, 'mustflow.command_contract.oneshot_stdin_not_closed'));
186
186
  }
187
187
  }
188
188
  if (lifecycle && LONG_RUNNING_LIFECYCLES.has(lifecycle) && runPolicy === 'agent_allowed') {
189
- issues.push(commandContractIssue(`Long-running intent ${intentName} must not use run_policy = "agent_allowed"`));
189
+ issues.push(commandContractIssue(`Long-running intent ${intentName} must not use run_policy = "agent_allowed"`, 'mustflow.command_contract.long_running_agent_allowed'));
190
190
  }
191
191
  if (intent.mode === 'shell' && runPolicy === 'agent_allowed' && intent.allow_shell !== true) {
192
- issues.push(commandContractIssue(`Agent-runnable shell intent ${intentName} must set allow_shell = true`));
192
+ issues.push(commandContractIssue(`Agent-runnable shell intent ${intentName} must set allow_shell = true`, 'mustflow.command_contract.agent_shell_requires_allow'));
193
193
  }
194
194
  if (!commandIntentHasCommandSource(intent)) {
195
- issues.push(commandContractIssue(`Configured intent ${intentName} must define argv or mode = "shell" with cmd`));
195
+ issues.push(commandContractIssue(`Configured intent ${intentName} must define argv or mode = "shell" with cmd`, 'mustflow.command_contract.executable_source_missing'));
196
196
  }
197
197
  const blockedCommandPattern = commandIntentBlockedCommandPattern(intent);
198
198
  if (blockedCommandPattern?.code === 'shell_background_pattern') {
199
- issues.push(commandContractIssue(`Shell intent ${intentName} contains a blocked long-running or background pattern`));
199
+ issues.push(commandContractIssue(`Shell intent ${intentName} contains a blocked long-running or background pattern`, 'mustflow.command_contract.shell_background_pattern'));
200
200
  }
201
201
  if (blockedCommandPattern?.code === 'long_running_command_pattern') {
202
- issues.push(commandContractIssue(`Intent ${intentName} contains a blocked long-running or background command pattern`));
202
+ issues.push(commandContractIssue(`Intent ${intentName} contains a blocked long-running or background command pattern`, 'mustflow.command_contract.long_running_command_pattern'));
203
203
  }
204
204
  if (hasOwn(intent, 'success_exit_codes')) {
205
205
  if (!successExitCodesAreValid(intent.success_exit_codes)) {
206
- issues.push(commandContractIssue(`[commands.intents.${intentName}].success_exit_codes must be ${SUCCESS_EXIT_CODES_CONTRACT_DESCRIPTION}`));
206
+ issues.push(commandContractIssue(`[commands.intents.${intentName}].success_exit_codes must be ${SUCCESS_EXIT_CODES_CONTRACT_DESCRIPTION}`, 'mustflow.command_contract.success_exit_codes_invalid'));
207
207
  }
208
208
  }
209
209
  validateCommandIntentEffects(intentName, intent, issues);
@@ -281,7 +281,9 @@ function validateCommandEnvInheritanceWarnings(commandsToml) {
281
281
  const issues = [];
282
282
  for (const warning of findCommandEnvInheritanceWarnings(commandsToml)) {
283
283
  const message = formatCommandEnvInheritanceWarning(warning);
284
- issues.push(warning.severity === 'warning' ? commandContractWarning(message) : commandContractIssue(message));
284
+ issues.push(warning.severity === 'warning'
285
+ ? commandContractWarning(message, 'mustflow.command_contract.broad_env_inheritance')
286
+ : commandContractIssue(message, 'mustflow.command_contract.broad_env_inheritance'));
285
287
  }
286
288
  return issues;
287
289
  }
@@ -316,7 +318,7 @@ function validateProjectLocalBinWarnings(projectRoot, commandsToml) {
316
318
  if (!projectLocalBinExecutableExists(projectRoot, executable)) {
317
319
  continue;
318
320
  }
319
- issues.push(commandContractWarning(`configured agent-runnable intent ${intentName} uses bare executable "${executable}" that matches project-local node_modules/.bin; use a package-manager mediated command such as npm exec, pnpm exec, bun x, or yarn exec`));
321
+ issues.push(commandContractWarning(`configured agent-runnable intent ${intentName} uses bare executable "${executable}" that matches project-local node_modules/.bin; use a package-manager mediated command such as npm exec, pnpm exec, bun x, or yarn exec`, 'mustflow.command_contract.project_local_bin_bare_executable'));
320
322
  }
321
323
  return issues;
322
324
  }
@@ -336,12 +338,12 @@ export function validateCommandContractConfig(commandsToml) {
336
338
  validateCommandDefaults(commandsToml, issues);
337
339
  validateCommandResources(commandsToml, issues);
338
340
  if (!isRecord(commandsToml.intents)) {
339
- issues.push(commandContractIssue('Missing [intents] table in .mustflow/config/commands.toml'));
341
+ issues.push(commandContractIssue('Missing [intents] table in .mustflow/config/commands.toml', 'mustflow.command_contract.intent_table_missing'));
340
342
  return issues;
341
343
  }
342
344
  for (const [intentName, intent] of Object.entries(commandsToml.intents)) {
343
345
  if (!isRecord(intent)) {
344
- issues.push(commandContractIssue(`Intent ${intentName} must be a TOML table`));
346
+ issues.push(commandContractIssue(`Intent ${intentName} must be a TOML table`, 'mustflow.command_contract.intent_not_table'));
345
347
  continue;
346
348
  }
347
349
  validateCommandIntent(intentName, intent, issues);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mustflow",
3
- "version": "2.22.9",
3
+ "version": "2.22.12",
4
4
  "description": "Agent workflow documents and CLI for mustflow repository roots.",
5
5
  "type": "module",
6
6
  "license": "MIT-0",
@@ -3,7 +3,7 @@ mustflow_doc: context.index
3
3
  kind: mustflow-context
4
4
  locale: ko
5
5
  canonical: false
6
- revision: 1
6
+ revision: 2
7
7
  name: context-index
8
8
  authority: router
9
9
  lifecycle: mustflow-owned
@@ -11,14 +11,14 @@ stability: medium
11
11
  review_status: needs_human_review
12
12
  ---
13
13
 
14
- # 문맥 색인
14
+ # 컨텍스트 색인
15
15
 
16
- 이 파일은 현재 작업에 필요한 프로젝트 문맥 파일을 결정하고 참조하는 안내서입니다.
17
- 불필요한 정보 유입을 방지하기 위해 기본적으로 모든 문맥 파일을 읽지 않습니다.
16
+ 이 파일은 현재 작업에 필요한 프로젝트 컨텍스트 파일을 결정하고 참조하는 안내서입니다.
17
+ 불필요한 정보 유입을 방지하기 위해 기본적으로 모든 컨텍스트 파일을 읽지 않습니다.
18
18
 
19
- ## 사용 가능한 문맥
19
+ ## 사용 가능한 컨텍스트
20
20
 
21
- | 문맥 | 적용 시나리오 | 경로 |
21
+ | 컨텍스트 | 적용 시나리오 | 경로 |
22
22
  | --- | --- | --- |
23
23
  | project | 작업이 프로젝트 방향, 범위, 공개 동작, 비목표, 저장소 전반의 규칙에 잠재적으로 영향을 미치는 경우 | `.mustflow/context/PROJECT.md` |
24
24
 
@@ -26,14 +26,14 @@ review_status: needs_human_review
26
26
 
27
27
  | 앵커 | 적용 시나리오 | 경로 |
28
28
  | --- | --- | --- |
29
- | 사용자용 개요 | 공개 프로젝트 개요나 설치 안내가 필요한 경우입니다. 강제 정책이 아닌 일반 문맥으로 참조하십시오. | `README.md` |
30
- | 로드맵 | 프로젝트 계획, 우선순위, 마일스톤 또는 비목표 문맥이 필요한 경우입니다. 설치된 mustflow 정책이 아닌 계획 문맥으로 참조하십시오. | `ROADMAP.md` |
29
+ | 사용자용 개요 | 공개 프로젝트 개요나 설치 안내가 필요한 경우입니다. 강제 정책이 아닌 일반 컨텍스트로 참조하십시오. | `README.md` |
30
+ | 로드맵 | 프로젝트 계획, 우선순위, 마일스톤 또는 비목표 컨텍스트가 필요한 경우입니다. 설치된 mustflow 정책이 아닌 계획 컨텍스트로 참조하십시오. | `ROADMAP.md` |
31
31
  | 시각 디자인 | UI, 시각적 정체성, 디자인 토큰, 레이아웃 또는 접근성을 변경하는 경우 | `DESIGN.md` |
32
32
 
33
33
  ## 읽기 규칙
34
34
 
35
- - 현재 작업에 해당하는 문맥 파일만 참조하십시오.
36
- - 문맥 파일은 더 높은 권한의 출처에 기반한다고 명시되지 않은 경우 참고용 지침으로 간주합니다.
37
- - 문맥이 코드, 테스트, 명령 계약, 명시적 사용자 지시와 충돌하는 경우 이를 보고하고 더 높은 권한의 출처를 우선 적용하십시오.
35
+ - 현재 작업에 해당하는 컨텍스트 파일만 참조하십시오.
36
+ - 컨텍스트 파일은 더 높은 권한의 출처에 기반한다고 명시되지 않은 경우 참고용 지침으로 간주합니다.
37
+ - 컨텍스트가 코드, 테스트, 명령 계약, 명시적 사용자 지시와 충돌하는 경우 이를 보고하고 더 높은 권한의 출처를 우선 적용하십시오.
38
38
  - 누락된 프로젝트 목표, 비목표, 디자인 토큰, API 계약, 데이터 규칙을 임의로 추측하거나 생성하지 마십시오.
39
- - `DESIGN.md`의 디자인 토큰을 `.mustflow/context/` 내에 중복 기록하지 마십시오.
39
+ - `DESIGN.md`의 디자인 토큰을 `.mustflow/context/` 내에 중복 기록하지 마십시오.
@@ -3,7 +3,7 @@ mustflow_doc: context.project
3
3
  kind: mustflow-context
4
4
  locale: ko
5
5
  canonical: false
6
- revision: 1
6
+ revision: 2
7
7
  name: project
8
8
  authority: contextual
9
9
  lifecycle: user-editable
@@ -15,14 +15,14 @@ source_refs:
15
15
  - .mustflow/config/commands.toml
16
16
  ---
17
17
 
18
- # 프로젝트 문맥
18
+ # 프로젝트 컨텍스트
19
19
 
20
- 이 파일은 코딩 에이전트를 위한 프로젝트별 문맥을 정의합니다.
20
+ 이 파일은 코딩 에이전트를 위한 프로젝트별 컨텍스트를 정의합니다.
21
21
  알 수 없는 항목은 비워 두시고, 내용을 임의로 추측하여 작성하지 마십시오.
22
22
 
23
23
  ## 권한 경계
24
24
 
25
- - 이 파일에는 근거가 있는 문맥, 알 수 없는 사항, 충돌 내용을 기록할 수 있습니다.
25
+ - 이 파일에는 근거가 있는 컨텍스트, 알 수 없는 사항, 충돌 내용을 기록할 수 있습니다.
26
26
  - 이 파일은 명령 실행 권한을 부여하거나, 파일 수정 금지 규칙을 정의하거나,
27
27
  `AGENTS.md` 또는 `.mustflow/config/*.toml`을 재정의하거나, 현재 근거가 없는
28
28
  기능을 약속해서는 안 됩니다.
@@ -62,5 +62,5 @@ source_refs:
62
62
 
63
63
  ## 오래된 내용 확인
64
64
 
65
- - 이 파일이 현재 코드, 테스트, 명령 계약, 명시적 사용자 지시와 충돌하는 경우, 이를 오래된 문맥으로 간주하고 충돌 내용을 보고해 주십시오.
66
- - 프로젝트 방향, 비목표, 저장소 전반의 규칙이 실제로 변경된 경우에만 이 파일을 수정해 주십시오.
65
+ - 이 파일이 현재 코드, 테스트, 명령 계약, 명시적 사용자 지시와 충돌하는 경우, 이를 오래된 컨텍스트로 간주하고 충돌 내용을 보고해 주십시오.
66
+ - 프로젝트 방향, 비목표, 저장소 전반의 규칙이 실제로 변경된 경우에만 이 파일을 수정해 주십시오.
@@ -2,7 +2,7 @@
2
2
  mustflow_doc: docs.agent-workflow
3
3
  locale: ko
4
4
  canonical: false
5
- revision: 26
5
+ revision: 27
6
6
  lifecycle: mustflow-owned
7
7
  authority: workflow-policy
8
8
  ---
@@ -20,16 +20,16 @@ authority: workflow-policy
20
20
  - 작업 시작 전 확인해야 할 문서 흐름
21
21
  - 상위 작업 공간과 하위 저장소 규칙 간 우선순위
22
22
  - 반복 입력의 안정성 유지 정책
23
- - 장기 작업에서 하네스가 따라야 할 작업 계약 경계
23
+ - 장기 작업에서 실행 하네스(실행 환경)가 따라야 할 작업 계약 경계
24
24
  - 계층형 압축 기억 정책과 요약 기억의 권위 한계
25
- - 명령 의도 상태별 실행 정책
25
+ - 명령 인텐트 상태별 실행 정책
26
26
  - 장기 실행 프로세스 방지 정책
27
27
  - 완료 주장 검토 및 검증 약화 방지 정책
28
- - 저장소별 선호값 해석 정책
28
+ - 저장소별 선호 설정 해석 정책
29
29
  - 수정, 검증, 실패 대응, 보안의 공통 기준
30
30
  - 스킬 문서와 설정 파일 갱신 기준
31
31
 
32
- 이 문서는 실제 테스트, 빌드, 규칙 검사 명령을 직접 나열하지 않습니다. 명령은 저장소마다 다르므로 `.mustflow/config/commands.toml`의 명령 의도 계약을 기준으로 판단합니다.
32
+ 이 문서는 실제 테스트, 빌드, 규칙 검사 명령을 직접 나열하지 않습니다. 명령은 저장소마다 다르므로 `.mustflow/config/commands.toml`의 명령 인텐트 계약을 기준으로 판단합니다.
33
33
 
34
34
  ## 기준 문서 역할
35
35
 
@@ -40,13 +40,13 @@ mustflow 문서는 각각 명확한 역할을 갖습니다. 단순히 편하게
40
40
  | `AGENTS.md` | 첫 진입점이며 반드시 지켜야 하는 간단한 저장소 규칙입니다. | 사용자 직접 지시와 호스트 안전 규칙 아래에서 가장 높은 저장소 내부 지침입니다. | 사용자가 수정 가능하며, 설치 방식에 따라 mustflow 관리 파일 또는 관리 블록입니다. |
41
41
  | `.mustflow/docs/agent-workflow.md` | 읽기, 수정, 검증, 보고, 실패 대응에 관한 공통 작업 정책입니다. | `AGENTS.md`를 상세히 풀어 설명하지만 실행 명령은 정의하지 않습니다. | mustflow가 소유하는 Markdown 문서입니다. |
42
42
  | `.mustflow/config/mustflow.toml` | 문서 루트, 보호 경로, 예산, 승인, 보존, 새로고침 등 작업 설정입니다. | mustflow 동작을 정의하는 기계 판독 설정입니다. | mustflow가 소유하는 TOML 파일입니다. |
43
- | `.mustflow/config/commands.toml` | 명령 의도 계약입니다. | 설정된 의도를 통해 프로젝트 명령 실행을 허용하는 유일한 기준입니다. | 명령 계약 변경 시 수정하는 저장소별 TOML 파일입니다. |
44
- | `.mustflow/config/preferences.toml` | 스타일, 언어, Git 제안, 테스트 작성 성향, 검증 선택, 버전 영향의 기본값입니다. | 권한이 아닌 낮은 권위의 선호값입니다. | 저장소별로 사용자가 조정할 수 있는 TOML 파일입니다. |
45
- | `.mustflow/context/INDEX.md` | 작업별 문맥 파일을 선택하는 라우터입니다. | 선택형 문맥만 고르며 정책 설명서는 아닙니다. | mustflow가 소유하는 Markdown 문서입니다. |
46
- | `.mustflow/context/PROJECT.md` | 신중한 프로젝트 사실, 미지점, 도메인 관습을 기록합니다. | 사용자 지시, 코드, 테스트, 명령 계약, 설정된 정책보다 낮은 권위의 참고 자료입니다. | 사용자가 수정 가능한 문맥 문서입니다. |
43
+ | `.mustflow/config/commands.toml` | 명령 인텐트 계약입니다. | 설정된 인텐트를 통해 프로젝트 명령 실행을 허용하는 유일한 기준입니다. | 명령 계약 변경 시 수정하는 저장소별 TOML 파일입니다. |
44
+ | `.mustflow/config/preferences.toml` | 스타일, 언어, Git 제안, 테스트 작성 성향, 검증 선택, 버전 영향의 기본값입니다. | 권한이 아닌 낮은 권위의 선호 설정입니다. | 저장소별로 사용자가 조정할 수 있는 TOML 파일입니다. |
45
+ | `.mustflow/context/INDEX.md` | 작업별 컨텍스트 파일을 선택하는 라우터입니다. | 선택형 컨텍스트만 고르며 정책 설명서는 아닙니다. | mustflow가 소유하는 Markdown 문서입니다. |
46
+ | `.mustflow/context/PROJECT.md` | 신중한 프로젝트 사실, 미지점, 도메인 관습을 기록합니다. | 사용자 지시, 코드, 테스트, 명령 계약, 설정된 정책보다 낮은 권위의 참고 자료입니다. | 사용자가 수정 가능한 컨텍스트 문서입니다. |
47
47
  | `.mustflow/skills/INDEX.md` | 작업에 맞는 절차 문서를 선택하는 라우터입니다. | 선택 계약만 담당하며 자세한 절차는 `SKILL.md`에 둡니다. | mustflow가 소유하는 Markdown 문서입니다. |
48
48
  | `.mustflow/skills/<name>/SKILL.md` | 반복 작업의 입력, 허용 범위, 검사, 보고 형식을 담은 절차입니다. | 절차 안내일 뿐이며 명령 실행 권한을 부여하거나 다른 규칙을 덮어쓰지 않습니다. | mustflow가 소유하는 Markdown 문서이며, 필요 시 언어별로 설치됩니다. |
49
- | `REPO_MAP.md` | 넓은 탐색과 하위 저장소 진입점을 위한 생성 앵커 지도입니다. | 현재 파일과 현재 지시보다 낮은 생성 탐색 보조 자료입니다. | 생성 파일이며 `repo_map` 의도 또는 `mf map`으로 갱신합니다. |
49
+ | `REPO_MAP.md` | 넓은 탐색과 하위 저장소 진입점을 위한 생성 앵커 지도입니다. | 현재 파일과 현재 지시보다 낮은 생성 탐색 보조 자료입니다. | 생성 파일이며 `repo_map` 인텐트 또는 `mf map`으로 갱신합니다. |
50
50
 
51
51
  ## 에이전트 작업 순환
52
52
 
@@ -55,7 +55,7 @@ mustflow 문서는 각각 명확한 역할을 갖습니다. 단순히 편하게
55
55
  1. `orient`: 필수 mustflow 문서, 현재 루트, 보호 경로, 작업 범위를 확인합니다.
56
56
  2. `plan`: 수정 전 작은 계획을 세우며, 명령이나 관습을 추측하지 않습니다.
57
57
  3. `act`: 요청 범위 내에서 가장 작은 안전한 변경을 수행합니다.
58
- 4. `verify`: `.mustflow/config/commands.toml`에 선언된 단발성 명령만 사용합니다.
58
+ 4. `verify`: `.mustflow/config/commands.toml`에 선언된 일회성 명령만 사용합니다.
59
59
  5. `report`: 변경 파일, 실행한 명령, 건너뛴 명령, 검증 결과, 남은 위험을 보고합니다.
60
60
  6. `handoff`: 안전하게 종료할 수 없으면 추측하지 않고 후속 작업이나 확인 질문을 남깁니다.
61
61
 
@@ -74,20 +74,20 @@ mustflow 문서는 각각 명확한 역할을 갖습니다. 단순히 편하게
74
74
 
75
75
  `REPO_MAP.md`는 넓은 저장소 탐색이 필요할 때만 읽습니다. 이 파일은 전체 파일 목록이 아니라 `AGENTS.md`, `README.md`, `package.json`, `SKILL.md`, 주요 설정 파일 같은 앵커를 찾아 에이전트가 처음 볼 위치를 줄이기 위한 생성 지도입니다. 전체 파일 목록이 필요하면 `git ls-files`나 편집기 파일 탐색기를 사용합니다. `node_modules`, `dist`, `build`, `.git`, 캐시, 대용량 산출물은 제외합니다.
76
76
 
77
- `mf context --json`을 사용할 수 있으면 현재 mustflow 루트의 읽기 순서, 명령 의도, 기능 표면, 마지막 실행 요약을 빠르게 확인할 수 있습니다. 이 출력은 얇은 색인일 뿐이며, 필수 문서와 실제 설정 파일 읽기를 대신하지 않습니다.
77
+ `mf context --json`을 사용할 수 있으면 현재 mustflow 루트의 읽기 순서, 명령 인텐트, 기능 표면, 마지막 실행 요약을 빠르게 확인할 수 있습니다. 이 출력은 얇은 색인일 뿐이며, 필수 문서와 실제 설정 파일 읽기를 대신하지 않습니다.
78
78
 
79
- `mf doctor` 또는 `mf doctor --json`을 사용할 수 있으면 수정 전에 현재 mustflow 루트의 설치 상태, 검사 결과, 실행 가능한 명령 의도, 다음 단계를 읽기 전용으로 확인합니다. 이 명령은 첫 방향을 잡기 위한 진단 명령이며, 파일을 쓰지 않습니다.
79
+ `mf doctor` 또는 `mf doctor --json`을 사용할 수 있으면 수정 전에 현재 mustflow 루트의 설치 상태, 검사 결과, 실행 가능한 명령 인텐트, 다음 단계를 읽기 전용으로 확인합니다. 이 명령은 첫 방향을 잡기 위한 진단 명령이며, 파일을 쓰지 않습니다.
80
80
 
81
- ## 프로젝트 문맥
81
+ ## 프로젝트 컨텍스트
82
82
 
83
- `.mustflow/context/`는 에이전트를 위한 작업별 프로젝트 문맥을 담습니다. 일반 문서 보관함이 아닙니다.
83
+ `.mustflow/context/`는 에이전트를 위한 작업별 프로젝트 컨텍스트를 담습니다. 일반 문서 보관함이 아닙니다.
84
84
 
85
- - 프로젝트, 제품, 도메인, UI, 백엔드, 데이터, 보안, 운영 문맥이 필요한 작업일 때만 `.mustflow/context/INDEX.md`를 읽습니다.
86
- - 문맥 색인에서 선택된 파일만 읽습니다.
87
- - 문맥 파일은 사용자 직접 지시, 현재 코드, 테스트, 명령 계약, 설정된 정책보다 낮은 권위의 참고 자료입니다.
85
+ - 프로젝트, 제품, 도메인, UI, 백엔드, 데이터, 보안, 운영 컨텍스트가 필요한 작업일 때만 `.mustflow/context/INDEX.md`를 읽습니다.
86
+ - 컨텍스트 색인에서 선택된 파일만 읽습니다.
87
+ - 컨텍스트 파일은 사용자 직접 지시, 현재 코드, 테스트, 명령 계약, 설정된 정책보다 낮은 권위의 참고 자료입니다.
88
88
  - 빠진 프로젝트 목표, 비목표, API 약속, 데이터 규칙, 디자인 토큰을 추측해 생성하지 않습니다.
89
89
  - `DESIGN.md`가 있으면 UI 작업에서 참고하는 선택적 외부 시각 디자인 참조로 봅니다. 그 안의 디자인 토큰을 `.mustflow/context/`에 중복 기록하지 않습니다.
90
- - 문맥이 현재 파일이나 명령 계약과 충돌하면 충돌을 보고하고 더 높은 권위의 출처를 따릅니다.
90
+ - 컨텍스트가 현재 파일이나 명령 계약과 충돌하면 충돌을 보고하고 더 높은 권위의 출처를 따릅니다.
91
91
 
92
92
  ## 스킬 활성화
93
93
 
@@ -102,7 +102,7 @@ mustflow 문서는 각각 명확한 역할을 갖습니다. 단순히 편하게
102
102
 
103
103
  작업 중 새 근거가 생겨 작업 유형이 바뀌면 그때 스킬을 다시 선택합니다. 예를 들어 설정된 명령이 실패하면 실패 원인 추적 스킬을, 테스트 계약이 바뀌면 테스트 유지보수 스킬을, 문서나 워크플로가 바뀌면 문서 수정 스킬을 읽습니다.
104
104
 
105
- 여러 스킬이 동시에 맞으면 변경 범위별로 가장 구체적인 스킬을 따르며, 각 스킬이 선언한 명령 의도만 합쳐서 검토합니다. 스킬은 원시 셸 명령, 장기 실행 프로세스, 작업 범위 밖 쓰기를 허용하지 않습니다.
105
+ 여러 스킬이 동시에 맞으면 변경 범위별로 가장 구체적인 스킬을 따르며, 각 스킬이 선언한 명령 인텐트만 합쳐서 검토합니다. 스킬은 원시 셸 명령, 장기 실행 프로세스, 작업 범위 밖 쓰기를 허용하지 않습니다.
106
106
 
107
107
  스킬을 사용했다면 다음 사용자 업데이트나 최종 보고에서 스킬 이름과 선택 이유를 간략히 밝힙니다. 파일을 만들거나 수정한 작업의 최종 보고에는 반드시 짧은 스킬 선택 기록을 포함합니다. 사용한 스킬 목록, 설치된 스킬 중 맞는 항목이 없었다는 사실, 또는 그럴듯한 스킬이 현재 프로필에 설치되어 있지 않다는 누락 중 해당 내용을 밝힙니다. 스킬 선택 기록만을 위해 버전 관리되는 작업 로그를 만들지 않습니다.
108
108
 
@@ -133,10 +133,10 @@ mustflow 문서는 각각 명확한 역할을 갖습니다. 단순히 편하게
133
133
  - 현재 변경 파일이 있는지 확인합니다.
134
134
  - 사용자 요청의 실제 수정 범위를 좁힙니다.
135
135
  - 작업 대상 경로가 `.mustflow/config/mustflow.toml`의 보호 경로에 포함되는지 확인합니다.
136
- - 필요한 명령 의도가 `.mustflow/config/commands.toml`에 등록되어 있는지 확인합니다.
137
- - mustflow 자체 상태가 불명확하면 `mustflow_doctor` 의도 또는 `mf doctor --json`으로 읽기 전용 진단을 먼저 확인합니다.
136
+ - 필요한 명령 인텐트가 `.mustflow/config/commands.toml`에 등록되어 있는지 확인합니다.
137
+ - mustflow 자체 상태가 불명확하면 `mustflow_doctor` 인텐트 또는 `mf doctor --json`으로 읽기 전용 진단을 먼저 확인합니다.
138
138
  - 작업과 맞는 스킬이 있으면 해당 `SKILL.md`를 읽습니다.
139
- - 명령 의도가 실행 가능하지 않으면 임의 대체 명령을 찾지 말고, 건너뛴 이유를 보고합니다.
139
+ - 명령 인텐트가 실행 가능하지 않으면 임의 대체 명령을 찾지 말고, 건너뛴 이유를 보고합니다.
140
140
 
141
141
  ## 입력 안정성 정책
142
142
 
@@ -148,8 +148,8 @@ mustflow 문서는 각각 명확한 역할을 갖습니다. 단순히 편하게
148
148
  - 생성 파일과 자주 바뀌는 정보는 필수 읽기 순서 앞쪽에 두지 않습니다.
149
149
  - 생성 시각, 해시, 최근 변경, 파일 수, 긴 로그 같은 변동 값은 문서 상단에 두지 않습니다.
150
150
  - 전체 대화 원문, 전체 터미널 출력, 원시 JSONL 이벤트 로그는 `.mustflow/` 안에 계속 덧붙이지 않습니다.
151
- - 실행 결과는 `.mustflow/state/runs/latest.json`처럼 작은 실행 영수증으로 남기고, 지식 문서는 원문 로그가 아니라 요약과 출처만 남깁니다.
152
- - 스킬 문서는 공통 정책 전문을 복사하지 말고 이 문서와 명령 의도를 참조합니다.
151
+ - 실행 결과는 `.mustflow/state/runs/latest.json`처럼 작은 실행 기록으로 남기고, 지식 문서는 원문 로그가 아니라 요약과 출처만 남깁니다.
152
+ - 스킬 문서는 공통 정책 전문을 복사하지 말고 이 문서와 명령 인텐트를 참조합니다.
153
153
  - `REPO_MAP.md`는 필요할 때만 읽는 생성 지도이며, 필수 읽기 순서에 포함하지 않습니다.
154
154
 
155
155
  mustflow는 LLM 제공자의 입력 캐시 적중을 보장하지 않습니다. 대신 같은 작업 규칙이 안정적으로 반복 입력될 수 있도록 문서 책임과 읽기 순서를 분리합니다.
@@ -158,10 +158,10 @@ mustflow는 LLM 제공자의 입력 캐시 적중을 보장하지 않습니다.
158
158
 
159
159
  프롬프트 캐시는 성능 최적화용 힌트일 뿐 권위 출처가 아닙니다. 캐시된 지침 블록이나 요약은 사용자 직접 지시, 현재 파일, 현재 명령 계약, 호스트 안전 규칙, 가장 가까운 `AGENTS.md`보다 우선하지 않습니다.
160
160
 
161
- 호스트나 에이전트 하네스가 모델 입력을 조립할 때는 다음 순서를 지켜야 합니다.
161
+ 호스트나 에이전트 실행 하네스가 모델 입력을 조립할 때는 다음 순서를 지켜야 합니다.
162
162
 
163
163
  1. 안정 접두부: `mf context --json --cache-profile stable`에서 얻은 저장소 규칙과 작업 흐름 문서입니다.
164
- 2. 작업 맥락: 선택된 문맥 파일, 맞는 스킬, 저장소 지도 앵커, 관련 소스 파일, 그리고 `cache_layer`가 `task`인 `mf search --json` 결과입니다.
164
+ 2. 작업 컨텍스트: 선택된 컨텍스트 파일, 맞는 스킬, 저장소 지도 앵커, 관련 소스 파일, 그리고 `cache_layer`가 `task`인 `mf search --json` 결과입니다.
165
165
  3. 변동 접미부: 현재 사용자 요청, 변경 파일 목록, 명령 출력 끝부분, 최신 실행 기록 메타데이터, 시각 정보, 그리고 `volatile` 값이 `true`인 `mf search --json` 결과입니다.
166
166
 
167
167
  안정 접두부를 재사용하기 전에는 보고된 콘텐츠 해시를 현재 파일과 비교합니다. 안정 문서의 해시가 하나라도 바뀌면 캐시된 텍스트를 재사용하지 말고 해당 문서를 다시 읽어야 합니다. 절대로 로컬 경로, 실행 기록 시각, 명령 출력, 변경 파일, 현재 사용자 작업 문구는 안정 접두부보다 앞에 두지 않습니다.
@@ -176,25 +176,25 @@ mustflow는 LLM 제공자의 입력 캐시 적중을 보장하지 않습니다.
176
176
  - 호스트 안전: 호스트의 승인, 샌드박스, 실행 제한이 더 엄격하면 계속 유효합니다.
177
177
  - 저장소 작업 규칙: 가장 가까운 `AGENTS.md`와 `.mustflow/config/*.toml`을 따릅니다.
178
178
  - 명령 실행: `.mustflow/config/commands.toml`이 프로젝트 명령 계약입니다.
179
- - 검증 근거: `mf run` 실행 영수증과 현재 파일은 호스트 셸 직접 실행 출력보다 높은 신뢰를 가집니다.
180
- - 문맥과 선호값: `.mustflow/context/*`, `preferences.toml`, 생성 지도는 낮은 권위의 기본값입니다.
179
+ - 검증 근거: `mf run` 실행 기록과 현재 파일은 호스트 셸 직접 실행 출력보다 높은 신뢰를 가집니다.
180
+ - 컨텍스트와 선호 설정: `.mustflow/context/*`, `preferences.toml`, 생성 지도는 낮은 권위의 기본값입니다.
181
181
  - 세션과 캐시 상태: 호스트 요약, `.mustflow/cache/**`, `.mustflow/state/**`는 현재 파일이나 현재 사용자 지시보다 우선하지 않습니다.
182
182
 
183
183
  허용 목록은 더 좁은 교집합으로 줄이고, 금지 행동, 승인 요구, 개인정보 규칙, 파괴적 명령 규칙은 누적합니다. 유효 규칙이 불명확하면 추측하지 말고 멈춘 뒤 충돌을 보고합니다.
184
184
 
185
185
  ## 지침 새로고침 정책
186
186
 
187
- 긴 세션에서는 작업 시작 때 읽은 지침이 뒤쪽 대화, 도구 출력, 맥락 압축에 밀릴 수 있습니다. mustflow는 이를 대화 횟수 파일로 처리하지 않고, 지침을 다시 확인해야 하는 지점으로 다룹니다.
187
+ 긴 세션에서는 작업 시작 때 읽은 지침이 뒤쪽 대화, 도구 출력, 컨텍스트 압축에 밀릴 수 있습니다. mustflow는 이를 대화 횟수 파일로 처리하지 않고, 지침을 다시 확인해야 하는 지점으로 다룹니다.
188
188
 
189
189
  mustflow 지침은 다음 지점에서 다시 확인합니다.
190
190
 
191
191
  - 세션 시작
192
192
  - 새 작업 시작
193
193
  - 첫 파일 수정 전
194
- - 현재 작업과 명령 의도에 대한 신선한 명령 수준 새로고침이 없을 때 명령 실행 전
194
+ - 현재 작업과 명령 인텐트에 대한 최신 명령 수준 갱신이 없을 때 명령 실행 전
195
195
  - `AGENTS.md` 또는 `.mustflow/**` 수정 후
196
196
  - 작업 루트 변경 또는 하위 독립 저장소 진입 후
197
- - 맥락 압축이나 요약 후
197
+ - 컨텍스트 압축이나 요약 후
198
198
  - 최종 보고 전
199
199
  - 설정된 대화 횟수, 도구 호출 수, 출력 크기 기준 초과 시
200
200
 
@@ -207,23 +207,23 @@ mustflow 지침은 다음 지점에서 다시 확인합니다.
207
207
  - `skill`: `AGENTS.md`와 `.mustflow/skills/INDEX.md`를 다시 읽습니다.
208
208
  - `full`: mustflow 필수 읽기 순서 전체를 다시 읽습니다.
209
209
 
210
- `before_command_run`은 현재 명령 의도에 대한 신선도 확인 지점입니다. 명령 계약이 바뀌지 않았다면 같은 명령을 반복할 때마다 모든 파일을 다시 읽으라는 뜻이 아닙니다.
210
+ `before_command_run`은 현재 명령 인텐트에 대한 최신성 확인 지점입니다. 명령 계약이 바뀌지 않았다면 같은 명령을 반복할 때마다 모든 파일을 다시 읽으라는 뜻이 아닙니다.
211
211
 
212
212
  대화 횟수, 메시지 수, 세션 활동 상태를 프로젝트 파일에 쓰지 않습니다. 에이전트 호스트가 새로고침 상태를 추적한다면 Git에 포함되는 프로젝트 문서가 아니라 로컬 캐시나 호스트 상태 저장소를 사용해야 합니다. 스킬 문서는 새로고침 절차를 설명할 수 있지만, 대화 종료 훅처럼 항상 실행되는 제어 장치로 보지 않습니다.
213
213
 
214
- ## 문맥 압축 정책
214
+ ## 컨텍스트 압축 정책
215
215
 
216
- `compaction`은 기본 데이터 수집 기능이 아니라 향후 하네스나 호스트가 지켜야 할 안전 정책입니다. 기본 템플릿은 이 기능을 꺼 둔 상태에서 안전 규칙만 선언합니다.
216
+ `compaction`은 기본 데이터 수집 기능이 아니라 향후 실행 하네스나 호스트가 지켜야 할 안전 정책입니다. 기본 템플릿은 이 기능을 꺼 둔 상태에서 안전 규칙만 선언합니다.
217
217
 
218
218
  프로젝트 내에 숨겨진 내부 추론, 비밀정보, 전체 대화 전문, 전체 터미널 출력, 원본 이벤트 로그, 원본 명령 로그를 저장하지 않습니다. 향후 호스트가 요약을 만들더라도 요약은 출처가 있어야 하며, 현재 파일과 현재 사용자 지시보다 낮은 권위를 가집니다.
219
219
 
220
- ## 하네스 계약 경계
220
+ ## 실행 하네스 계약 경계
221
221
 
222
- mustflow는 자율 에이전트 실행 환경이 아닙니다. mustflow는 여러 에이전트 하네스가 저장소에 들어왔을 때 읽고 따를 수 있는 저장소 내부 작업 계약층입니다.
222
+ mustflow는 자율 에이전트 실행 환경이 아닙니다. mustflow는 여러 에이전트 실행 하네스가 저장소에 들어왔을 때 읽고 따를 수 있는 저장소 내부 작업 계약층입니다.
223
223
 
224
224
  - 사고 계약: `AGENTS.md`, 이 문서, 스킬 문서는 모델이 따라야 할 작업 절차를 설명합니다.
225
225
  - 실행 계약: `.mustflow/config/commands.toml`과 `mf run`은 안전한 명령 실행 경계를 정합니다.
226
- - 세션 계약: 실행 영수증, 제한된 체크포인트, 작은 인계 문서는 복구와 검토 근거를 남깁니다.
226
+ - 세션 계약: 실행 기록, 제한된 체크포인트, 작은 인계 문서는 복구와 검토 근거를 남깁니다.
227
227
 
228
228
  저장소가 명시적으로 선택 기능을 추가하지 않았다면 `workers/`, `personas/`, 여러 에이전트 조정 폴더, 원시 이벤트 로그, 자율 반복 실행기를 만들지 않습니다.
229
229
 
@@ -233,17 +233,17 @@ mustflow는 자율 에이전트 실행 환경이 아닙니다. mustflow는 여
233
233
 
234
234
  1. 계획: 작업 목표, 저장소 규칙, 명령 계약, 완료 기준을 읽습니다.
235
235
  2. 작업: 현재 단위에서 가장 작은 안전한 변경을 수행합니다.
236
- 3. Verify: 설정된 단발성 명령 의도만 실행하며, 가능하면 `mf run`을 사용합니다.
237
- 4. 판정: 원래 완료 기준, 변경 파일, 명령 계약, 실행 영수증을 기준으로 결과를 평가합니다.
236
+ 3. Verify: 설정된 일회성 명령 인텐트만 실행하며, 가능하면 `mf run`을 사용합니다.
237
+ 4. 판정: 원래 완료 기준, 변경 파일, 명령 계약, 실행 기록을 기준으로 결과를 평가합니다.
238
238
  5. 인계: 작업이 미완료, 차단, 계속 진행 필요 상태이면 작은 인계 내용을 남깁니다.
239
239
 
240
- 판정 단계는 작업자가 “완료”라고 말한 사실만으로 충분하다고 보지 않습니다. 원래 목표와 완료 기준, 변경 파일, 명령 계약, 실행 영수증을 근거로 판단합니다.
240
+ 판정 단계는 작업자가 “완료”라고 말한 사실만으로 충분하다고 보지 않습니다. 원래 목표와 완료 기준, 변경 파일, 명령 계약, 실행 기록을 근거로 판단합니다.
241
241
 
242
- ## 선호값 해석 정책
242
+ ## 선호 설정 해석 정책
243
243
 
244
- `.mustflow/config/preferences.toml`은 저장소별 기본 선호값입니다.
244
+ `.mustflow/config/preferences.toml`은 저장소별 기본 선호 설정입니다.
245
245
 
246
- 이 파일의 값은 사용자 직접 지시, 시스템 지침, 개발자 지침, 하위 `AGENTS.md`, 기존 파일 스타일보다 낮은 기본값입니다. 선호값을 이유로 기존 코드 전체를 재포맷하거나, 요청과 무관한 파일을 변경하거나, 운영 로그와 사용자 노출 문자열을 임의로 번역하지 않습니다.
246
+ 이 파일의 값은 사용자 직접 지시, 시스템 지침, 개발자 지침, 하위 `AGENTS.md`, 기존 파일 스타일보다 낮은 기본값입니다. 선호 설정을 이유로 기존 코드 전체를 재포맷하거나, 요청과 무관한 파일을 변경하거나, 운영 로그와 사용자 노출 문자열을 임의로 번역하지 않습니다.
247
247
 
248
248
  언어 관련 값은 대상별로 해석합니다.
249
249
 
@@ -271,7 +271,7 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
271
271
  - `git.auto_commit = false`: 사용자 요청 없이 커밋하지 않습니다.
272
272
  - `git.auto_push = false`: 사용자 요청 없이 푸시하지 않습니다.
273
273
 
274
- 이 값들은 저장소 선호값이지 권한이 아닙니다. 사용자 직접 지시, `.mustflow/config/commands.toml`, `.mustflow/config/mustflow.toml`의 승인 정책보다 우선하지 않습니다. 특히 `git.auto_commit = true`는 푸시 권한을 뜻하지 않으며, `git.auto_push = true`는 `mf init`으로 설정할 수 없습니다.
274
+ 이 값들은 저장소 선호 설정이지 권한이 아닙니다. 사용자 직접 지시, `.mustflow/config/commands.toml`, `.mustflow/config/mustflow.toml`의 승인 정책보다 우선하지 않습니다. 특히 `git.auto_commit = true`는 푸시 권한을 뜻하지 않으며, `git.auto_push = true`는 `mf init`으로 설정할 수 없습니다.
275
275
 
276
276
  스테이징, 커밋, amend, rebase, reset, push 등 Git 상태나 기록을 바꾸는 작업은 사용자가 명시적으로 요청한 경우에만 수행합니다.
277
277
 
@@ -287,18 +287,18 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
287
287
 
288
288
  ## 버전 영향 정책
289
289
 
290
- 버전 영향 설정은 저장소 선호값입니다. 버전 파일을 수정할지 판단할 때 이 값을 따르지만, 사용자 직접 지시, 호스트 안전 규칙, `.mustflow/config/mustflow.toml`의 승인 관문보다 우선하지는 않습니다.
290
+ 버전 영향 설정은 저장소 선호 설정입니다. 버전 파일을 수정할지 판단할 때 이 값을 따르지만, 사용자 직접 지시, 호스트 안전 규칙, `.mustflow/config/mustflow.toml`의 승인 관문보다 우선하지는 않습니다.
291
291
 
292
292
  코드, 템플릿, 스키마, CLI 동작, 패키지 메타데이터, 사용자에게 보이는 문서, 설치 출력, 테스트가 변경되면 `.mustflow/config/preferences.toml`의 `[release.versioning]`을 확인합니다.
293
293
 
294
294
  - `impact_check = true`: 현재 변경이 패키지나 템플릿 버전 변경을 요구하는지 보고합니다.
295
- - `suggest_bump = true`: 근거가 분명할 때 패치, 마이너, 메이저 중 알맞은 판올림을 제안합니다.
296
- - `auto_bump = true`: 영향이 분명하고 버전 기준 원본을 찾았으며 더 엄격한 사용자, 호스트, 승인 규칙이 막지 않을 때 알맞은 패키지나 템플릿 버전 판올림을 적용합니다.
297
- - `auto_bump = false`: 사용자가 버전 판올림이나 릴리스 준비 작업을 요청하지 않으면 패키지와 템플릿 버전 파일을 그대로 둡니다.
295
+ - `suggest_bump = true`: 근거가 분명할 때 패치, 마이너, 메이저 중 알맞은 버전 올림을 제안합니다.
296
+ - `auto_bump = true`: 영향이 분명하고 버전 기준 원본을 찾았으며 더 엄격한 사용자, 호스트, 승인 규칙이 막지 않을 때 알맞은 패키지나 템플릿 버전 올림을 적용합니다.
297
+ - `auto_bump = false`: 사용자가 버전 올림이나 릴리스 준비 작업을 요청하지 않으면 패키지와 템플릿 버전 파일을 그대로 둡니다.
298
298
  - `require_user_confirmation = true`: 버전 파일을 수정하기 전에 사용자에게 확인합니다.
299
299
  - `require_user_confirmation = false`: `auto_bump = true`이면 별도 확인 단계를 추가하지 않습니다.
300
300
 
301
- 버전 변경을 제안하거나 적용하기 전에는 이 저장소의 버전 기준 원본을 먼저 찾습니다. `package.json`만 버전 파일이라고 가정하지 않습니다. 저장소 언어와 프레임워크에 맞는 매니페스트, 릴리스 문서, 기존 판올림 패턴을 확인한 뒤 어떤 파일이 기준 원본이고 어떤 파일이 파생 파일인지 판단합니다.
301
+ 버전 변경을 제안하거나 적용하기 전에는 이 저장소의 버전 기준 원본을 먼저 찾습니다. `package.json`만 버전 파일이라고 가정하지 않습니다. 저장소 언어와 프레임워크에 맞는 매니페스트, 릴리스 문서, 기존 버전 올림 패턴을 확인한 뒤 어떤 파일이 기준 원본이고 어떤 파일이 파생 파일인지 판단합니다.
302
302
 
303
303
  자주 쓰이는 버전 원천 후보는 다음과 같습니다.
304
304
 
@@ -312,13 +312,13 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
312
312
  - 컨테이너, 차트, 애플리케이션: `Chart.yaml`, 이미지 라벨, 앱 매니페스트, 릴리스 노트, 배포 메타데이터.
313
313
  - mustflow 템플릿: 패키지 메타데이터, 템플릿 매니페스트, 문서 예시, 설치 버전을 검증하는 테스트.
314
314
 
315
- 버전을 바꿀 때는 `sync_*` 선호값에 따라 패키지 메타데이터, 템플릿 매니페스트 버전, 문서 예시, 테스트를 같은 변경 안에서 맞춥니다.
315
+ 버전을 바꿀 때는 `sync_*` 선호 설정에 따라 패키지 메타데이터, 템플릿 매니페스트 버전, 문서 예시, 테스트를 같은 변경 안에서 맞춥니다.
316
316
 
317
317
  ## 명령 실행 정책
318
318
 
319
319
  `.mustflow/config/commands.toml`은 실행 명령의 기준 원본입니다.
320
320
 
321
- 에이전트는 다음 조건을 모두 만족하는 명령 의도만 실행합니다.
321
+ 에이전트는 다음 조건을 모두 만족하는 명령 인텐트만 실행합니다.
322
322
 
323
323
  - `status = "configured"`
324
324
  - `lifecycle = "oneshot"`
@@ -328,11 +328,11 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
328
328
  - `argv` 또는 `mode = "shell"`과 `cmd`로 실행 명령이 선언됨
329
329
  - `cwd`가 현재 mustflow 루트 안에 있음
330
330
 
331
- 새 설정에서는 `manual_only`를 명령 의도의 `status` 값으로 사용합니다. `run_policy = "manual_only"`는 기존 설정 호환을 위해 읽을 수 있지만, 새 템플릿에서는 만들지 않습니다.
331
+ 새 설정에서는 `manual_only`를 명령 인텐트의 `status` 값으로 사용합니다. `run_policy = "manual_only"`는 기존 설정 호환을 위해 읽을 수 있지만, 새 템플릿에서는 만들지 않습니다.
332
332
 
333
- 명령 의도가 없거나 `unknown`, `not_applicable`, `manual_only`, `disabled`이면 대체 명령을 추측하지 않고 건너뛴 이유를 보고합니다.
333
+ 명령 인텐트가 없거나 `unknown`, `not_applicable`, `manual_only`, `disabled`이면 대체 명령을 추측하지 않고 건너뛴 이유를 보고합니다.
334
334
 
335
- 명령 의도 상태의 의미는 다음과 같습니다.
335
+ 명령 인텐트 상태의 의미는 다음과 같습니다.
336
336
 
337
337
  - `configured`: 실행 가능한 명령이 선언되어 있습니다.
338
338
  - `unknown`: 아직 명령 계약이 없습니다.
@@ -370,15 +370,15 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
370
370
 
371
371
  쓰기 경로가 있거나 파괴적일 수 있는 명령은 실행 전에 영향 범위를 확인합니다. 프로젝트 테스트, 빌드, 규칙 검사처럼 저장소별 동작을 수행하는 명령은 계약에 없으면 발견하거나 추측해 실행하지 않습니다. `mf help`, `mf status`, `mf doctor --json`, `mf context --json`처럼 mustflow 상태를 읽기만 하는 검사 명령은 작업 맥락 확인용으로 사용할 수 있습니다.
372
372
 
373
- 단발성 명령은 해당 실행기를 우선적으로 사용하십시오. `mf run`은 `oneshot` 의도만 실행해야 하며, 장기 실행 생명주기를 가진 의도는 거부해야 합니다. 제한 시간을 넘긴 명령은 실패로 보고하며, mustflow가 시작한 프로세스만 정리 대상입니다. 포트 번호만 보고 임의 프로세스를 종료하지 않습니다.
373
+ 일회성 명령은 해당 실행기를 우선적으로 사용하십시오. `mf run`은 `oneshot` 인텐트만 실행해야 하며, 장기 실행 생명주기를 가진 인텐트는 거부해야 합니다. 제한 시간을 넘긴 명령은 실패로 보고하며, mustflow가 시작한 프로세스만 정리 대상입니다. 포트 번호만 보고 임의 프로세스를 종료하지 않습니다.
374
374
 
375
- `mf run`으로 명령을 실행하면 `.mustflow/state/runs/latest.json`에 간결한 실행 결과 기록을 남깁니다. 자동화가 결과를 읽어야 하거나 최종 보고 근거가 필요하면 `mf run <intent> --json`을 사용합니다. 실행 결과 기록에는 의도 이름, 실제 실행 방식, 작업 디렉터리, 제한 시간, 종료 코드, 시간 초과 여부, 표준 출력/오류 끝부분이 포함됩니다.
375
+ `mf run`으로 명령을 실행하면 `.mustflow/state/runs/latest.json`에 간결한 실행 결과 기록을 남깁니다. 자동화가 결과를 읽어야 하거나 최종 보고 근거가 필요하면 `mf run <intent> --json`을 사용합니다. 실행 결과 기록에는 인텐트 이름, 실제 실행 방식, 작업 디렉터리, 제한 시간, 종료 코드, 시간 초과 여부, 표준 출력/오류 끝부분이 포함됩니다.
376
376
 
377
- `mf run` 명령 의도는 순차로 실행합니다. 설정된 다른 의도가 아직 실행 중이면 두 번째 `mf run`을 시작하지 않습니다. 비어 있지 않은 `writes`를 선언한 의도는 배타적인 검증 단계이므로, 다른 `mf run`을 실행하기 전에 종료될 때까지 기다립니다. 특히 의도가 `dist/` 같은 패키지 산출물을 다시 쓰는 경우 중요합니다. 로컬 `mf` 실행 파일이 그 산출물에서 로드될 수 있기 때문입니다.
377
+ `mf run` 명령 인텐트는 순차로 실행합니다. 설정된 다른 인텐트가 아직 실행 중이면 두 번째 `mf run`을 시작하지 않습니다. 비어 있지 않은 `writes`를 선언한 인텐트는 배타적인 검증 단계이므로, 다른 `mf run`을 실행하기 전에 종료될 때까지 기다립니다. 특히 인텐트가 `dist/` 같은 패키지 산출물을 다시 쓰는 경우 중요합니다. 로컬 `mf` 실행 파일이 그 산출물에서 로드될 수 있기 때문입니다.
378
378
 
379
379
  설치된 mustflow 문서 흐름을 갱신할 때도 원시 `mf update`를 직접 실행하지 말고 설정된 갱신 의도를 사용합니다. 먼저 `mustflow_update_dry_run`으로 계획을 확인하고, 차단된 로컬 변경이나 수동 검토 항목이 없으며 작업이 실제 적용을 요구할 때만 `mustflow_update_apply`를 실행합니다. 적용 의도는 여전히 `mf update`의 안전 정책을 따라 템플릿 매니페스트 경로, 백업, 잠금 파일 항목만 쓰고 로컬 변경은 거부합니다.
380
380
 
381
- 호스트 셸은 명령을 실행할 수 있지만, 프로젝트 명령을 직접 실행한 결과가 곧 mustflow 검증 근거가 되지는 않습니다. `mf run`을 우회한 명령 출력은 사용자가 명시적으로 수동 우회를 승인했고 최종 보고에 mustflow 실행 영수증이 없음을 밝힌 경우가 아니라면 낮은 신뢰도의 참고 정보로만 봅니다.
381
+ 호스트 셸은 명령을 실행할 수 있지만, 프로젝트 명령을 직접 실행한 결과가 곧 mustflow 검증 근거가 되지는 않습니다. `mf run`을 우회한 명령 출력은 사용자가 명시적으로 수동 우회를 승인했고 최종 보고에 mustflow 실행 기록이 없음을 밝힌 경우가 아니라면 낮은 신뢰도의 참고 정보로만 봅니다.
382
382
 
383
383
  실행 결과 기록은 검증 증거이지만 기준 원본은 아닙니다. 명령이 무엇이어야 하는지는 `.mustflow/config/commands.toml`을 따르며, 실행 결과 기록은 특정 시점에 무엇이 실행되었고 어떻게 끝났는지 보고할 때 사용합니다.
384
384
 
@@ -387,31 +387,31 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
387
387
  - 요청과 직접 관련된 파일만 수정합니다.
388
388
  - 기존 변경 사항을 되돌리지 않습니다.
389
389
  - 보호 경로, 외부 의존성, 생성 산출물은 명시 요청 없이 수정하지 않습니다.
390
- - 생성 파일은 가능하면 직접 편집하지 않고 선언된 명령 의도로 갱신합니다.
390
+ - 생성 파일은 가능하면 직접 편집하지 않고 선언된 명령 인텐트로 갱신합니다.
391
391
  - 루트의 `config/`, `docs/`, `skills/`는 프로젝트 자체 경로일 수 있으므로 mustflow 문서로 가정하지 않습니다.
392
392
  - mustflow 문서 흐름에 속한 파일은 기본적으로 `AGENTS.md`와 `.mustflow/**`입니다.
393
393
 
394
394
  ## 문서 검수 대기열
395
395
 
396
- 에이전트가 사용자에게 보이는 문서, 워크플로 문서, 템플릿 문서, 문맥 문서, 스킬 문서를 생성하거나 수정하면 사용자가 추적하지 말라고 명시한 경우를 제외하고 `mf docs review add <path>`로 해당 문서를 기록합니다. 대기열은 `.mustflow/review/docs.toml`에 저장되며 필요할 때만 생성됩니다.
396
+ 에이전트가 사용자에게 보이는 문서, 워크플로 문서, 템플릿 문서, 컨텍스트 문서, 스킬 문서를 생성하거나 수정하면 사용자가 추적하지 말라고 명시한 경우를 제외하고 `mf docs review add <path>`로 해당 문서를 기록합니다. 대기열은 `.mustflow/review/docs.toml`에 저장되며 필요할 때만 생성됩니다.
397
397
 
398
- 검수 완료 주체는 사람, LLM, 도구, 외부 프로세스일 수 있습니다. 특정 LLM 제품 목록을 고정으로 관리하지 말고, 넓은 검수자 종류와 자유 형식의 검수자 식별자, 제공자, 모델, 명령 의도, 요약만 기록합니다.
398
+ 검수 완료 주체는 사람, LLM, 도구, 외부 프로세스일 수 있습니다. 특정 LLM 제품 목록을 고정으로 관리하지 말고, 넓은 검수자 종류와 자유 형식의 검수자 식별자, 제공자, 모델, 명령 인텐트, 요약만 기록합니다.
399
399
 
400
400
  검수된 문서를 기본 목록에서 숨기되 기록을 남기려면 `mf docs review approve <path> --reviewer-kind <kind> --reviewer-id <id>`를 사용합니다. 검수자가 확신을 가지고 승인할 수 없으면 `needs-human`을, 저장소가 의도적으로 검수에서 제외하는 문서에는 `ignore`를 사용합니다.
401
401
 
402
402
  ## 검증 정책
403
403
 
404
404
  - 코드 변경 후에는 관련 테스트나 규칙 검사 의도가 `configured`인지 확인하고 실행합니다.
405
- - 문서만 변경한 경우에도 링크, 명령 의도 이름, 경로가 맞는지 확인합니다.
405
+ - 문서만 변경한 경우에도 링크, 명령 인텐트 이름, 경로가 맞는지 확인합니다.
406
406
  - 설정 파일을 변경한 경우에는 형식과 실제 경로를 함께 확인합니다.
407
407
  - mustflow 문서 흐름, 스킬, 명령 계약, 저장소 지도를 변경한 경우 가능하면 `mf check --strict`를 실행합니다.
408
408
  - 실행하지 못한 검증은 이유를 숨기지 않고 보고합니다.
409
409
 
410
- 검증 명령을 실행할 수 없을 때는 대체 명령을 추측하지 않습니다. 대신 실행하지 못한 의도 이름, 상태, 이유를 보고합니다. 명령 의도가 `configured`라도 `lifecycle = "oneshot"`이 아니면 검증 명령으로 실행하지 않고, 장기 실행 명령이라 건너뛰었다고 보고합니다.
410
+ 검증 명령을 실행할 수 없을 때는 대체 명령을 추측하지 않습니다. 대신 실행하지 못한 인텐트 이름, 상태, 이유를 보고합니다. 명령 인텐트가 `configured`라도 `lifecycle = "oneshot"`이 아니면 검증 명령으로 실행하지 않고, 장기 실행 명령이라 건너뛰었다고 보고합니다.
411
411
 
412
412
  ## 검증 선택 정책
413
413
 
414
- 검증 범위는 `.mustflow/config/preferences.toml`의 `[verification.selection]`을 참고합니다. 이 값은 명령 실행 권한이 아니라, 어떤 configured 명령 의도를 검토할지 정하는 기본값입니다.
414
+ 검증 범위는 `.mustflow/config/preferences.toml`의 `[verification.selection]`을 참고합니다. 이 값은 명령 실행 권한이 아니라, 어떤 configured 명령 인텐트를 검토할지 정하는 기본값입니다.
415
415
 
416
416
  검증은 위험 크기에 비례해야 합니다. 바뀐 표면을 덮는 `test_related`, `test_fast`, `build`, 문서 전용 검증이 설정되어 있으면 넓은 전체 테스트보다 먼저 사용합니다. 전체 테스트는 여러 영역을 가로지르는 동작, 릴리스 위험, 더 좁은 검증 누락, 또는 설정된 정책이 명시적으로 요구하는 경우에 사용합니다. 더 좁은 의도가 적절하지만 `unknown`, `manual_only`, 또는 미선언 상태라면 느린 전체 테스트를 조용히 기본값으로 삼지 말고 그 공백을 보고합니다.
417
417
 
@@ -426,7 +426,7 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
426
426
 
427
427
  동작, 보안, 데이터, 명령 계약, 릴리스 산출물, 생성 템플릿이 변경된 근거가 있으면 생략 설정으로 위험을 숨기지 않습니다. 관련 configured 의도로 올리거나, 필요한 의도가 없다고 보고합니다.
428
428
 
429
- `mf check --strict`는 기본 구조 검사에 더해 스킬 문서의 원시 셸 명령 블록, `REPO_MAP.md`의 생성 시각, 원격 저장소 주소, 브랜치 같은 변동성 높은 메타데이터, 명령 출력 제한 설정, 보존 정책, 생성 파일 크기, 원시 JSONL 로그 흔적, 최신 실행 영수증 형식을 확인합니다. 이 검사는 에이전트가 불안정한 입력이나 추측 가능한 실행 예시를 기준으로 작업하지 않도록 돕는 보조 검증입니다.
429
+ `mf check --strict`는 기본 구조 검사에 더해 스킬 문서의 원시 셸 명령 블록, `REPO_MAP.md`의 생성 시각, 원격 저장소 주소, 브랜치 같은 변동성 높은 메타데이터, 명령 출력 제한 설정, 보존 정책, 생성 파일 크기, 원시 JSONL 로그 흔적, 최신 실행 기록 형식을 확인합니다. 이 검사는 에이전트가 불안정한 입력이나 추측 가능한 실행 예시를 기준으로 작업하지 않도록 돕는 보조 검증입니다.
430
430
 
431
431
  ## 검증 약화 방지
432
432
 
@@ -437,7 +437,7 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
437
437
  - 실패하는 테스트를 삭제해 검증을 통과시키기
438
438
  - 이유 설명 없이 단언이나 기대값을 느슨하게 만들기
439
439
  - 관련 검증 의도를 건너뛰기
440
- - 실패를 피하기 위해 명령 의도를 `not_applicable`로 바꾸기
440
+ - 실패를 피하기 위해 명령 인텐트를 `not_applicable`로 바꾸기
441
441
  - 구현 뒤 완료 기준을 바꾸기
442
442
 
443
443
  의도한 동작이 변경되었거나, 기존 테스트가 잘못되었거나, 새 동작에 맞는 검증이 필요할 때는 테스트를 수정할 수 있습니다. 이 경우 최종 보고에서 이유를 설명합니다.
@@ -446,7 +446,7 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
446
446
 
447
447
  테스트는 현재 동작 계약을 검증하는 장치이지, 영구 보존해야 하는 산출물이 아닙니다.
448
448
 
449
- 새 테스트를 얼마나 적극적으로 만들지는 `.mustflow/config/preferences.toml`의 `[testing.authoring]`을 참고합니다. 기본값인 `new_test_policy = "evidence_required"`는 공개 동작 변경, 회귀 위험, 설정 규칙, 스키마 계약, 보안이나 데이터 경로처럼 동작 계약을 검증해야 한다는 근거가 있을 때만 새 테스트를 추가하라는 뜻입니다. 이 선호값은 테스트 작성 성향을 안내할 뿐이며, 필요한 검증을 약화하거나 유효한 테스트 삭제를 정당화하지 않습니다.
449
+ 새 테스트를 얼마나 적극적으로 만들지는 `.mustflow/config/preferences.toml`의 `[testing.authoring]`을 참고합니다. 기본값인 `new_test_policy = "evidence_required"`는 공개 동작 변경, 회귀 위험, 설정 규칙, 스키마 계약, 보안이나 데이터 경로처럼 동작 계약을 검증해야 한다는 근거가 있을 때만 새 테스트를 추가하라는 뜻입니다. 이 선호 설정은 테스트 작성 성향을 안내할 뿐이며, 필요한 검증을 약화하거나 유효한 테스트 삭제를 정당화하지 않습니다.
450
450
 
451
451
  에이전트는 다음 행동을 하지 않습니다.
452
452
 
@@ -458,7 +458,7 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
458
458
 
459
459
  검증하던 동작이 의도적으로 제거되었거나, 공개 계약이 변경되었거나, 테스트가 제거된 구현 세부사항만 검증하거나, 더 강한 테스트가 같은 위험을 이미 검증하거나, 스냅샷이 낡은 경우에는 테스트를 수정하거나 제거할 수 있습니다.
460
460
 
461
- 테스트를 추가, 수정, 삭제했거나 낡은 테스트 후보를 발견했다면 최종 보고에 검증하려는 동작 계약, 영향받은 테스트, 실행한 명령 의도, 건너뛴 명령 의도, 남은 테스트 위험을 포함합니다.
461
+ 테스트를 추가, 수정, 삭제했거나 낡은 테스트 후보를 발견했다면 최종 보고에 검증하려는 동작 계약, 영향받은 테스트, 실행한 명령 인텐트, 건너뛴 명령 인텐트, 남은 테스트 위험을 포함합니다.
462
462
 
463
463
  ## 예산, 승인, 격리 정책
464
464
 
@@ -474,7 +474,7 @@ Git 기록을 바꾸는 행동은 기본적으로 금지합니다.
474
474
 
475
475
  명령이 실패하면 다음을 기록합니다.
476
476
 
477
- - 실행한 명령 의도
477
+ - 실행한 명령 인텐트
478
478
  - 실제 실행된 `argv` 또는 `cmd`
479
479
  - 명령 생명주기와 제한 시간
480
480
  - 작업 디렉터리
@@ -2,7 +2,7 @@
2
2
  mustflow_doc: agents.root
3
3
  locale: ko
4
4
  canonical: false
5
- revision: 19
5
+ revision: 20
6
6
  lifecycle: user-editable
7
7
  authority: binding
8
8
  ---
@@ -21,9 +21,9 @@ mustflow가 관리하는 세부 문서와 설정은 `.mustflow/` 폴더 아래
21
21
  4. `.mustflow/config/commands.toml`
22
22
  5. `.mustflow/config/preferences.toml` (있다면)
23
23
  6. `.mustflow/skills/INDEX.md`
24
- 7. 프로젝트, 제품, 도메인, UI, 백엔드, 데이터, 보안, 운영 문맥이 필요한 경우
24
+ 7. 프로젝트, 제품, 도메인, UI, 백엔드, 데이터, 보안, 운영 컨텍스트가 필요한 경우
25
25
  `.mustflow/context/INDEX.md`
26
- 8. 문맥 색인에서 선택된 `.mustflow/context/<name>.md` 파일
26
+ 8. 컨텍스트 색인에서 선택된 `.mustflow/context/<name>.md` 파일
27
27
  9. 현재 작업과 관련된 `.mustflow/skills/<name>/SKILL.md`
28
28
  10. 넓은 저장소 탐색이 필요할 때만 `REPO_MAP.md`
29
29
  11. 관련 소스, 테스트, 문서 파일
@@ -32,18 +32,18 @@ mustflow가 관리하는 세부 문서와 설정은 `.mustflow/` 폴더 아래
32
32
 
33
33
  - 기존 변경 사항은 되돌리지 않습니다.
34
34
  - 명령어를 임의로 추측하지 않습니다.
35
- - `status = "configured"`, `lifecycle = "oneshot"`, `run_policy = "agent_allowed"`인 명령 의도만 실행합니다.
36
- - 단발성 명령은 가능하면 `mf run <intent>`로 실행하며, 자동화나 최종 보고 근거가 필요할 경우 `mf run <intent> --json` 실행 결과를 기록으로 사용합니다.
37
- - `mf run` 명령 의도는 순차적으로 실행합니다. 설정된 의도가 아직 실행 중이면 다른 `mf run`을 시작하지 말고, 특히 의도가 `dist/`처럼 비어 있지 않은 `writes`를 선언한 경우 반드시 완료될 때까지 기다립니다.
38
- - 위험을 최소화하는 가장 좁은 검증 의도를 선택합니다. 명령 계약에 관련 테스트나 빠른 검사가 있으면 넓은 전체 테스트보다 우선하며, 더 좁은 검증 의도가 없으면 느린 전체 테스트를 조용히 기본값으로 삼지 말고 누락 사실을 보고합니다.
35
+ - `status = "configured"`, `lifecycle = "oneshot"`, `run_policy = "agent_allowed"`인 명령 인텐트(intent)만 실행합니다.
36
+ - 일회성 명령은 가능하면 `mf run <intent>`로 실행하며, 자동화나 최종 보고 근거가 필요할 경우 `mf run <intent> --json` 실행 결과를 기록으로 사용합니다.
37
+ - `mf run` 명령 인텐트는 순차적으로 실행합니다. 설정된 인텐트가 아직 실행 중이면 다른 `mf run`을 시작하지 말고, 특히 인텐트가 `dist/`처럼 비어 있지 않은 `writes`를 선언한 경우 반드시 완료될 때까지 기다립니다.
38
+ - 위험을 최소화하는 가장 좁은 검증 명령 인텐트를 선택합니다. 명령 계약에 관련 테스트나 빠른 검사가 있으면 넓은 전체 테스트보다 우선하며, 더 좁은 검증 인텐트가 없으면 느린 전체 테스트를 조용히 기본값으로 삼지 말고 누락 사실을 보고합니다.
39
39
  - 개발 서버, 감시 모드, 브라우저, 대화형 명령, 백그라운드 프로세스는 직접 실행하지 않습니다.
40
- - 이 저장소가 명시적으로 설정하지 않았다면 자율 반복 실행기, 다중 작업자 조정, 페르소나 시스템, 장기 실행 하네스는 시작하지 않습니다.
40
+ - 이 저장소가 명시적으로 설정하지 않았다면 자율 반복 실행기, 다중 작업자 조정, 페르소나 시스템, 장기 실행 하네스(실행 환경)는 시작하지 않습니다.
41
41
  - 작업이 장시간 실행되거나 민감한 상태에 영향을 줄 수 있다면 `.mustflow/config/mustflow.toml`의 `[budget]`, `[approval]`, `[isolation]` 정책을 따릅니다.
42
42
  - 수정 전 현재 mustflow 루트 상태와 다음 단계를 빠르게 확인하려면 `mf doctor` 또는 `mf doctor --json`을 사용합니다. 이 명령은 파일을 쓰지 않는 진단용 명령입니다.
43
- - `mf context --json`은 읽기 전용 문맥 확인 용도로 사용할 수 있으나, 실제 작업 규칙이나 명령 계약을 대체하지 않습니다.
44
- - `.mustflow/config/preferences.toml`의 선호값은 사용자 직접 지시와 기존 파일 스타일보다 낮은 기본값으로 취급합니다.
45
- - 코드, 템플릿, 스키마, CLI 동작, 패키지 메타데이터, 사용자에게 보이는 문서, 설치 출력, 테스트가 변경되면 최종 보고 전에 `.mustflow/config/preferences.toml`의 `[release.versioning]`을 확인합니다. 버전 파일은 해당 선호값에 따라서만 변경할 수 있습니다. `auto_bump = true`이고 `require_user_confirmation = false`이면 자동으로 버전 판올림을 적용하며, 그렇지 않으면 설정에 따라 판올림을 제안하거나 수정 전에 사용자 확인을 받습니다. 버전 기준 파일이 `package.json`이라고 가정하지 말고, 제안하거나 수정하기 전에 이 저장소에서 실제 기준으로 사용하는 버전 위치를 반드시 확인합니다.
46
- - `.mustflow/context/` 파일은 프로젝트 방향과 도메인 약속을 설명하는 작업별 문맥입니다. 코드, 테스트, 명령 계약, 사용자 지시를 대신하는 최종 기준으로 보지 않습니다.
43
+ - `mf context --json`은 읽기 전용 컨텍스트 확인 용도로 사용할 수 있으나, 실제 작업 규칙이나 명령 계약을 대체하지 않습니다.
44
+ - `.mustflow/config/preferences.toml`의 선호 설정은 사용자 직접 지시와 기존 파일 스타일보다 낮은 기본값으로 취급합니다.
45
+ - 코드, 템플릿, 스키마, CLI 동작, 패키지 메타데이터, 사용자에게 보이는 문서, 설치 출력, 테스트가 변경되면 최종 보고 전에 `.mustflow/config/preferences.toml`의 `[release.versioning]`을 확인합니다. 버전 파일은 해당 선호 설정에 따라서만 변경할 수 있습니다. `auto_bump = true`이고 `require_user_confirmation = false`이면 자동으로 버전 올림(버전 범프)을 적용하며, 그렇지 않으면 설정에 따라 버전 올림을 제안하거나 수정 전에 사용자 확인을 받습니다. 버전 기준 파일이 `package.json`이라고 가정하지 말고, 제안하거나 수정하기 전에 이 저장소에서 실제 기준으로 사용하는 버전 위치를 반드시 확인합니다.
46
+ - `.mustflow/context/` 파일은 프로젝트 방향과 도메인 약속을 설명하는 작업별 컨텍스트입니다. 코드, 테스트, 명령 계약, 사용자 지시를 대신하는 최종 기준으로 보지 않습니다.
47
47
  - `DESIGN.md`가 있으면 UI, 시각 디자인, 레이아웃, 디자인 토큰, 접근성 작업에서만 읽습니다. 없는 `DESIGN.md`를 임의로 생성하지 않습니다.
48
48
  - 작업과 맞는 스킬이 있으면 해당 `SKILL.md`를 읽고 따릅니다.
49
49
  - 파일을 만들거나 수정하기 전에 `.mustflow/skills/INDEX.md`를 기준으로 현재 작업에 적용 가능한 스킬이 하나 이상 있는지 판단합니다. 이 스킬 선택 단계는 작업이 작거나 명백해 보이는 경우에도 반드시 거쳐야 합니다.
@@ -71,7 +71,7 @@ mustflow가 관리하는 세부 문서와 설정은 `.mustflow/` 폴더 아래
71
71
  - 현재 사용자 직접 지시는 안전하지 않은 경우가 아니라면 작업 목표를 결정합니다.
72
72
  - 호스트의 안전 규칙과 승인 절차는 계속 유효합니다.
73
73
  - 저장소 작업 규칙은 가장 가까운 `AGENTS.md`와 `.mustflow/config/*.toml`에서 가져옵니다.
74
- - 프로젝트 검증 명령은 설정된 mustflow 명령 의도를 사용해야 합니다.
74
+ - 프로젝트 검증 명령은 설정된 mustflow 명령 인텐트를 사용해야 합니다.
75
75
  - 개인정보, 비밀 정보, 파괴적 명령, Git 푸시 규칙은 더 엄격한 쪽을 따릅니다.
76
76
  - 생성된 상태, 요약, 캐시는 현재 파일이나 현재 사용자 지시보다 우선하지 않습니다.
77
77
 
@@ -79,7 +79,7 @@ mustflow가 관리하는 세부 문서와 설정은 `.mustflow/` 폴더 아래
79
79
 
80
80
  ## 지침 새로고침 지점
81
81
 
82
- - 긴 세션에서는 첫 수정 전, 현재 명령 의도에 대한 신선한 명령 확인이 없을 때의 명령 실행 전, 문맥 압축 후, `AGENTS.md` 또는 `.mustflow/**` 수정 후, 루트 변경 후, 최종 보고 전에 mustflow 지침을 다시 확인합니다.
82
+ - 긴 세션에서는 첫 수정 전, 현재 명령 인텐트에 대한 최신 명령 확인이 없을 때의 명령 실행 전, 컨텍스트 압축 후, `AGENTS.md` 또는 `.mustflow/**` 수정 후, 루트 변경 후, 최종 보고 전에 mustflow 지침을 다시 확인합니다.
83
83
  - `.mustflow/config/mustflow.toml`의 `[refresh]` 정책을 기준으로 가벼운 확인, 명령 확인, 스킬 확인, 전체 확인 중 필요한 수준을 판단합니다.
84
84
  - 대화 횟수나 세션 활동 상태를 프로젝트 파일에 저장하지 않습니다. 세션 새로고침 상태는 로컬 캐시나 호스트 애플리케이션이 관리합니다.
85
85
 
@@ -1,6 +1,6 @@
1
1
  id = "default"
2
2
  name = "default"
3
- version = "2.22.9"
3
+ version = "2.22.12"
4
4
  description = "Minimal workflow for LLM agents to read, edit, and verify their work in a repository."
5
5
  common_root = "common"
6
6
  locales_root = "locales"