mustflow 1.30.0 → 2.11.0
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 +35 -11
- package/dist/cli/commands/classify.js +61 -6
- package/dist/cli/commands/contract-lint.js +13 -4
- package/dist/cli/commands/dashboard.js +6 -0
- package/dist/cli/commands/index.js +5 -0
- package/dist/cli/commands/run.js +224 -48
- package/dist/cli/commands/upgrade.js +65 -0
- package/dist/cli/commands/verify.js +550 -33
- package/dist/cli/i18n/en.js +73 -10
- package/dist/cli/i18n/es.js +73 -10
- package/dist/cli/i18n/fr.js +73 -10
- package/dist/cli/i18n/hi.js +73 -10
- package/dist/cli/i18n/ko.js +73 -10
- package/dist/cli/i18n/zh.js +73 -10
- package/dist/cli/index.js +27 -46
- package/dist/cli/lib/command-registry.js +5 -0
- package/dist/cli/lib/dashboard-export.js +62 -12
- package/dist/cli/lib/dashboard-html/client-script.js +1936 -0
- package/dist/cli/lib/dashboard-html/locale-bootstrap.js +8 -0
- package/dist/cli/lib/dashboard-html/styles.js +572 -0
- package/dist/cli/lib/dashboard-html/template.js +134 -0
- package/dist/cli/lib/dashboard-html/types.js +1 -0
- package/dist/cli/lib/dashboard-html.js +1 -1907
- package/dist/cli/lib/dashboard-locale.js +37 -0
- package/dist/cli/lib/local-index/constants.js +48 -0
- package/dist/cli/lib/local-index/index.js +2256 -0
- package/dist/cli/lib/local-index/sql.js +15 -0
- package/dist/cli/lib/local-index/types.js +1 -0
- package/dist/cli/lib/local-index.js +1 -1908
- package/dist/cli/lib/reporter.js +6 -0
- package/dist/cli/lib/run-plan.js +96 -4
- package/dist/cli/lib/templates.js +18 -1
- package/dist/cli/lib/validation/command-intents.js +11 -0
- package/dist/cli/lib/validation/constants.js +238 -0
- package/dist/cli/lib/validation/index.js +1384 -0
- package/dist/cli/lib/validation/primitives.js +198 -0
- package/dist/cli/lib/validation/test-selection.js +95 -0
- package/dist/cli/lib/validation/types.js +1 -0
- package/dist/cli/lib/validation.js +1 -1661
- package/dist/core/bounded-output.js +38 -0
- package/dist/core/change-classification.js +6 -2
- package/dist/core/change-verification.js +240 -6
- package/dist/core/check-issues.js +12 -0
- package/dist/core/command-contract-validation.js +20 -0
- package/dist/core/command-effects.js +13 -0
- package/dist/core/completion-verdict.js +209 -0
- package/dist/core/contract-lint.js +316 -7
- package/dist/core/dashboard-verification.js +8 -0
- package/dist/core/external-evidence.js +9 -0
- package/dist/core/public-json-contracts.js +28 -0
- package/dist/core/repeated-failure.js +17 -0
- package/dist/core/repro-evidence.js +53 -0
- package/dist/core/run-performance-history.js +307 -0
- package/dist/core/run-profile.js +87 -0
- package/dist/core/run-receipt.js +171 -4
- package/dist/core/run-write-drift.js +18 -2
- package/dist/core/scope-risk.js +64 -0
- package/dist/core/skill-route-alignment.js +110 -0
- package/dist/core/source-anchor-status.js +4 -1
- package/dist/core/test-selection.js +227 -0
- package/dist/core/validation-ratchet.js +52 -0
- package/dist/core/verification-decision-graph.js +67 -0
- package/dist/core/verification-evidence.js +249 -0
- package/dist/core/verification-scheduler.js +96 -2
- package/examples/README.md +12 -4
- package/package.json +1 -1
- package/schemas/README.md +18 -4
- package/schemas/change-verification-report.schema.json +169 -5
- package/schemas/commands.schema.json +51 -1
- package/schemas/contract-lint-report.schema.json +80 -0
- package/schemas/dashboard-export.schema.json +500 -0
- package/schemas/explain-report.schema.json +2 -0
- package/schemas/latest-run-pointer.schema.json +384 -0
- package/schemas/run-receipt.schema.json +113 -0
- package/schemas/test-selection.schema.json +81 -0
- package/schemas/verify-report.schema.json +361 -1
- package/schemas/verify-run-manifest.schema.json +410 -0
- package/templates/default/common/.mustflow/config/commands.toml +1 -1
- package/templates/default/i18n.toml +1 -1
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +124 -29
- package/templates/default/locales/en/.mustflow/skills/routes.toml +289 -0
- package/templates/default/manifest.toml +29 -2
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Languages: [English](README.md) · [한국어](docs/i18n/ko/README.md) · [中文](docs/i18n/zh/README.md) · [Español](docs/i18n/es/README.md) · [Français](docs/i18n/fr/README.md) · [हिन्दी](docs/i18n/hi/README.md)
|
|
4
4
|
|
|
5
|
-
mustflow is a
|
|
5
|
+
mustflow is a repository-local work contract and verification CLI for LLM coding agents. It keeps agents inside explicit read, command, and verification boundaries without replacing the host agent's sandbox, approval, checkpoint, model, or tool policies.
|
|
6
6
|
|
|
7
|
-
The core concept is straightforward: place `AGENTS.md` at the project root and keep detailed workflows under `.mustflow/`. Agents start from `AGENTS.md
|
|
7
|
+
The core concept is straightforward: place `AGENTS.md` at the project root and keep detailed workflows under `.mustflow/`. Agents start from `AGENTS.md`, then follow the repository command contract, skills, project context, and verification rules in sequence.
|
|
8
8
|
|
|
9
9
|
- Documentation site: <https://0disoft.github.io/mustflow/>
|
|
10
10
|
- Human-readable project examples: [`examples/`](examples/)
|
|
@@ -14,10 +14,24 @@ The core concept is straightforward: place `AGENTS.md` at the project root and k
|
|
|
14
14
|
- Security: [SECURITY.md](https://github.com/0disoft/mustflow/blob/main/SECURITY.md)
|
|
15
15
|
- Changelog: [CHANGELOG.md](https://github.com/0disoft/mustflow/blob/main/CHANGELOG.md)
|
|
16
16
|
|
|
17
|
+
## Choose your path
|
|
18
|
+
|
|
19
|
+
- Use mustflow in your repository: start with [Quick start](#quick-start), then review the [no-guessing workflow](#no-guessing-workflow) and [`examples/minimal-js/`](examples/minimal-js/).
|
|
20
|
+
- Contribute to mustflow: read [CONTRIBUTING.md](CONTRIBUTING.md), then run only configured command intents from [`.mustflow/config/commands.toml`](.mustflow/config/commands.toml).
|
|
21
|
+
- Build an AI coding tool or agent harness: use `AGENTS.md` and `mf context --json` for repository context, then consume JSON output and schemas from `mf classify`, `mf verify`, `mf run`, `mf dashboard`, and [`schemas/`](schemas/).
|
|
22
|
+
|
|
17
23
|
## No-guessing workflow
|
|
18
24
|
|
|
19
25
|
The initial mustflow path is deliberately narrow.
|
|
20
26
|
|
|
27
|
+
Authority stays narrow:
|
|
28
|
+
|
|
29
|
+
- Current user instructions define the task goal unless they are unsafe.
|
|
30
|
+
- Host safety, sandbox, and approval gates still apply.
|
|
31
|
+
- Repository work rules come from the nearest `AGENTS.md` and `.mustflow/config/*.toml`.
|
|
32
|
+
- Command execution authority comes only from `.mustflow/config/commands.toml`.
|
|
33
|
+
- Skills, context files, preferences, generated maps, search results, cache, and state files guide or explain work. They do not grant command permission.
|
|
34
|
+
|
|
21
35
|
```sh
|
|
22
36
|
npm install -D mustflow
|
|
23
37
|
npx mf init --yes
|
|
@@ -27,9 +41,9 @@ npx mf check --strict
|
|
|
27
41
|
After changes to code, templates, schemas, or documentation, classify the changed paths and review the verification plan before running any commands.
|
|
28
42
|
|
|
29
43
|
```sh
|
|
30
|
-
npx mf classify --changed --
|
|
31
|
-
npx mf verify --from-
|
|
32
|
-
npx mf verify --from-
|
|
44
|
+
npx mf classify --changed --write .mustflow/state/change-classification.json
|
|
45
|
+
npx mf verify --from-classification .mustflow/state/change-classification.json --plan-only --json
|
|
46
|
+
npx mf verify --from-classification .mustflow/state/change-classification.json --json
|
|
33
47
|
```
|
|
34
48
|
|
|
35
49
|
The plan is based on change classification and the `required_after` metadata in `.mustflow/config/commands.toml`. A command runs only if its declared intent is configured, one-shot, agent-allowed, closed-stdin, bounded by a timeout, and backed by an explicit command source.
|
|
@@ -239,9 +253,9 @@ If a project already has optional root Markdown files such as `README.md`, `PROJ
|
|
|
239
253
|
npx mf init --yes
|
|
240
254
|
npx mf doctor
|
|
241
255
|
npx mf check --strict
|
|
242
|
-
npx mf classify --changed --
|
|
243
|
-
npx mf verify --from-
|
|
244
|
-
npx mf verify --from-
|
|
256
|
+
npx mf classify --changed --write .mustflow/state/change-classification.json
|
|
257
|
+
npx mf verify --from-classification .mustflow/state/change-classification.json --plan-only --json
|
|
258
|
+
npx mf verify --from-classification .mustflow/state/change-classification.json --json
|
|
245
259
|
```
|
|
246
260
|
|
|
247
261
|
Create the optional local search index if search capabilities are needed. Run the normal command
|
|
@@ -268,6 +282,14 @@ npx mf update --dry-run
|
|
|
268
282
|
npx mf update --apply
|
|
269
283
|
```
|
|
270
284
|
|
|
285
|
+
After updating the mustflow package, `mf upgrade` combines the package freshness check with the safe project-file update step. It does not install packages by itself; update npm, pnpm, or Bun first.
|
|
286
|
+
|
|
287
|
+
```sh
|
|
288
|
+
bun update -g mustflow
|
|
289
|
+
mf upgrade --dry-run
|
|
290
|
+
mf upgrade
|
|
291
|
+
```
|
|
292
|
+
|
|
271
293
|
Agents should prefer the configured update intents so the repository receives a run receipt.
|
|
272
294
|
|
|
273
295
|
```sh
|
|
@@ -286,8 +308,8 @@ mf run mustflow_update_apply
|
|
|
286
308
|
| `mf check` | Validate mustflow files, TOML configuration, and skill document shape. |
|
|
287
309
|
| `mf check --strict` | Run additional safety checks for document identity, authority/lifecycle metadata, skill index/body alignment, skill metadata, command boundaries, version-source discovery, retention policy, output limits, raw logs, and secret-like context. |
|
|
288
310
|
| `mf adapters status` | Inspect existing host-specific instruction and adapter files without generating adapter files or granting command authority. |
|
|
289
|
-
| `mf classify --changed` | Classify changed paths, public surfaces, and validation reasons
|
|
290
|
-
| `mf contract-lint` | Inspect `.mustflow/config/commands.toml` for command-contract errors and warnings without running commands. |
|
|
311
|
+
| `mf classify --changed` | Classify changed paths, public surfaces, and validation reasons. Add `--write <path>` to save the classification report. |
|
|
312
|
+
| `mf contract-lint` | Inspect `.mustflow/config/commands.toml` for command-contract errors and warnings without running commands. Add `--suggest` to print non-runnable candidate snippets from existing command files. |
|
|
291
313
|
| `mf doctor` | Inspect the current mustflow root without writing files. |
|
|
292
314
|
| `mf docs review list` | Show documents still waiting for prose review after agent edits. |
|
|
293
315
|
| `mf docs review add <path>` | Add or refresh a document review queue entry. |
|
|
@@ -304,6 +326,8 @@ mf run mustflow_update_apply
|
|
|
304
326
|
| `mf status` | Inspect installed state and changed or missing files. |
|
|
305
327
|
| `mf update --dry-run` | Calculate a template update plan without writing files. |
|
|
306
328
|
| `mf update --apply` | Apply template updates when nothing is blocked. |
|
|
329
|
+
| `mf upgrade` | Check package freshness, then apply safe bundled template updates when the package is current. |
|
|
330
|
+
| `mf upgrade --dry-run` | Check package freshness and print the safe project update plan without writing files. |
|
|
307
331
|
| `mf help <topic>` | Show installed mustflow help. |
|
|
308
332
|
| `mf dashboard` | Start a local inspection dashboard for status, verification recommendations, release/version-source status, template update readiness, latest run receipt, skill routes, safe preferences, and documentation review. Use `--export-json <path>` or `--export <path>` for a bounded static report. It does not execute commands or apply fixes. |
|
|
309
333
|
| `mf version` | Print the installed mustflow package version. |
|
|
@@ -346,7 +370,7 @@ npx mf init --product-source-locale en --product-locale ko-KR
|
|
|
346
370
|
npx mf init --set git.auto_commit=true
|
|
347
371
|
```
|
|
348
372
|
|
|
349
|
-
- `--profile`: Project profile. The default is `minimal`. Profiles also select the installed skill surface: `minimal` installs core everyday coding skills,
|
|
373
|
+
- `--profile`: Project profile. The default is `minimal`. Profiles also select the installed skill surface: `minimal` installs core everyday coding skills, `patterns` adds architecture-pattern procedures, and `oss`, `team`, `product`, and `library` add opt-in skill groups without removing optional skill files from the package.
|
|
350
374
|
- `--locale`: Installed mustflow document language. The default template currently supports `en`, `ko`, `zh`, `es`, `fr`, and `hi`. The default template includes localized documents for all these locales.
|
|
351
375
|
- `--agent-lang`: Default language for final agent reports.
|
|
352
376
|
- `--interactive`: Choose init settings via prompts.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
1
3
|
import { createChangeClassificationReport, } from '../../core/change-classification.js';
|
|
2
4
|
import { printUsageError, renderHelp } from '../lib/cli-output.js';
|
|
3
5
|
import { readGitChangedFiles } from '../lib/git-changes.js';
|
|
@@ -10,10 +12,15 @@ export function getClassifyHelp(lang = 'en') {
|
|
|
10
12
|
summary: t(lang, 'classify.help.summary'),
|
|
11
13
|
options: [
|
|
12
14
|
{ label: '--changed', description: t(lang, 'classify.help.option.changed') },
|
|
15
|
+
{ label: '--write <path>', description: t(lang, 'classify.help.option.write') },
|
|
13
16
|
{ label: '--json', description: t(lang, 'cli.option.json') },
|
|
14
17
|
{ label: '-h, --help', description: t(lang, 'cli.option.help') },
|
|
15
18
|
],
|
|
16
|
-
examples: [
|
|
19
|
+
examples: [
|
|
20
|
+
'mf classify --changed',
|
|
21
|
+
'mf classify --changed --write .mustflow/state/change-classification.json',
|
|
22
|
+
'mf classify README.md schemas/verify-report.schema.json --json',
|
|
23
|
+
],
|
|
17
24
|
exitCodes: [
|
|
18
25
|
{ label: '0', description: t(lang, 'classify.help.exit.ok') },
|
|
19
26
|
{ label: '1', description: t(lang, 'cli.common.invalidInput') },
|
|
@@ -24,7 +31,9 @@ function parseClassifyArgs(args) {
|
|
|
24
31
|
const paths = [];
|
|
25
32
|
let json = false;
|
|
26
33
|
let changed = false;
|
|
27
|
-
|
|
34
|
+
let writePath;
|
|
35
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
36
|
+
const arg = args[index];
|
|
28
37
|
if (arg === '--json') {
|
|
29
38
|
json = true;
|
|
30
39
|
continue;
|
|
@@ -33,12 +42,29 @@ function parseClassifyArgs(args) {
|
|
|
33
42
|
changed = true;
|
|
34
43
|
continue;
|
|
35
44
|
}
|
|
45
|
+
if (arg === '--write') {
|
|
46
|
+
const value = args[index + 1];
|
|
47
|
+
if (!value || value.startsWith('-')) {
|
|
48
|
+
return { json, changed, writePath, paths, error: 'missing_write_value' };
|
|
49
|
+
}
|
|
50
|
+
writePath = value;
|
|
51
|
+
index += 1;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (arg.startsWith('--write=')) {
|
|
55
|
+
const value = arg.slice('--write='.length);
|
|
56
|
+
if (value.length === 0) {
|
|
57
|
+
return { json, changed, writePath, paths, error: 'missing_write_value' };
|
|
58
|
+
}
|
|
59
|
+
writePath = value;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
36
62
|
if (arg.startsWith('-')) {
|
|
37
|
-
return { json, changed, paths, error: arg };
|
|
63
|
+
return { json, changed, writePath, paths, error: arg };
|
|
38
64
|
}
|
|
39
65
|
paths.push(arg);
|
|
40
66
|
}
|
|
41
|
-
return { json, changed, paths };
|
|
67
|
+
return { json, changed, writePath, paths };
|
|
42
68
|
}
|
|
43
69
|
export function createClassifyOutput(projectRoot, source, paths) {
|
|
44
70
|
const files = source === 'changed' ? readGitChangedFiles(projectRoot) : paths;
|
|
@@ -75,6 +101,19 @@ function renderClassifyOutput(output, lang) {
|
|
|
75
101
|
}
|
|
76
102
|
return lines.join('\n');
|
|
77
103
|
}
|
|
104
|
+
function resolveWritePath(projectRoot, inputPath) {
|
|
105
|
+
const resolved = path.resolve(projectRoot, inputPath);
|
|
106
|
+
const relative = path.relative(projectRoot, resolved);
|
|
107
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
108
|
+
throw new Error('write_path_outside_root');
|
|
109
|
+
}
|
|
110
|
+
return resolved;
|
|
111
|
+
}
|
|
112
|
+
function writeClassifyOutput(projectRoot, inputPath, output) {
|
|
113
|
+
const outputPath = resolveWritePath(projectRoot, inputPath);
|
|
114
|
+
mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
115
|
+
writeFileSync(outputPath, `${JSON.stringify(output, null, 2)}\n`, 'utf8');
|
|
116
|
+
}
|
|
78
117
|
export function runClassify(args, reporter, lang = 'en') {
|
|
79
118
|
if (args.includes('--help') || args.includes('-h')) {
|
|
80
119
|
reporter.stdout(getClassifyHelp(lang));
|
|
@@ -82,7 +121,10 @@ export function runClassify(args, reporter, lang = 'en') {
|
|
|
82
121
|
}
|
|
83
122
|
const parsed = parseClassifyArgs(args);
|
|
84
123
|
if (parsed.error) {
|
|
85
|
-
|
|
124
|
+
const message = parsed.error === 'missing_write_value'
|
|
125
|
+
? t(lang, 'cli.error.missingValue', { option: '--write' })
|
|
126
|
+
: t(lang, 'cli.error.unknownOption', { option: parsed.error });
|
|
127
|
+
printUsageError(reporter, message, 'mf classify --help', getClassifyHelp(lang), lang);
|
|
86
128
|
return 1;
|
|
87
129
|
}
|
|
88
130
|
if (parsed.changed && parsed.paths.length > 0) {
|
|
@@ -93,7 +135,20 @@ export function runClassify(args, reporter, lang = 'en') {
|
|
|
93
135
|
printUsageError(reporter, t(lang, 'classify.error.missingInput'), 'mf classify --help', getClassifyHelp(lang), lang);
|
|
94
136
|
return 1;
|
|
95
137
|
}
|
|
96
|
-
const
|
|
138
|
+
const projectRoot = resolveMustflowRoot();
|
|
139
|
+
const output = createClassifyOutput(projectRoot, parsed.changed ? 'changed' : 'paths', parsed.paths);
|
|
140
|
+
if (parsed.writePath) {
|
|
141
|
+
try {
|
|
142
|
+
writeClassifyOutput(projectRoot, parsed.writePath, output);
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
const message = error instanceof Error && error.message === 'write_path_outside_root'
|
|
146
|
+
? t(lang, 'classify.error.write_path_outside_root')
|
|
147
|
+
: t(lang, 'cli.common.invalidInput');
|
|
148
|
+
printUsageError(reporter, message, 'mf classify --help', getClassifyHelp(lang), lang);
|
|
149
|
+
return 1;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
97
152
|
if (parsed.json) {
|
|
98
153
|
reporter.stdout(JSON.stringify(output, null, 2));
|
|
99
154
|
return 0;
|
|
@@ -14,10 +14,11 @@ export function getContractLintHelp(lang = 'en') {
|
|
|
14
14
|
summary: t(lang, 'contractLint.help.summary'),
|
|
15
15
|
options: [
|
|
16
16
|
{ label: '--coverage', description: t(lang, 'contractLint.help.option.coverage') },
|
|
17
|
+
{ label: '--suggest', description: t(lang, 'contractLint.help.option.suggest') },
|
|
17
18
|
{ label: '--json', description: t(lang, 'cli.option.json') },
|
|
18
19
|
{ label: '-h, --help', description: t(lang, 'cli.option.help') },
|
|
19
20
|
],
|
|
20
|
-
examples: ['mf contract-lint', 'mf contract-lint --coverage', 'mf contract-lint --coverage --json'],
|
|
21
|
+
examples: ['mf contract-lint', 'mf contract-lint --coverage', 'mf contract-lint --suggest', 'mf contract-lint --coverage --json'],
|
|
21
22
|
exitCodes: [
|
|
22
23
|
{ label: '0', description: t(lang, 'contractLint.help.exit.ok') },
|
|
23
24
|
{ label: '1', description: t(lang, 'contractLint.help.exit.fail') },
|
|
@@ -32,13 +33,14 @@ function readPreferences(projectRoot) {
|
|
|
32
33
|
const preferences = readTomlFile(preferencesPath);
|
|
33
34
|
return isRecord(preferences) ? preferences : undefined;
|
|
34
35
|
}
|
|
35
|
-
function createContractLintOutput(projectRoot, coverage) {
|
|
36
|
+
function createContractLintOutput(projectRoot, coverage, suggest) {
|
|
36
37
|
return {
|
|
37
38
|
schema_version: CONTRACT_LINT_SCHEMA_VERSION,
|
|
38
39
|
command: 'contract-lint',
|
|
39
40
|
mustflow_root: projectRoot,
|
|
40
41
|
report: lintCommandContract(readCommandContract(projectRoot), {
|
|
41
42
|
coverage,
|
|
43
|
+
suggest,
|
|
42
44
|
projectRoot,
|
|
43
45
|
releaseVersioningEnabled: releaseVersioningIsEnabled(readPreferences(projectRoot)),
|
|
44
46
|
}),
|
|
@@ -63,6 +65,13 @@ function renderContractLintOutput(output, lang) {
|
|
|
63
65
|
if (output.report.coverage) {
|
|
64
66
|
lines.push('', t(lang, 'contractLint.label.coverage'), `${t(lang, 'contractLint.label.classificationReasons')}: ${output.report.coverage.knownClassificationReasons.length}`, `${t(lang, 'contractLint.label.requiredAfterReasons')}: ${output.report.coverage.requiredAfterReasons.length}`, `${t(lang, 'contractLint.label.runnableReasons')}: ${output.report.coverage.runnableReasons.length}`, `${t(lang, 'contractLint.label.coverageFindings')}: ${output.report.coverage.findings.length}`);
|
|
65
67
|
}
|
|
68
|
+
if (output.report.suggestions) {
|
|
69
|
+
lines.push('', t(lang, 'contractLint.label.suggestions'));
|
|
70
|
+
for (const suggestion of output.report.suggestions) {
|
|
71
|
+
lines.push(`- ${suggestion.sourceFile}:${suggestion.sourceName} -> ${suggestion.suggestedIntent}`);
|
|
72
|
+
lines.push(...suggestion.snippet.split('\n').map((line) => ` ${line}`));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
66
75
|
if (output.report.issues.length > 0) {
|
|
67
76
|
lines.push('', t(lang, 'contractLint.label.issues'));
|
|
68
77
|
for (const issue of output.report.issues) {
|
|
@@ -77,13 +86,13 @@ export function runContractLint(args, reporter, lang = 'en') {
|
|
|
77
86
|
reporter.stdout(getContractLintHelp(lang));
|
|
78
87
|
return 0;
|
|
79
88
|
}
|
|
80
|
-
const supported = new Set(['--coverage', '--json']);
|
|
89
|
+
const supported = new Set(['--coverage', '--suggest', '--json']);
|
|
81
90
|
const unsupported = args.filter((arg) => !supported.has(arg));
|
|
82
91
|
if (unsupported.length > 0) {
|
|
83
92
|
printUsageError(reporter, t(lang, 'cli.error.unknownOption', { option: unsupported[0] }), 'mf contract-lint --help', getContractLintHelp(lang), lang);
|
|
84
93
|
return 1;
|
|
85
94
|
}
|
|
86
|
-
const output = createContractLintOutput(resolveMustflowRoot(), args.includes('--coverage'));
|
|
95
|
+
const output = createContractLintOutput(resolveMustflowRoot(), args.includes('--coverage'), args.includes('--suggest'));
|
|
87
96
|
if (args.includes('--json')) {
|
|
88
97
|
reporter.stdout(JSON.stringify(output, null, 2));
|
|
89
98
|
}
|
|
@@ -25,6 +25,7 @@ const DEFAULT_DASHBOARD_HOST = '127.0.0.1';
|
|
|
25
25
|
const DEFAULT_DASHBOARD_PORT = 0;
|
|
26
26
|
const MAX_REQUEST_BYTES = 64 * 1024;
|
|
27
27
|
const LOCAL_DASHBOARD_HOSTS = new Set(['127.0.0.1', 'localhost', '::1']);
|
|
28
|
+
const DOC_REVIEW_BULK_PAYLOAD_FIELDS = ['paths', 'documents', 'entries'];
|
|
28
29
|
const RELEASE_FILE_PATTERNS = [
|
|
29
30
|
/^package\.json$/u,
|
|
30
31
|
/^bun\.lockb?$/u,
|
|
@@ -296,6 +297,11 @@ function readDocReviewPayload(value) {
|
|
|
296
297
|
throw new Error('Request body must be a JSON object.');
|
|
297
298
|
}
|
|
298
299
|
const payload = value;
|
|
300
|
+
for (const field of DOC_REVIEW_BULK_PAYLOAD_FIELDS) {
|
|
301
|
+
if (field in payload) {
|
|
302
|
+
throw new Error('Bulk documentation review updates require a separate confirmed flow.');
|
|
303
|
+
}
|
|
304
|
+
}
|
|
299
305
|
const status = readRequiredStringField(payload, 'status');
|
|
300
306
|
if (status !== 'approved' && status !== 'needs_human' && status !== 'ignored') {
|
|
301
307
|
throw new Error('status must be approved, needs_human, or ignored.');
|
|
@@ -42,6 +42,11 @@ function renderIndexSummary(result, lang) {
|
|
|
42
42
|
`skill_routes: ${result.skill_route_count}`,
|
|
43
43
|
`${t(lang, 'label.commandIntents')}: ${result.command_intent_count}`,
|
|
44
44
|
`command_effects: ${result.command_effect_count}`,
|
|
45
|
+
`verification_evidence_summaries: ${result.verification_evidence_summary_count}`,
|
|
46
|
+
`verification_receipt_summaries: ${result.verification_receipt_summary_count}`,
|
|
47
|
+
`verification_coverage_states: ${result.verification_coverage_state_count}`,
|
|
48
|
+
`verification_risk_signals: ${result.verification_risk_signal_count}`,
|
|
49
|
+
`failure_fingerprints: ${result.failure_fingerprint_count}`,
|
|
45
50
|
`source_anchors: ${result.source_anchor_count}`,
|
|
46
51
|
`index_mode: ${result.index_mode}`,
|
|
47
52
|
`reused_existing: ${result.reused_existing ? 'yes' : 'no'}`,
|