mustflow 2.107.3 → 2.107.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/cli/commands/init.js +49 -1
- package/dist/cli/commands/run/execution.js +7 -0
- package/dist/cli/commands/run/executor.js +7 -0
- package/dist/cli/commands/verify.js +14 -0
- package/dist/cli/commands/workspace.js +106 -16
- package/dist/cli/i18n/en.js +6 -1
- package/dist/cli/i18n/es.js +6 -1
- package/dist/cli/i18n/fr.js +6 -1
- package/dist/cli/i18n/hi.js +6 -1
- package/dist/cli/i18n/ko.js +6 -1
- package/dist/cli/i18n/zh.js +6 -1
- package/dist/cli/index.js +8 -0
- package/dist/cli/lib/agent-context.js +7 -0
- package/dist/cli/lib/repo-map.js +14 -0
- package/dist/cli/lib/run-plan.js +7 -0
- package/dist/core/change-verification.js +7 -0
- package/dist/core/verification-scheduler.js +7 -0
- package/package.json +1 -1
- package/schemas/README.md +3 -3
- package/schemas/workspace-status.schema.json +4 -2
- package/templates/default/common/.mustflow/config/mustflow.toml +3 -3
- package/templates/default/i18n.toml +18 -0
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +11 -0
- package/templates/default/locales/en/.mustflow/skills/cli-option-contract-review/SKILL.md +147 -0
- package/templates/default/locales/en/.mustflow/skills/routes.toml +18 -0
- package/templates/default/locales/en/.mustflow/skills/third-party-api-integration-review/SKILL.md +188 -0
- package/templates/default/locales/en/.mustflow/skills/website-task-friction-review/SKILL.md +139 -0
- package/templates/default/manifest.toml +18 -1
package/README.md
CHANGED
|
@@ -269,6 +269,7 @@ mf run mustflow_update_apply
|
|
|
269
269
|
| `mf onboard commands` | Suggest review-only command-intent snippets from package.json, Makefile, or justfile without writing files or granting command authority. |
|
|
270
270
|
| `mf next` | Inspect install state, changed files, verification coverage, and command-contract gaps, then print the next safe mustflow action without running commands. |
|
|
271
271
|
| `mf evidence` | Summarize changed-file verification requirements, risk-priced evidence assessment, latest failure replay capsule, conflict ledger, receipts, remaining risks, and gaps without running commands. |
|
|
272
|
+
| `mf workspace scan` | Scan a `projects/` directory for nested repositories without requiring workspace configuration or granting command authority. |
|
|
272
273
|
| `mf workspace status` | Inspect configured workspace roots and nested repository contract readiness without granting parent-to-child command authority. |
|
|
273
274
|
| `mf workspace command-catalog` | Aggregate per-repository command intent availability with safe `mf run` entrypoints and no raw command strings. |
|
|
274
275
|
| `mf workspace verify --changed --plan-only` | Aggregate per-repository changed-file verification plans without running commands or granting parent-to-child command authority. |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readSync } from 'node:fs';
|
|
1
|
+
import { existsSync, lstatSync, readSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { stdin as processStdin, stdout as processStdout } from 'node:process';
|
|
4
4
|
import { createInterface } from 'node:readline/promises';
|
|
@@ -9,6 +9,7 @@ import { isLocaleTag } from '../lib/locale-tags.js';
|
|
|
9
9
|
import { MANIFEST_LOCK_RELATIVE_PATH, sha256File } from '../lib/manifest-lock.js';
|
|
10
10
|
import { formatCliOptionParseError, hasCliOptionToken, parseCliOptions } from '../lib/option-parser.js';
|
|
11
11
|
import { isCommitMessageStyle, isTestAuthoringPolicy } from '../lib/preferences-options.js';
|
|
12
|
+
import { discoverNestedRepositories, getRepoMapConfig } from '../lib/repo-map.js';
|
|
12
13
|
import { getDefaultTemplate, getTemplateFiles } from '../lib/templates.js';
|
|
13
14
|
const MUSTFLOW_BLOCK_START = '<!-- mustflow:start schema=1 -->';
|
|
14
15
|
const MUSTFLOW_BLOCK_END = '<!-- mustflow:end -->';
|
|
@@ -17,6 +18,8 @@ const GITIGNORE_FRAGMENT_RELATIVE_PATH = 'gitignore.mustflow';
|
|
|
17
18
|
const NON_INTERACTIVE_PROMPT_MAX_BYTES = 16 * 1024;
|
|
18
19
|
const NON_INTERACTIVE_PROMPT_MAX_RESPONSES = 64;
|
|
19
20
|
const NON_INTERACTIVE_PROMPT_READ_CHUNK_BYTES = 4096;
|
|
21
|
+
const WORKSPACE_INIT_REPOSITORY_THRESHOLD = 2;
|
|
22
|
+
const DEFAULT_WORKSPACE_SCAN_ROOT = 'projects';
|
|
20
23
|
const LOCALE_LABELS = {
|
|
21
24
|
en: 'English',
|
|
22
25
|
ko: 'Korean',
|
|
@@ -540,6 +543,47 @@ function shouldPromptForInit(args, options) {
|
|
|
540
543
|
}
|
|
541
544
|
return Boolean(processStdin.isTTY && processStdout.isTTY);
|
|
542
545
|
}
|
|
546
|
+
function hasGitMarker(directoryPath) {
|
|
547
|
+
try {
|
|
548
|
+
const marker = lstatSync(path.join(directoryPath, '.git'));
|
|
549
|
+
return marker.isDirectory() || marker.isFile();
|
|
550
|
+
}
|
|
551
|
+
catch {
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
function hasInstalledMustflowMarker(directoryPath) {
|
|
556
|
+
return existsSync(path.join(directoryPath, 'AGENTS.md')) || existsSync(path.join(directoryPath, '.mustflow'));
|
|
557
|
+
}
|
|
558
|
+
function countDefaultWorkspaceRepositories(targetRoot) {
|
|
559
|
+
const config = getRepoMapConfig(targetRoot);
|
|
560
|
+
const repositories = discoverNestedRepositories(targetRoot, { ...config.map, includeNested: true }, {
|
|
561
|
+
...config.workspace,
|
|
562
|
+
enabled: true,
|
|
563
|
+
roots: [DEFAULT_WORKSPACE_SCAN_ROOT],
|
|
564
|
+
});
|
|
565
|
+
return repositories.length;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* mf:anchor cli.init.workspace-root-guard
|
|
569
|
+
* purpose: Detect multi-repository workspace roots before installing repository-scoped mustflow files.
|
|
570
|
+
* search: mf init, workspace root, projects directory, nested repositories, install guard
|
|
571
|
+
* invariant: Non-git workspace folders with multiple nested repositories should not receive repo-scoped AGENTS.md by default.
|
|
572
|
+
* risk: config, state
|
|
573
|
+
*/
|
|
574
|
+
function shouldRefuseWorkspaceRootInit(targetRoot) {
|
|
575
|
+
if (hasGitMarker(targetRoot) || hasInstalledMustflowMarker(targetRoot)) {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
return countDefaultWorkspaceRepositories(targetRoot) >= WORKSPACE_INIT_REPOSITORY_THRESHOLD;
|
|
579
|
+
}
|
|
580
|
+
function printWorkspaceRootInitRefusal(targetRoot, reporter, lang) {
|
|
581
|
+
reporter.stderr(t(lang, 'init.error.workspaceRootDetected', {
|
|
582
|
+
count: countDefaultWorkspaceRepositories(targetRoot),
|
|
583
|
+
projectsDir: DEFAULT_WORKSPACE_SCAN_ROOT,
|
|
584
|
+
}));
|
|
585
|
+
reporter.stderr(t(lang, 'init.error.workspaceRootGuidance'));
|
|
586
|
+
}
|
|
543
587
|
async function promptChoice(reader, reporter, lang, question, choices, defaultValue) {
|
|
544
588
|
const defaultIndex = Math.max(0, choices.findIndex((choice) => choice.value === defaultValue));
|
|
545
589
|
reporter.stdout('');
|
|
@@ -944,6 +988,10 @@ export async function runInit(args, reporter, lang = 'en') {
|
|
|
944
988
|
}
|
|
945
989
|
const targetRoot = process.cwd();
|
|
946
990
|
let template;
|
|
991
|
+
if (shouldRefuseWorkspaceRootInit(targetRoot)) {
|
|
992
|
+
printWorkspaceRootInitRefusal(targetRoot, reporter, lang);
|
|
993
|
+
return 1;
|
|
994
|
+
}
|
|
947
995
|
try {
|
|
948
996
|
template = getDefaultTemplate();
|
|
949
997
|
}
|
|
@@ -174,6 +174,13 @@ function createRunProgressReporter(input) {
|
|
|
174
174
|
}
|
|
175
175
|
};
|
|
176
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* mf:anchor cli.run.execute
|
|
179
|
+
* purpose: Coordinate approved run-plan execution with active locks, environment policy, output limits, and write drift.
|
|
180
|
+
* search: run plan execution, active lock, environment policy, write drift, receipt
|
|
181
|
+
* invariant: Trusted root, runnable plan, active lock, and receipt tracking remain one preflight chain.
|
|
182
|
+
* risk: config, security, state
|
|
183
|
+
*/
|
|
177
184
|
export async function executeRunCommand(request, reporter, lang = 'en', options = {}) {
|
|
178
185
|
const executorStartedAtMs = performance.now();
|
|
179
186
|
const profiler = new RunProfiler();
|
|
@@ -27,6 +27,13 @@ function normalizeSpawnedCommandInput(command) {
|
|
|
27
27
|
windowsVerbatimArguments: false,
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* mf:anchor cli.run.process-lifecycle
|
|
32
|
+
* purpose: Spawn configured commands with bounded output and deterministic timeout termination.
|
|
33
|
+
* search: child process, timeout, process tree, output limit, kill after
|
|
34
|
+
* invariant: Timed-out or output-limited commands must stop the process tree and return bounded stdout and stderr snapshots.
|
|
35
|
+
* risk: state, security
|
|
36
|
+
*/
|
|
30
37
|
function runSpawnedCommandStreaming(command, cwd, env, timeoutSeconds, killAfterSeconds, maxOutputBytes, stdoutTailBytes, stderrTailBytes, reporter, streamOutput, enforceOutputLimit) {
|
|
31
38
|
if (command.executable.trim().length === 0) {
|
|
32
39
|
return Promise.resolve({
|
|
@@ -600,6 +600,13 @@ function toParallelismReport(settings) {
|
|
|
600
600
|
note: settings.note,
|
|
601
601
|
};
|
|
602
602
|
}
|
|
603
|
+
/**
|
|
604
|
+
* mf:anchor cli.verify.receipt-manifest
|
|
605
|
+
* purpose: Persist verify receipts, latest summary, failure evidence, and completion verdict in one state update boundary.
|
|
606
|
+
* search: mf verify, receipt manifest, latest run, completion verdict, failure fingerprint
|
|
607
|
+
* invariant: Receipt paths and verdict evidence must share the same verification_plan_id.
|
|
608
|
+
* risk: state, data_consistency
|
|
609
|
+
*/
|
|
603
610
|
function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks, scopeDiffRisks, validationRatchetRisks, reproEvidence, externalChecks) {
|
|
604
611
|
const statePaths = createVerifyRunStatePaths(projectRoot);
|
|
605
612
|
const receipts = [];
|
|
@@ -770,6 +777,13 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
770
777
|
updateRunReceiptState(projectRoot, resolveRunReceiptRetentionPolicy(readMustflowConfigIfExists(projectRoot)));
|
|
771
778
|
return outputWithReceiptPaths;
|
|
772
779
|
}
|
|
780
|
+
/**
|
|
781
|
+
* mf:anchor cli.verify.output-model
|
|
782
|
+
* purpose: Create the verification output from classification, command contract, selected intents, and evidence risk models.
|
|
783
|
+
* search: verification output, risk assessment, source anchors, validation ratchet, external evidence
|
|
784
|
+
* invariant: Completion verdict risk counts must be derived from the same report and results that produce receipts.
|
|
785
|
+
* risk: state, data_consistency
|
|
786
|
+
*/
|
|
773
787
|
async function createVerifyOutput(input, planSource, projectRoot, lang, reproEvidence = null, externalChecks = [], parallelism = DEFAULT_VERIFY_PARALLELISM, parallelismReport = null) {
|
|
774
788
|
const contract = readCommandContract(projectRoot);
|
|
775
789
|
const report = createChangeVerificationReport(input.classificationReport, contract, projectRoot);
|
|
@@ -9,9 +9,15 @@ import { resolveMustflowRoot } from '../lib/project-root.js';
|
|
|
9
9
|
import { getRepoMapConfig, discoverNestedRepositories } from '../lib/repo-map.js';
|
|
10
10
|
import { createRunPlan } from '../lib/run-plan.js';
|
|
11
11
|
import { readCommandContract, readString, readStringArray } from '../../core/config-loading.js';
|
|
12
|
+
const DEFAULT_WORKSPACE_SCAN_ROOT = 'projects';
|
|
13
|
+
const WORKSPACE_SCAN_SCHEMA_VERSION = '1';
|
|
12
14
|
const WORKSPACE_STATUS_SCHEMA_VERSION = '1';
|
|
13
15
|
const WORKSPACE_COMMAND_CATALOG_SCHEMA_VERSION = '1';
|
|
14
16
|
const WORKSPACE_VERIFICATION_PLAN_SCHEMA_VERSION = '1';
|
|
17
|
+
const WORKSPACE_SCAN_OPTIONS = [
|
|
18
|
+
{ name: '--json', kind: 'boolean' },
|
|
19
|
+
{ name: '--projects-dir', kind: 'string' },
|
|
20
|
+
];
|
|
15
21
|
const WORKSPACE_STATUS_OPTIONS = [{ name: '--json', kind: 'boolean' }];
|
|
16
22
|
const WORKSPACE_COMMAND_CATALOG_OPTIONS = [{ name: '--json', kind: 'boolean' }];
|
|
17
23
|
const WORKSPACE_VERIFY_OPTIONS = [
|
|
@@ -24,6 +30,7 @@ function getWorkspaceHelp(lang = 'en') {
|
|
|
24
30
|
usage: 'mf workspace <action> [options]',
|
|
25
31
|
summary: t(lang, 'workspace.help.summary'),
|
|
26
32
|
commands: [
|
|
33
|
+
{ label: 'scan', description: t(lang, 'workspace.help.action.scan') },
|
|
27
34
|
{ label: 'status', description: t(lang, 'workspace.help.action.status') },
|
|
28
35
|
{ label: 'command-catalog', description: t(lang, 'workspace.help.action.commandCatalog') },
|
|
29
36
|
{ label: 'verify', description: t(lang, 'workspace.help.action.verify') },
|
|
@@ -31,10 +38,13 @@ function getWorkspaceHelp(lang = 'en') {
|
|
|
31
38
|
options: [
|
|
32
39
|
{ label: '--changed', description: t(lang, 'classify.help.option.changed') },
|
|
33
40
|
{ label: '--plan-only', description: t(lang, 'verify.help.option.planOnly') },
|
|
41
|
+
{ label: '--projects-dir <path>', description: t(lang, 'workspace.help.option.projectsDir') },
|
|
34
42
|
{ label: '--json', description: t(lang, 'cli.option.json') },
|
|
35
43
|
{ label: '-h, --help', description: t(lang, 'cli.option.help') },
|
|
36
44
|
],
|
|
37
45
|
examples: [
|
|
46
|
+
'mf workspace scan --json',
|
|
47
|
+
'mf workspace scan --projects-dir projects --json',
|
|
38
48
|
'mf workspace status --json',
|
|
39
49
|
'mf workspace command-catalog --json',
|
|
40
50
|
'mf workspace verify --changed --plan-only --json',
|
|
@@ -63,6 +73,13 @@ function createWorkspaceVerificationPlanPolicy() {
|
|
|
63
73
|
selected_intents_run_via: 'mf run <intent>',
|
|
64
74
|
};
|
|
65
75
|
}
|
|
76
|
+
function createAdHocWorkspaceConfig(base, projectsDir) {
|
|
77
|
+
return {
|
|
78
|
+
...base,
|
|
79
|
+
enabled: true,
|
|
80
|
+
roots: [projectsDir],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
66
83
|
function getIntentNames(intents) {
|
|
67
84
|
return Object.keys(intents).sort((left, right) => left.localeCompare(right));
|
|
68
85
|
}
|
|
@@ -136,6 +153,13 @@ function summarizeRepository(projectRoot, repository) {
|
|
|
136
153
|
issues,
|
|
137
154
|
};
|
|
138
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* mf:anchor cli.workspace.status-read-model
|
|
158
|
+
* purpose: Summarize nested repositories and command contracts without granting parent-root command authority.
|
|
159
|
+
* search: workspace status, nested repositories, command contract, read only, runnable intents
|
|
160
|
+
* invariant: Workspace status reports observable repo facts and never executes or authorizes child-repository commands.
|
|
161
|
+
* risk: config, state
|
|
162
|
+
*/
|
|
139
163
|
function createWorkspaceStatusOutput() {
|
|
140
164
|
const projectRoot = resolveMustflowRoot();
|
|
141
165
|
const config = getRepoMapConfig(projectRoot);
|
|
@@ -148,18 +172,35 @@ function createWorkspaceStatusOutput() {
|
|
|
148
172
|
schema_version: WORKSPACE_STATUS_SCHEMA_VERSION,
|
|
149
173
|
command: 'workspace status',
|
|
150
174
|
mustflow_root: projectRoot,
|
|
151
|
-
workspace:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
175
|
+
workspace: workspaceConfigOutput(config.workspace),
|
|
176
|
+
policy: createWorkspaceStatusPolicy(),
|
|
177
|
+
repository_count: repositories.length,
|
|
178
|
+
repositories,
|
|
179
|
+
issues,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function createWorkspaceScanOutput(projectsDir) {
|
|
183
|
+
const projectRoot = resolveMustflowRoot();
|
|
184
|
+
const config = getRepoMapConfig(projectRoot);
|
|
185
|
+
const workspace = createAdHocWorkspaceConfig(config.workspace, projectsDir);
|
|
186
|
+
const repositories = discoverNestedRepositories(projectRoot, { ...config.map, includeNested: true }, workspace).map((repository) => summarizeRepository(projectRoot, repository));
|
|
187
|
+
const issues = repositories.length === 0
|
|
188
|
+
? [t('en', 'workspace.scan.issue.noneDiscovered', { projectsDir })]
|
|
189
|
+
: [];
|
|
190
|
+
return {
|
|
191
|
+
schema_version: WORKSPACE_SCAN_SCHEMA_VERSION,
|
|
192
|
+
command: 'workspace scan',
|
|
193
|
+
mustflow_root: projectRoot,
|
|
194
|
+
workspace: workspaceConfigOutput(workspace),
|
|
159
195
|
policy: createWorkspaceStatusPolicy(),
|
|
160
196
|
repository_count: repositories.length,
|
|
161
197
|
repositories,
|
|
162
198
|
issues,
|
|
199
|
+
projects_dir: projectsDir,
|
|
200
|
+
next_actions: [
|
|
201
|
+
'mf init inside one target repository',
|
|
202
|
+
'mf workspace status --json after configuring workspace roots',
|
|
203
|
+
],
|
|
163
204
|
};
|
|
164
205
|
}
|
|
165
206
|
function readWorkspaceRepositories(projectRoot) {
|
|
@@ -171,12 +212,12 @@ function readWorkspaceRepositories(projectRoot) {
|
|
|
171
212
|
}
|
|
172
213
|
function workspaceConfigOutput(config) {
|
|
173
214
|
return {
|
|
174
|
-
enabled: config.
|
|
175
|
-
roots: config.
|
|
176
|
-
max_depth: config.
|
|
177
|
-
max_repositories: config.
|
|
178
|
-
follow_symlinks: config.
|
|
179
|
-
stop_at_repository_root: config.
|
|
215
|
+
enabled: config.enabled,
|
|
216
|
+
roots: config.roots,
|
|
217
|
+
max_depth: config.maxDepth,
|
|
218
|
+
max_repositories: config.maxRepositories,
|
|
219
|
+
follow_symlinks: config.followSymlinks,
|
|
220
|
+
stop_at_repository_root: config.stopAtRepositoryRoot,
|
|
180
221
|
};
|
|
181
222
|
}
|
|
182
223
|
function createWorkspaceIssues(config, repositoryCount) {
|
|
@@ -295,7 +336,7 @@ function createWorkspaceCommandCatalogOutput() {
|
|
|
295
336
|
schema_version: WORKSPACE_COMMAND_CATALOG_SCHEMA_VERSION,
|
|
296
337
|
command: 'workspace command-catalog',
|
|
297
338
|
mustflow_root: projectRoot,
|
|
298
|
-
workspace: workspaceConfigOutput(config),
|
|
339
|
+
workspace: workspaceConfigOutput(config.workspace),
|
|
299
340
|
policy: createWorkspaceStatusPolicy(),
|
|
300
341
|
repository_count: repositories.length,
|
|
301
342
|
total_intent_count: repositories.reduce((total, repository) => total + repository.intent_count, 0),
|
|
@@ -331,6 +372,13 @@ function selectedIntentsForVerificationReport(repositoryPath, report) {
|
|
|
331
372
|
conflict_count: entry.conflicts.length,
|
|
332
373
|
}));
|
|
333
374
|
}
|
|
375
|
+
/**
|
|
376
|
+
* mf:anchor cli.workspace.verify-plan
|
|
377
|
+
* purpose: Build per-repository verification plans from each child repository's own command contract.
|
|
378
|
+
* search: workspace verify, changed files, plan only, command contract, child repository
|
|
379
|
+
* invariant: Workspace verification output selects intents per repository and does not run raw commands from the parent root.
|
|
380
|
+
* risk: config, state
|
|
381
|
+
*/
|
|
334
382
|
function createVerificationRepository(projectRoot, repository) {
|
|
335
383
|
const repositoryRoot = path.resolve(projectRoot, repository.relativePath);
|
|
336
384
|
const commandSurface = summarizeCommandSurface(repositoryRoot, repository);
|
|
@@ -391,7 +439,7 @@ function createWorkspaceVerificationPlanOutput() {
|
|
|
391
439
|
schema_version: WORKSPACE_VERIFICATION_PLAN_SCHEMA_VERSION,
|
|
392
440
|
command: 'workspace verify',
|
|
393
441
|
mustflow_root: projectRoot,
|
|
394
|
-
workspace: workspaceConfigOutput(config),
|
|
442
|
+
workspace: workspaceConfigOutput(config.workspace),
|
|
395
443
|
policy: createWorkspaceVerificationPlanPolicy(),
|
|
396
444
|
repository_count: repositories.length,
|
|
397
445
|
total_changed_file_count: repositories.reduce((total, repository) => total + (repository.changed_file_count ?? 0), 0),
|
|
@@ -402,6 +450,29 @@ function createWorkspaceVerificationPlanOutput() {
|
|
|
402
450
|
issues: createWorkspaceIssues(config, repositories.length),
|
|
403
451
|
};
|
|
404
452
|
}
|
|
453
|
+
function renderWorkspaceScan(output) {
|
|
454
|
+
const lines = [
|
|
455
|
+
'mustflow workspace scan',
|
|
456
|
+
`mustflow root: ${output.mustflow_root}`,
|
|
457
|
+
`projects dir: ${output.projects_dir}`,
|
|
458
|
+
`repositories: ${output.repository_count}`,
|
|
459
|
+
'',
|
|
460
|
+
];
|
|
461
|
+
if (output.repositories.length === 0) {
|
|
462
|
+
lines.push(`No nested repositories discovered under ${output.projects_dir}.`);
|
|
463
|
+
return lines.join('\n');
|
|
464
|
+
}
|
|
465
|
+
for (const repository of output.repositories) {
|
|
466
|
+
lines.push(`- ${repository.relative_path} (${repository.status})`);
|
|
467
|
+
lines.push(` mustflow: ${repository.mustflow ? 'yes' : 'no'}`);
|
|
468
|
+
lines.push(` command contract: ${repository.command_contract.path ?? 'missing'}`);
|
|
469
|
+
}
|
|
470
|
+
lines.push('', 'Next actions:');
|
|
471
|
+
for (const action of output.next_actions) {
|
|
472
|
+
lines.push(`- ${action}`);
|
|
473
|
+
}
|
|
474
|
+
return lines.join('\n');
|
|
475
|
+
}
|
|
405
476
|
function renderWorkspaceStatus(output) {
|
|
406
477
|
const lines = [
|
|
407
478
|
'mustflow workspace status',
|
|
@@ -488,6 +559,22 @@ function renderWorkspaceVerificationPlan(output) {
|
|
|
488
559
|
}
|
|
489
560
|
return lines.join('\n');
|
|
490
561
|
}
|
|
562
|
+
function runWorkspaceScan(args, reporter, lang) {
|
|
563
|
+
if (hasCliOptionToken(args, '--help', ['-h'])) {
|
|
564
|
+
reporter.stdout(getWorkspaceHelp(lang));
|
|
565
|
+
return 0;
|
|
566
|
+
}
|
|
567
|
+
const parsed = parseCliOptions(args, WORKSPACE_SCAN_OPTIONS);
|
|
568
|
+
if (parsed.error) {
|
|
569
|
+
printUsageError(reporter, formatCliOptionParseError(parsed.error, lang), 'mf workspace --help', getWorkspaceHelp(lang), lang);
|
|
570
|
+
return 1;
|
|
571
|
+
}
|
|
572
|
+
const projectsDirValue = parsed.values.get('--projects-dir');
|
|
573
|
+
const projectsDir = typeof projectsDirValue === 'string' ? projectsDirValue : DEFAULT_WORKSPACE_SCAN_ROOT;
|
|
574
|
+
const output = createWorkspaceScanOutput(projectsDir);
|
|
575
|
+
reporter.stdout(hasParsedCliOption(parsed, '--json') ? JSON.stringify(output, null, 2) : renderWorkspaceScan(output));
|
|
576
|
+
return 0;
|
|
577
|
+
}
|
|
491
578
|
function runWorkspaceStatus(args, reporter, lang) {
|
|
492
579
|
if (hasCliOptionToken(args, '--help', ['-h'])) {
|
|
493
580
|
reporter.stdout(getWorkspaceHelp(lang));
|
|
@@ -552,6 +639,9 @@ export function runWorkspace(args, reporter, lang = 'en') {
|
|
|
552
639
|
printUsageError(reporter, t(lang, 'cli.error.unknownOption', { option: action }), 'mf workspace --help', getWorkspaceHelp(lang), lang);
|
|
553
640
|
return 1;
|
|
554
641
|
}
|
|
642
|
+
if (action === 'scan') {
|
|
643
|
+
return runWorkspaceScan(rest, reporter, lang);
|
|
644
|
+
}
|
|
555
645
|
if (action === 'status') {
|
|
556
646
|
return runWorkspaceStatus(rest, reporter, lang);
|
|
557
647
|
}
|
package/dist/cli/i18n/en.js
CHANGED
|
@@ -135,14 +135,17 @@ export const enMessages = {
|
|
|
135
135
|
"evidence.section.gaps": "Gaps",
|
|
136
136
|
"evidence.section.remainingRisks": "Remaining risks",
|
|
137
137
|
"workspace.help.summary": "Inspect configured workspace roots and nested repository contract readiness without granting command authority.",
|
|
138
|
+
"workspace.help.action.scan": "Scan a projects directory for nested repositories without requiring workspace configuration",
|
|
138
139
|
"workspace.help.action.status": "Print discovered nested repositories and their local mustflow contract status",
|
|
139
140
|
"workspace.help.action.commandCatalog": "Print per-repository command intent availability without raw command strings",
|
|
140
141
|
"workspace.help.action.verify": "Print per-repository changed-file verification plans without running commands",
|
|
142
|
+
"workspace.help.option.projectsDir": "Select the child directory to scan; default: projects",
|
|
141
143
|
"workspace.help.exit.ok": "Workspace status was inspected",
|
|
142
|
-
"workspace.error.missingAction": "Specify a workspace action: status, command-catalog, or verify",
|
|
144
|
+
"workspace.error.missingAction": "Specify a workspace action: scan, status, command-catalog, or verify",
|
|
143
145
|
"workspace.error.unknownAction": "Unknown workspace action: {action}",
|
|
144
146
|
"workspace.error.verifyRequiresChanged": "workspace verify requires --changed",
|
|
145
147
|
"workspace.error.verifyRequiresPlanOnly": "workspace verify requires --plan-only",
|
|
148
|
+
"workspace.scan.issue.noneDiscovered": "No nested git repositories were discovered under {projectsDir}.",
|
|
146
149
|
"context.help.summary": "Print the agent context for the current mustflow root.",
|
|
147
150
|
"context.help.option.json": "Print machine-readable context JSON",
|
|
148
151
|
"context.help.option.cacheProfile": "Print a prompt-cache profile: stable, task, volatile, or all",
|
|
@@ -680,6 +683,8 @@ Read these files before working:
|
|
|
680
683
|
"init.error.unsupportedPreference": "Unsupported init preference setting: {key}",
|
|
681
684
|
"init.error.promptInputTooLarge": "Interactive init stdin input is too large; expected at most {maxBytes} bytes.",
|
|
682
685
|
"init.error.promptInputTooManyResponses": "Interactive init stdin input has too many responses; expected at most {maxResponses} lines.",
|
|
686
|
+
"init.error.workspaceRootDetected": "This directory looks like a multi-repository workspace, not a single repository: found {count} git repositories under {projectsDir}.",
|
|
687
|
+
"init.error.workspaceRootGuidance": "Run mf workspace scan --json here, or run mf init inside one target repository.",
|
|
683
688
|
"init.prompt.locale": "Which language should mustflow documents use?",
|
|
684
689
|
"init.prompt.profile": "Which project profile should mustflow use?",
|
|
685
690
|
"init.prompt.agentLang": "Which language should agents use for final reports?",
|
package/dist/cli/i18n/es.js
CHANGED
|
@@ -135,14 +135,17 @@ export const esMessages = {
|
|
|
135
135
|
"evidence.section.gaps": "Brechas",
|
|
136
136
|
"evidence.section.remainingRisks": "Riesgos restantes",
|
|
137
137
|
"workspace.help.summary": "Inspecciona raíces workspace configuradas y preparación de contratos anidados sin conceder autoridad de comandos.",
|
|
138
|
+
"workspace.help.action.scan": "Escanea un directorio projects en busca de repositorios anidados sin requerir configuración de workspace",
|
|
138
139
|
"workspace.help.action.status": "Imprime repositorios anidados descubiertos y su estado de contrato mustflow local",
|
|
139
140
|
"workspace.help.action.commandCatalog": "Imprime disponibilidad de intents por repositorio sin cadenas de comando sin procesar",
|
|
140
141
|
"workspace.help.action.verify": "Imprime planes de verificación de cambios por repositorio sin ejecutar comandos",
|
|
142
|
+
"workspace.help.option.projectsDir": "Selecciona el directorio hijo que se escaneará; predeterminado: projects",
|
|
141
143
|
"workspace.help.exit.ok": "Se inspeccionó el estado del workspace",
|
|
142
|
-
"workspace.error.missingAction": "Especifica una acción workspace: status, command-catalog o verify",
|
|
144
|
+
"workspace.error.missingAction": "Especifica una acción workspace: scan, status, command-catalog o verify",
|
|
143
145
|
"workspace.error.unknownAction": "Acción workspace desconocida: {action}",
|
|
144
146
|
"workspace.error.verifyRequiresChanged": "workspace verify requiere --changed",
|
|
145
147
|
"workspace.error.verifyRequiresPlanOnly": "workspace verify requiere --plan-only",
|
|
148
|
+
"workspace.scan.issue.noneDiscovered": "No se descubrieron repositorios git anidados bajo {projectsDir}.",
|
|
146
149
|
"context.help.summary": "Imprime el contexto de agente para la raíz mustflow actual.",
|
|
147
150
|
"context.help.option.json": "Imprime JSON de contexto legible por máquinas",
|
|
148
151
|
"context.help.option.cacheProfile": "Imprime un perfil de caché de prompt: stable, task, volatile o all",
|
|
@@ -680,6 +683,8 @@ Lee estos archivos antes de trabajar:
|
|
|
680
683
|
"init.error.unsupportedPreference": "Ajuste de preferencia de inicio no admitido: {key}",
|
|
681
684
|
"init.error.promptInputTooLarge": "La entrada estándar de init interactivo es demasiado grande; se esperaban como máximo {maxBytes} bytes.",
|
|
682
685
|
"init.error.promptInputTooManyResponses": "La entrada estándar de init interactivo tiene demasiadas respuestas; se esperaban como máximo {maxResponses} líneas.",
|
|
686
|
+
"init.error.workspaceRootDetected": "Este directorio parece un workspace de varios repositorios, no un solo repositorio: se encontraron {count} repositorios git bajo {projectsDir}.",
|
|
687
|
+
"init.error.workspaceRootGuidance": "Ejecuta mf workspace scan --json aquí, o ejecuta mf init dentro de un repositorio de destino.",
|
|
683
688
|
"init.prompt.locale": "¿Qué idioma deben usar los documentos mustflow?",
|
|
684
689
|
"init.prompt.profile": "¿Qué perfil de proyecto debe usar mustflow?",
|
|
685
690
|
"init.prompt.agentLang": "¿Qué idioma deben usar los agentes en los informes finales?",
|
package/dist/cli/i18n/fr.js
CHANGED
|
@@ -135,14 +135,17 @@ export const frMessages = {
|
|
|
135
135
|
"evidence.section.gaps": "Écarts",
|
|
136
136
|
"evidence.section.remainingRisks": "Risques restants",
|
|
137
137
|
"workspace.help.summary": "Inspecte les racines workspace configurées et l'état des contrats imbriqués sans accorder d'autorité de commande.",
|
|
138
|
+
"workspace.help.action.scan": "Scanne un répertoire projects pour trouver des dépôts imbriqués sans exiger de configuration workspace",
|
|
138
139
|
"workspace.help.action.status": "Affiche les dépôts imbriqués découverts et leur état de contrat mustflow local",
|
|
139
140
|
"workspace.help.action.commandCatalog": "Affiche la disponibilité des intents par dépôt sans chaînes de commande brutes",
|
|
140
141
|
"workspace.help.action.verify": "Affiche les plans de vérification des changements par dépôt sans exécuter de commandes",
|
|
142
|
+
"workspace.help.option.projectsDir": "Sélectionne le répertoire enfant à scanner ; par défaut : projects",
|
|
141
143
|
"workspace.help.exit.ok": "L'état du workspace a été inspecté",
|
|
142
|
-
"workspace.error.missingAction": "Indiquez une action workspace : status, command-catalog ou verify",
|
|
144
|
+
"workspace.error.missingAction": "Indiquez une action workspace : scan, status, command-catalog ou verify",
|
|
143
145
|
"workspace.error.unknownAction": "Action workspace inconnue : {action}",
|
|
144
146
|
"workspace.error.verifyRequiresChanged": "workspace verify nécessite --changed",
|
|
145
147
|
"workspace.error.verifyRequiresPlanOnly": "workspace verify nécessite --plan-only",
|
|
148
|
+
"workspace.scan.issue.noneDiscovered": "Aucun dépôt git imbriqué n'a été découvert sous {projectsDir}.",
|
|
146
149
|
"context.help.summary": "Imprime le contexte d'agent pour la racine mustflow actuelle.",
|
|
147
150
|
"context.help.option.json": "Imprime le JSON de contexte lisible par machine",
|
|
148
151
|
"context.help.option.cacheProfile": "Imprime un profil de cache de prompt : stable, task, volatile ou all",
|
|
@@ -680,6 +683,8 @@ Lisez ces fichiers avant de travailler :
|
|
|
680
683
|
"init.error.unsupportedPreference": "Paramètre de préférence d'initialisation non pris en charge : {key}",
|
|
681
684
|
"init.error.promptInputTooLarge": "L'entrée standard de l'init interactif est trop volumineuse ; {maxBytes} octets maximum sont attendus.",
|
|
682
685
|
"init.error.promptInputTooManyResponses": "L'entrée standard de l'init interactif contient trop de réponses ; {maxResponses} lignes maximum sont attendues.",
|
|
686
|
+
"init.error.workspaceRootDetected": "Ce répertoire ressemble à un workspace multi-dépôts, pas à un dépôt unique : {count} dépôts git ont été trouvés sous {projectsDir}.",
|
|
687
|
+
"init.error.workspaceRootGuidance": "Exécutez mf workspace scan --json ici, ou exécutez mf init dans un dépôt cible.",
|
|
683
688
|
"init.prompt.locale": "Quelle langue les documents mustflow doivent-ils utiliser ?",
|
|
684
689
|
"init.prompt.profile": "Quel profil de projet mustflow doit-il utiliser ?",
|
|
685
690
|
"init.prompt.agentLang": "Quelle langue les agents doivent-ils utiliser pour les rapports finaux ?",
|
package/dist/cli/i18n/hi.js
CHANGED
|
@@ -135,14 +135,17 @@ export const hiMessages = {
|
|
|
135
135
|
"evidence.section.gaps": "Gaps",
|
|
136
136
|
"evidence.section.remainingRisks": "Remaining risks",
|
|
137
137
|
"workspace.help.summary": "command authority दिए बिना configured workspace roots और nested repository contract readiness inspect करें.",
|
|
138
|
+
"workspace.help.action.scan": "workspace configuration के बिना projects directory में nested repositories scan करें",
|
|
138
139
|
"workspace.help.action.status": "discovered nested repositories और उनके local mustflow contract status प्रिंट करें",
|
|
139
140
|
"workspace.help.action.commandCatalog": "raw command strings के बिना per-repository command intent availability प्रिंट करें",
|
|
140
141
|
"workspace.help.action.verify": "commands चलाए बिना per-repository changed-file verification plans प्रिंट करें",
|
|
142
|
+
"workspace.help.option.projectsDir": "scan की जाने वाली child directory चुनें; default: projects",
|
|
141
143
|
"workspace.help.exit.ok": "Workspace status inspect हुआ",
|
|
142
|
-
"workspace.error.missingAction": "workspace action बताएँ: status, command-catalog या verify",
|
|
144
|
+
"workspace.error.missingAction": "workspace action बताएँ: scan, status, command-catalog या verify",
|
|
143
145
|
"workspace.error.unknownAction": "अज्ञात workspace action: {action}",
|
|
144
146
|
"workspace.error.verifyRequiresChanged": "workspace verify के लिए --changed चाहिए",
|
|
145
147
|
"workspace.error.verifyRequiresPlanOnly": "workspace verify के लिए --plan-only चाहिए",
|
|
148
|
+
"workspace.scan.issue.noneDiscovered": "{projectsDir} के नीचे कोई nested git repository नहीं मिला.",
|
|
146
149
|
"context.help.summary": "वर्तमान mustflow रूट के लिए एजेंट संदर्भ प्रिंट करें।",
|
|
147
150
|
"context.help.option.json": "मशीन-पठनीय संदर्भ JSON प्रिंट करें",
|
|
148
151
|
"context.help.option.cacheProfile": "prompt cache profile प्रिंट करें: stable, task, volatile, या all",
|
|
@@ -680,6 +683,8 @@ export const hiMessages = {
|
|
|
680
683
|
"init.error.unsupportedPreference": "असमर्थित init preference setting: {key}",
|
|
681
684
|
"init.error.promptInputTooLarge": "Interactive init stdin input बहुत बड़ा है; अधिकतम {maxBytes} bytes अपेक्षित हैं।",
|
|
682
685
|
"init.error.promptInputTooManyResponses": "Interactive init stdin input में बहुत अधिक responses हैं; अधिकतम {maxResponses} lines अपेक्षित हैं।",
|
|
686
|
+
"init.error.workspaceRootDetected": "यह directory single repository नहीं बल्कि multi-repository workspace जैसी दिखती है: {projectsDir} के नीचे {count} git repositories मिले.",
|
|
687
|
+
"init.error.workspaceRootGuidance": "यहाँ mf workspace scan --json चलाएँ, या target repository के अंदर mf init चलाएँ.",
|
|
683
688
|
"init.prompt.locale": "mustflow दस्तावेज़ कौन सी भाषा उपयोग करें?",
|
|
684
689
|
"init.prompt.profile": "mustflow कौन सा project profile उपयोग करे?",
|
|
685
690
|
"init.prompt.agentLang": "एजेंट final reports के लिए कौन सी भाषा उपयोग करें?",
|
package/dist/cli/i18n/ko.js
CHANGED
|
@@ -135,14 +135,17 @@ export const koMessages = {
|
|
|
135
135
|
"evidence.section.gaps": "구멍",
|
|
136
136
|
"evidence.section.remainingRisks": "남은 리스크",
|
|
137
137
|
"workspace.help.summary": "명령 권한을 부여하지 않고 설정된 workspace root와 nested repository 계약 준비 상태를 확인합니다.",
|
|
138
|
+
"workspace.help.action.scan": "workspace 설정 없이 projects 디렉터리의 nested repository를 스캔합니다",
|
|
138
139
|
"workspace.help.action.status": "발견된 nested repository와 각 로컬 mustflow 계약 상태를 출력합니다",
|
|
139
140
|
"workspace.help.action.commandCatalog": "raw command string 없이 repository별 command intent 사용 가능 상태를 출력합니다",
|
|
140
141
|
"workspace.help.action.verify": "명령을 실행하지 않고 repository별 changed-file verification plan을 출력합니다",
|
|
142
|
+
"workspace.help.option.projectsDir": "스캔할 하위 디렉터리를 지정합니다. 기본값: projects",
|
|
141
143
|
"workspace.help.exit.ok": "workspace 상태를 확인했습니다",
|
|
142
|
-
"workspace.error.missingAction": "workspace 작업을 지정하세요: status, command-catalog 또는 verify",
|
|
144
|
+
"workspace.error.missingAction": "workspace 작업을 지정하세요: scan, status, command-catalog 또는 verify",
|
|
143
145
|
"workspace.error.unknownAction": "알 수 없는 workspace 작업: {action}",
|
|
144
146
|
"workspace.error.verifyRequiresChanged": "workspace verify에는 --changed가 필요합니다",
|
|
145
147
|
"workspace.error.verifyRequiresPlanOnly": "workspace verify에는 --plan-only가 필요합니다",
|
|
148
|
+
"workspace.scan.issue.noneDiscovered": "{projectsDir} 아래에서 nested git repository를 찾지 못했습니다.",
|
|
146
149
|
"context.help.summary": "현재 mustflow 루트의 에이전트 작업 맥락을 출력합니다.",
|
|
147
150
|
"context.help.option.json": "맥락을 JSON 형식으로 출력합니다",
|
|
148
151
|
"context.help.option.cacheProfile": "프롬프트 캐시 프로필을 출력합니다: stable, task, volatile, all",
|
|
@@ -680,6 +683,8 @@ export const koMessages = {
|
|
|
680
683
|
"init.error.unsupportedPreference": "지원하지 않는 초기 설정 항목입니다: {key}",
|
|
681
684
|
"init.error.promptInputTooLarge": "대화형 init 표준입력이 너무 큽니다. 최대 {maxBytes}바이트까지만 허용됩니다.",
|
|
682
685
|
"init.error.promptInputTooManyResponses": "대화형 init 표준입력 응답이 너무 많습니다. 최대 {maxResponses}줄까지만 허용됩니다.",
|
|
686
|
+
"init.error.workspaceRootDetected": "이 디렉터리는 단일 저장소가 아니라 여러 저장소를 담은 workspace처럼 보입니다: {projectsDir} 아래에서 git repository {count}개를 찾았습니다.",
|
|
687
|
+
"init.error.workspaceRootGuidance": "여기서는 mf workspace scan --json을 실행하거나, 대상 저장소 안으로 이동해서 mf init을 실행하세요.",
|
|
683
688
|
"init.prompt.locale": "mustflow 문서는 어떤 언어로 설치할까요?",
|
|
684
689
|
"init.prompt.profile": "이 저장소에는 어떤 프로젝트 유형을 사용할까요?",
|
|
685
690
|
"init.prompt.agentLang": "에이전트 최종 응답은 어떤 언어로 받을까요?",
|
package/dist/cli/i18n/zh.js
CHANGED
|
@@ -135,14 +135,17 @@ export const zhMessages = {
|
|
|
135
135
|
"evidence.section.gaps": "缺口",
|
|
136
136
|
"evidence.section.remainingRisks": "剩余风险",
|
|
137
137
|
"workspace.help.summary": "检查已配置的 workspace 根目录和嵌套仓库合同状态,但不授予命令权限。",
|
|
138
|
+
"workspace.help.action.scan": "无需 workspace 配置即可扫描 projects 目录中的嵌套仓库",
|
|
138
139
|
"workspace.help.action.status": "输出发现的嵌套仓库及其本地 mustflow 合同状态",
|
|
139
140
|
"workspace.help.action.commandCatalog": "输出各仓库的命令 intent 可用性,不包含原始命令字符串",
|
|
140
141
|
"workspace.help.action.verify": "输出各仓库的变更文件验证计划,但不运行命令",
|
|
142
|
+
"workspace.help.option.projectsDir": "选择要扫描的子目录;默认值:projects",
|
|
141
143
|
"workspace.help.exit.ok": "已检查 workspace 状态",
|
|
142
|
-
"workspace.error.missingAction": "请指定 workspace 操作:status、command-catalog 或 verify",
|
|
144
|
+
"workspace.error.missingAction": "请指定 workspace 操作:scan、status、command-catalog 或 verify",
|
|
143
145
|
"workspace.error.unknownAction": "未知 workspace 操作:{action}",
|
|
144
146
|
"workspace.error.verifyRequiresChanged": "workspace verify 需要 --changed",
|
|
145
147
|
"workspace.error.verifyRequiresPlanOnly": "workspace verify 需要 --plan-only",
|
|
148
|
+
"workspace.scan.issue.noneDiscovered": "未在 {projectsDir} 下发现嵌套 git 仓库。",
|
|
146
149
|
"context.help.summary": "输出当前 mustflow 根目录的代理上下文。",
|
|
147
150
|
"context.help.option.json": "输出机器可读的上下文 JSON",
|
|
148
151
|
"context.help.option.cacheProfile": "输出提示缓存配置文件:stable、task、volatile 或 all",
|
|
@@ -680,6 +683,8 @@ export const zhMessages = {
|
|
|
680
683
|
"init.error.unsupportedPreference": "不支持的初始化偏好设置:{key}",
|
|
681
684
|
"init.error.promptInputTooLarge": "交互式 init 的标准输入过大;最多允许 {maxBytes} 字节。",
|
|
682
685
|
"init.error.promptInputTooManyResponses": "交互式 init 的标准输入响应过多;最多允许 {maxResponses} 行。",
|
|
686
|
+
"init.error.workspaceRootDetected": "此目录看起来是多仓库 workspace,而不是单个仓库:在 {projectsDir} 下发现了 {count} 个 git 仓库。",
|
|
687
|
+
"init.error.workspaceRootGuidance": "请在此处运行 mf workspace scan --json,或进入目标仓库后运行 mf init。",
|
|
683
688
|
"init.prompt.locale": "mustflow 文档应使用哪种语言?",
|
|
684
689
|
"init.prompt.profile": "mustflow 应使用哪个项目配置?",
|
|
685
690
|
"init.prompt.agentLang": "代理最终报告应使用哪种语言?",
|
package/dist/cli/index.js
CHANGED
|
@@ -40,6 +40,7 @@ function getTopLevelHelp(lang) {
|
|
|
40
40
|
'mf onboard commands --json',
|
|
41
41
|
'mf next --json',
|
|
42
42
|
'mf evidence --changed --json',
|
|
43
|
+
'mf workspace scan --json',
|
|
43
44
|
'mf workspace status --json',
|
|
44
45
|
'mf workspace verify --changed --plan-only --json',
|
|
45
46
|
'mf context --json',
|
|
@@ -99,6 +100,13 @@ function parseGlobalOptions(argv) {
|
|
|
99
100
|
}
|
|
100
101
|
return { lang, args: parsed.positionals };
|
|
101
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* mf:anchor cli.entrypoint.dispatch
|
|
105
|
+
* purpose: Resolve top-level CLI options and dispatch commands without bypassing per-command validation.
|
|
106
|
+
* search: CLI dispatch, global options, command registry, version alias, help
|
|
107
|
+
* invariant: Unknown commands and global option errors must stop before any command runner is loaded.
|
|
108
|
+
* risk: config
|
|
109
|
+
*/
|
|
102
110
|
export async function runCli(argv, reporter = consoleReporter) {
|
|
103
111
|
const parsed = parseGlobalOptions(argv);
|
|
104
112
|
const [command, ...args] = parsed.args;
|
|
@@ -598,6 +598,13 @@ function readTaskPromptCacheRepoMapReadPlan() {
|
|
|
598
598
|
},
|
|
599
599
|
};
|
|
600
600
|
}
|
|
601
|
+
/**
|
|
602
|
+
* mf:anchor cli.context.prompt-cache-task-layer
|
|
603
|
+
* purpose: Build the task-layer context plan that prefers selected routes, local-index anchors, and bounded repo-map spans.
|
|
604
|
+
* search: mf context, prompt cache, task context, route read plan, repo map, local index
|
|
605
|
+
* invariant: Task context may recommend what to read next but cannot replace AGENTS.md or command contract authority.
|
|
606
|
+
* risk: config, cache
|
|
607
|
+
*/
|
|
601
608
|
async function readTaskPromptCacheLayer(projectRoot, mustflow) {
|
|
602
609
|
const layer = readPromptCacheLayer(mustflow, 'task');
|
|
603
610
|
const localIndex = await readLocalIndexPromptContext(projectRoot);
|
package/dist/cli/lib/repo-map.js
CHANGED
|
@@ -232,6 +232,13 @@ function readMustflowConfig(projectRoot) {
|
|
|
232
232
|
return {};
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* mf:anchor cli.repo-map.config
|
|
237
|
+
* purpose: Resolve repository-map and workspace discovery settings from mustflow configuration.
|
|
238
|
+
* search: repo map config, priority paths, anchor files, workspace roots, include nested
|
|
239
|
+
* invariant: Map and workspace settings shape navigation only and do not create command authority.
|
|
240
|
+
* risk: config
|
|
241
|
+
*/
|
|
235
242
|
export function getRepoMapConfig(projectRoot) {
|
|
236
243
|
const parsed = readMustflowConfig(projectRoot);
|
|
237
244
|
const configuredPriorityPaths = [...getStringArray(parsed.read_order), ...getStringArray(parsed.optional_read_order)];
|
|
@@ -266,6 +273,13 @@ function classifyGitLsFilesFailure(result) {
|
|
|
266
273
|
}
|
|
267
274
|
return 'error';
|
|
268
275
|
}
|
|
276
|
+
/**
|
|
277
|
+
* mf:anchor cli.repo-map.git-file-discovery
|
|
278
|
+
* purpose: Read tracked files for repository-map fingerprints and anchor discovery with bounded git execution.
|
|
279
|
+
* search: git ls-files, repo map fingerprint, tracked files, timeout, max buffer
|
|
280
|
+
* invariant: Git discovery failures produce status metadata instead of falling back to unbounded filesystem scans.
|
|
281
|
+
* risk: config, state
|
|
282
|
+
*/
|
|
269
283
|
export function discoverGitFilesForRepoMap(projectRoot, options = {}) {
|
|
270
284
|
const spawnGit = options.spawnGit ?? spawnGitLsFiles;
|
|
271
285
|
const result = spawnGit('git', ['ls-files', '-z'], {
|
package/dist/cli/lib/run-plan.js
CHANGED
|
@@ -206,6 +206,13 @@ function createBlockedRunPlan(contract, intentName, intent, eligibility, reasonC
|
|
|
206
206
|
staleActiveLocks: [],
|
|
207
207
|
};
|
|
208
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* mf:anchor cli.run-plan.eligibility
|
|
211
|
+
* purpose: Convert a command intent contract into a runnable or blocked execution plan.
|
|
212
|
+
* search: run plan, command intent, agent_allowed, cwd safety, output limits, approval gate
|
|
213
|
+
* invariant: A runnable plan exists only after intent eligibility, approvals, cwd, timeout, and command source checks pass.
|
|
214
|
+
* risk: config, security, state
|
|
215
|
+
*/
|
|
209
216
|
export function createRunPlan(projectRoot, contract, intentName, options = {}) {
|
|
210
217
|
const rawIntent = contract.intents[intentName];
|
|
211
218
|
const eligibility = evaluateCommandIntentEligibility(intentName, rawIntent);
|