mustflow 2.22.17 → 2.22.47
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 +6 -0
- package/dist/cli/commands/api.js +874 -0
- package/dist/cli/commands/dashboard.js +51 -4
- package/dist/cli/commands/explain.js +3 -2
- package/dist/cli/commands/help.js +0 -1
- package/dist/cli/commands/run.js +41 -4
- package/dist/cli/commands/verify.js +4 -43
- package/dist/cli/i18n/en.js +15 -0
- package/dist/cli/i18n/es.js +15 -0
- package/dist/cli/i18n/fr.js +15 -0
- package/dist/cli/i18n/hi.js +15 -0
- package/dist/cli/i18n/ko.js +15 -0
- package/dist/cli/i18n/zh.js +15 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/lib/cli-output.js +1 -1
- package/dist/cli/lib/command-registry.js +6 -0
- package/dist/cli/lib/dashboard-html/client-script.js +9 -0
- package/dist/cli/lib/dashboard-html/styles.js +48 -1
- package/dist/cli/lib/doc-review-ledger.js +1 -1
- package/dist/cli/lib/local-index/index.js +324 -298
- package/dist/cli/lib/repo-map.js +19 -5
- package/dist/cli/lib/validation/index.js +6 -2
- package/dist/core/active-run-locks.js +36 -8
- package/dist/core/atomic-state-write.js +5 -20
- package/dist/core/change-verification.js +18 -2
- package/dist/core/contract-lint.js +3 -3
- package/dist/core/public-json-contracts.js +48 -0
- package/dist/core/repeated-failure.js +1 -1
- package/dist/core/run-write-drift.js +30 -17
- package/dist/core/safe-filesystem.js +54 -5
- package/dist/core/skill-route-explanation.js +2 -1
- package/dist/core/source-anchors.js +7 -3
- package/dist/core/validation-ratchet.js +61 -18
- package/dist/core/verification-decision-graph.js +8 -1
- package/dist/core/verification-plan-id.js +44 -0
- package/package.json +1 -1
- package/schemas/README.md +6 -0
- package/schemas/command-catalog.schema.json +158 -0
- package/schemas/diff-risk.schema.json +74 -0
- package/schemas/health.schema.json +45 -0
- package/schemas/latest-evidence.schema.json +95 -0
- package/schemas/verification-plan.schema.json +245 -0
- package/schemas/workspace-summary.schema.json +282 -0
- package/templates/default/i18n.toml +139 -1
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +24 -1
- package/templates/default/locales/en/.mustflow/skills/api-contract-change/SKILL.md +212 -0
- package/templates/default/locales/en/.mustflow/skills/astro-code-change/SKILL.md +184 -0
- package/templates/default/locales/en/.mustflow/skills/auth-permission-change/SKILL.md +194 -0
- package/templates/default/locales/en/.mustflow/skills/config-env-change/SKILL.md +189 -0
- package/templates/default/locales/en/.mustflow/skills/css-code-change/SKILL.md +199 -0
- package/templates/default/locales/en/.mustflow/skills/dart-code-change/SKILL.md +179 -0
- package/templates/default/locales/en/.mustflow/skills/database-migration-change/SKILL.md +178 -0
- package/templates/default/locales/en/.mustflow/skills/dependency-upgrade-review/SKILL.md +151 -0
- package/templates/default/locales/en/.mustflow/skills/elysia-code-change/SKILL.md +115 -0
- package/templates/default/locales/en/.mustflow/skills/file-path-cross-platform-change/SKILL.md +147 -0
- package/templates/default/locales/en/.mustflow/skills/flutter-code-change/SKILL.md +116 -0
- package/templates/default/locales/en/.mustflow/skills/go-code-change/SKILL.md +156 -0
- package/templates/default/locales/en/.mustflow/skills/hono-code-change/SKILL.md +117 -0
- package/templates/default/locales/en/.mustflow/skills/html-code-change/SKILL.md +173 -0
- package/templates/default/locales/en/.mustflow/skills/javascript-code-change/SKILL.md +149 -0
- package/templates/default/locales/en/.mustflow/skills/python-code-change/SKILL.md +154 -0
- package/templates/default/locales/en/.mustflow/skills/release-publish-change/SKILL.md +172 -0
- package/templates/default/locales/en/.mustflow/skills/routes.toml +138 -0
- package/templates/default/locales/en/.mustflow/skills/rust-code-change/SKILL.md +154 -0
- package/templates/default/locales/en/.mustflow/skills/svelte-code-change/SKILL.md +186 -0
- package/templates/default/locales/en/.mustflow/skills/tailwind-code-change/SKILL.md +164 -0
- package/templates/default/locales/en/.mustflow/skills/tauri-code-change/SKILL.md +185 -0
- package/templates/default/locales/en/.mustflow/skills/typescript-code-change/SKILL.md +184 -0
- package/templates/default/locales/en/.mustflow/skills/unocss-code-change/SKILL.md +186 -0
- package/templates/default/manifest.toml +158 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHash, randomBytes } from 'node:crypto';
|
|
1
|
+
import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
2
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
3
3
|
import http from 'node:http';
|
|
4
4
|
import path from 'node:path';
|
|
@@ -306,8 +306,36 @@ function sendText(response, statusCode, value) {
|
|
|
306
306
|
function sendBadRequest(response) {
|
|
307
307
|
sendText(response, 400, 'Bad request');
|
|
308
308
|
}
|
|
309
|
+
function isDashboardBadRequestError(error, message) {
|
|
310
|
+
return (error instanceof SyntaxError ||
|
|
311
|
+
message === 'Request body is too large.' ||
|
|
312
|
+
message === 'Invalid review status.' ||
|
|
313
|
+
message === 'Request body must be a JSON object.' ||
|
|
314
|
+
message === 'Request body must include an updates array.' ||
|
|
315
|
+
message === 'Each update must be a JSON object.' ||
|
|
316
|
+
message === 'Each update must include an id.' ||
|
|
317
|
+
message === 'Bulk documentation review updates require a separate confirmed flow.' ||
|
|
318
|
+
message.startsWith('Unknown dashboard preference: ') ||
|
|
319
|
+
message.endsWith(' is locked in the dashboard.') ||
|
|
320
|
+
message.endsWith(' is required.') ||
|
|
321
|
+
message.endsWith(' must be a boolean.') ||
|
|
322
|
+
message.endsWith(' must be an integer.') ||
|
|
323
|
+
message.endsWith(' must be a string.') ||
|
|
324
|
+
message.endsWith(' must not be empty.') ||
|
|
325
|
+
/^.+ must be at (?:least|most) \d+\.$/u.test(message) ||
|
|
326
|
+
/^.+ must be one of: .+\.$/u.test(message) ||
|
|
327
|
+
message.startsWith('status must be ') ||
|
|
328
|
+
message.startsWith('reviewerKind must be '));
|
|
329
|
+
}
|
|
309
330
|
function isAuthorized(request, token) {
|
|
310
|
-
|
|
331
|
+
const rawToken = request.headers['x-mustflow-dashboard-token'];
|
|
332
|
+
const candidate = Array.isArray(rawToken) ? rawToken[0] : rawToken;
|
|
333
|
+
if (typeof candidate !== 'string') {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
const expected = Buffer.from(token);
|
|
337
|
+
const actual = Buffer.from(candidate);
|
|
338
|
+
return expected.byteLength === actual.byteLength && timingSafeEqual(actual, expected);
|
|
311
339
|
}
|
|
312
340
|
async function readRequestJson(request) {
|
|
313
341
|
const chunks = [];
|
|
@@ -841,19 +869,38 @@ export async function runDashboard(args, reporter, lang = 'en') {
|
|
|
841
869
|
}
|
|
842
870
|
sendText(response, 404, 'Not found');
|
|
843
871
|
}
|
|
844
|
-
catch {
|
|
845
|
-
|
|
872
|
+
catch (error) {
|
|
873
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
874
|
+
if (isDashboardBadRequestError(error, message)) {
|
|
875
|
+
sendBadRequest(response);
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
reporter.stderr(message);
|
|
879
|
+
sendText(response, 500, 'Internal server error');
|
|
846
880
|
}
|
|
847
881
|
});
|
|
882
|
+
server.headersTimeout = 10_000;
|
|
883
|
+
server.requestTimeout = 30_000;
|
|
884
|
+
server.keepAliveTimeout = 1_000;
|
|
848
885
|
return new Promise((resolve) => {
|
|
849
886
|
let resolved = false;
|
|
887
|
+
const sockets = new Set();
|
|
850
888
|
const close = () => {
|
|
851
889
|
if (resolved) {
|
|
852
890
|
return;
|
|
853
891
|
}
|
|
854
892
|
resolved = true;
|
|
855
893
|
server.close(() => resolve(0));
|
|
894
|
+
for (const socket of sockets) {
|
|
895
|
+
socket.destroy();
|
|
896
|
+
}
|
|
856
897
|
};
|
|
898
|
+
server.on('connection', (socket) => {
|
|
899
|
+
sockets.add(socket);
|
|
900
|
+
socket.on('close', () => {
|
|
901
|
+
sockets.delete(socket);
|
|
902
|
+
});
|
|
903
|
+
});
|
|
857
904
|
server.on('error', (error) => {
|
|
858
905
|
if (!resolved) {
|
|
859
906
|
resolved = true;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { existsSync
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { printUsageError, renderHelp } from '../lib/cli-output.js';
|
|
4
4
|
import { t } from '../lib/i18n.js';
|
|
5
|
+
import { MUSTFLOW_JSON_MAX_BYTES, readMustflowTextFile } from '../lib/mustflow-read.js';
|
|
5
6
|
import { resolveMustflowRoot } from '../lib/project-root.js';
|
|
6
7
|
import { explainAssetOptimization, explainCommandIntent, } from '../../core/command-explanation.js';
|
|
7
8
|
import { readCommandContract, readMustflowConfigIfExists } from '../../core/config-loading.js';
|
|
@@ -225,7 +226,7 @@ function getLatestFailureExplainOutput(projectRoot) {
|
|
|
225
226
|
}
|
|
226
227
|
let parsed;
|
|
227
228
|
try {
|
|
228
|
-
parsed = JSON.parse(
|
|
229
|
+
parsed = JSON.parse(readMustflowTextFile(projectRoot, LATEST_RUN_RECEIPT_RELATIVE_PATH, { maxBytes: MUSTFLOW_JSON_MAX_BYTES }));
|
|
229
230
|
}
|
|
230
231
|
catch {
|
|
231
232
|
return {
|
package/dist/cli/commands/run.js
CHANGED
|
@@ -117,6 +117,31 @@ function renderActiveLockConflictMessage(intentName, conflicts, lang) {
|
|
|
117
117
|
: t(lang, 'run.error.activeLockConflictUnknown');
|
|
118
118
|
return t(lang, 'run.error.activeLockConflict', { intent: intentName, detail });
|
|
119
119
|
}
|
|
120
|
+
function createRunProgressReporter(input) {
|
|
121
|
+
if (!input.enabled) {
|
|
122
|
+
return () => undefined;
|
|
123
|
+
}
|
|
124
|
+
input.reporter.stderr(t(input.lang, 'run.progress.started', { intent: input.intentName, seconds: input.timeoutSeconds }));
|
|
125
|
+
const timers = [];
|
|
126
|
+
for (const ratio of [0.5, 0.8]) {
|
|
127
|
+
const delayMs = Math.max(1, Math.floor(input.timeoutSeconds * 1000 * ratio));
|
|
128
|
+
const elapsedSeconds = Math.max(1, Math.round(input.timeoutSeconds * ratio));
|
|
129
|
+
const timer = setTimeout(() => {
|
|
130
|
+
input.reporter.stderr(t(input.lang, 'run.progress.timeoutWarning', {
|
|
131
|
+
intent: input.intentName,
|
|
132
|
+
seconds: elapsedSeconds,
|
|
133
|
+
percent: Math.round(ratio * 100),
|
|
134
|
+
}));
|
|
135
|
+
}, delayMs);
|
|
136
|
+
timer.unref?.();
|
|
137
|
+
timers.push(timer);
|
|
138
|
+
}
|
|
139
|
+
return () => {
|
|
140
|
+
for (const timer of timers) {
|
|
141
|
+
clearTimeout(timer);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
120
145
|
export function getRunHelp(lang = 'en') {
|
|
121
146
|
return renderHelp({
|
|
122
147
|
usage: 'mf run <intent> [options]',
|
|
@@ -241,13 +266,25 @@ export async function runRun(args, reporter, lang = 'en', options = {}) {
|
|
|
241
266
|
let streamedOutput = false;
|
|
242
267
|
const childStartedAtMs = performance.now();
|
|
243
268
|
const startedAt = new Date();
|
|
269
|
+
const stopRunProgress = createRunProgressReporter({
|
|
270
|
+
enabled: !json && Boolean(reporter.writeStderr),
|
|
271
|
+
intentName,
|
|
272
|
+
timeoutSeconds: plan.timeoutSeconds,
|
|
273
|
+
reporter,
|
|
274
|
+
lang,
|
|
275
|
+
});
|
|
244
276
|
const result = await profiler.measureAsync('child_command', async () => {
|
|
245
|
-
|
|
277
|
+
try {
|
|
278
|
+
if (plan.commandArgv) {
|
|
279
|
+
streamedOutput = !json;
|
|
280
|
+
return runArgvCommandStreaming(plan.argvCommand, plan.cwd, env, plan.timeoutSeconds, plan.killAfterSeconds, plan.maxOutputBytes, stdoutTailBytes, stderrTailBytes, reporter, !json, true);
|
|
281
|
+
}
|
|
246
282
|
streamedOutput = !json;
|
|
247
|
-
return
|
|
283
|
+
return runShellCommandStreaming(plan.shellCommand, plan.cwd, env, plan.timeoutSeconds, plan.killAfterSeconds, plan.maxOutputBytes, stdoutTailBytes, stderrTailBytes, reporter, !json, true);
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
stopRunProgress();
|
|
248
287
|
}
|
|
249
|
-
streamedOutput = !json;
|
|
250
|
-
return runShellCommandStreaming(plan.shellCommand, plan.cwd, env, plan.timeoutSeconds, plan.killAfterSeconds, plan.maxOutputBytes, stdoutTailBytes, stderrTailBytes, reporter, !json, true);
|
|
251
288
|
});
|
|
252
289
|
const childDurationMs = performance.now() - childStartedAtMs;
|
|
253
290
|
const finishedAt = new Date();
|
|
@@ -6,6 +6,7 @@ import { readUtf8FileInsideWithoutSymlinks, writeJsonFileInsideWithoutSymlinks }
|
|
|
6
6
|
import { createVerifyCompletionVerdict, } from '../../core/completion-verdict.js';
|
|
7
7
|
import { createExternalEvidenceRisks, } from '../../core/external-evidence.js';
|
|
8
8
|
import { createRepeatedFailureRisks, createVerificationFailureFingerprint, updateRepeatedFailureState, } from '../../core/repeated-failure.js';
|
|
9
|
+
import { createVerificationPlanId } from '../../core/verification-plan-id.js';
|
|
9
10
|
import { countReproEvidenceVerdictEffects, createReproEvidenceRisks, } from '../../core/repro-evidence.js';
|
|
10
11
|
import { createVerifyEvidenceModel } from '../../core/verification-evidence.js';
|
|
11
12
|
import { createScopeDiffRisks } from '../../core/scope-risk.js';
|
|
@@ -24,6 +25,9 @@ import { readLocalCommandEffectGraphs, readLocalPathSurfaces, readLocalSourceAnc
|
|
|
24
25
|
import { resolveMustflowRoot } from '../lib/project-root.js';
|
|
25
26
|
export { planErrorMessageKey, readInputFromClassificationReport } from './verify/input.js';
|
|
26
27
|
const VERIFY_SCHEMA_VERSION = '1';
|
|
28
|
+
function hashTextSha256(content) {
|
|
29
|
+
return `sha256:${createHash('sha256').update(content).digest('hex')}`;
|
|
30
|
+
}
|
|
27
31
|
function createBufferedOutput() {
|
|
28
32
|
const stdout = [];
|
|
29
33
|
const stderr = [];
|
|
@@ -569,49 +573,6 @@ function readPreviousVerifyLatestSummary(projectRoot) {
|
|
|
569
573
|
return null;
|
|
570
574
|
}
|
|
571
575
|
}
|
|
572
|
-
function hashTextSha256(content) {
|
|
573
|
-
return `sha256:${createHash('sha256').update(content).digest('hex')}`;
|
|
574
|
-
}
|
|
575
|
-
function stableJson(value) {
|
|
576
|
-
if (Array.isArray(value)) {
|
|
577
|
-
return `[${value.map((entry) => stableJson(entry)).join(',')}]`;
|
|
578
|
-
}
|
|
579
|
-
if (value && typeof value === 'object') {
|
|
580
|
-
const record = value;
|
|
581
|
-
return `{${Object.keys(record)
|
|
582
|
-
.sort((left, right) => left.localeCompare(right))
|
|
583
|
-
.map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`)
|
|
584
|
-
.join(',')}}`;
|
|
585
|
-
}
|
|
586
|
-
return JSON.stringify(value) ?? 'null';
|
|
587
|
-
}
|
|
588
|
-
function getCandidateIntentNames(report) {
|
|
589
|
-
return [...new Set(report.candidates.map((candidate) => candidate.intent).filter((intent) => Boolean(intent)))]
|
|
590
|
-
.sort((left, right) => left.localeCompare(right));
|
|
591
|
-
}
|
|
592
|
-
function createVerificationPlanId(report, contract) {
|
|
593
|
-
const relatedIntents = Object.fromEntries(getCandidateIntentNames(report).map((intent) => [intent, contract.intents[intent] ?? null]));
|
|
594
|
-
const fingerprintSource = {
|
|
595
|
-
schema_version: '1',
|
|
596
|
-
algorithm: 'mustflow.verify_plan_id.v1',
|
|
597
|
-
report: {
|
|
598
|
-
source: report.source,
|
|
599
|
-
files: report.files,
|
|
600
|
-
classification_summary: report.classification_summary,
|
|
601
|
-
requirements: report.requirements,
|
|
602
|
-
candidates: report.candidates,
|
|
603
|
-
gaps: report.gaps,
|
|
604
|
-
schedule: report.schedule,
|
|
605
|
-
test_selection: report.test_selection,
|
|
606
|
-
},
|
|
607
|
-
command_contract: {
|
|
608
|
-
defaults: contract.defaults,
|
|
609
|
-
resources: contract.resources,
|
|
610
|
-
intents: relatedIntents,
|
|
611
|
-
},
|
|
612
|
-
};
|
|
613
|
-
return hashTextSha256(stableJson(fingerprintSource));
|
|
614
|
-
}
|
|
615
576
|
function toParallelismReport(settings) {
|
|
616
577
|
return {
|
|
617
578
|
requested: settings.requested,
|
package/dist/cli/i18n/en.js
CHANGED
|
@@ -24,6 +24,7 @@ export const enMessages = {
|
|
|
24
24
|
"value.missing": "missing",
|
|
25
25
|
"value.passed": "passed",
|
|
26
26
|
"value.failed": "failed",
|
|
27
|
+
"command.api.summary": "Print stable machine-readable API reports for agents",
|
|
27
28
|
"command.adapters.summary": "Inspect host adapter compatibility without generating adapter files",
|
|
28
29
|
"command.init.summary": "Copy the default mustflow agent workflow",
|
|
29
30
|
"command.check.summary": "Validate mustflow files",
|
|
@@ -86,6 +87,18 @@ export const enMessages = {
|
|
|
86
87
|
"context.help.option.cacheProfile": "Print a prompt-cache profile: stable, task, volatile, or all",
|
|
87
88
|
"context.help.exit.ok": "Context was inspected and printed",
|
|
88
89
|
"context.title": "mustflow context",
|
|
90
|
+
"api.help.summary": "Print stable machine-readable API reports for the current mustflow root.",
|
|
91
|
+
"api.help.action.workspaceSummary": "Print a read-only workspace briefing for coding agents",
|
|
92
|
+
"api.help.action.commandCatalog": "Print command intent availability without exposing raw command execution strings",
|
|
93
|
+
"api.help.action.verificationPlan": "Print a read-only verification plan for changed files",
|
|
94
|
+
"api.help.action.latestEvidence": "Print bounded latest run or verify evidence for agents",
|
|
95
|
+
"api.help.action.diffRisk": "Print a compact changed-file risk and verification summary",
|
|
96
|
+
"api.help.action.health": "Print a compact workspace health summary",
|
|
97
|
+
"api.help.exit.ok": "The API report was inspected and printed",
|
|
98
|
+
"api.error.missingAction": "Specify an api action: workspace-summary, command-catalog, verification-plan, latest-evidence, diff-risk, or health",
|
|
99
|
+
"api.error.unknownAction": "Unknown api action: {action}",
|
|
100
|
+
"api.error.actionRequiresJson": "{action} requires --json",
|
|
101
|
+
"api.error.actionRequiresChanged": "{action} currently requires --changed",
|
|
89
102
|
"label.installed": "Installed",
|
|
90
103
|
"label.mustflowRoot": "mustflow root",
|
|
91
104
|
"label.commandContract": "Command specification",
|
|
@@ -665,6 +678,8 @@ Read these files before working:
|
|
|
665
678
|
"run.help.exit.ok": "The command completed with an allowed exit code",
|
|
666
679
|
"run.help.exit.fail": "The command was invalid, refused, timed out, or failed",
|
|
667
680
|
"run.label.suggestedIntentSnippet": "Suggested command contract snippet",
|
|
681
|
+
"run.progress.started": "Running {intent} (timeout: {seconds}s)...",
|
|
682
|
+
"run.progress.timeoutWarning": "Still running {intent}... ({seconds}s elapsed, {percent}% of timeout)",
|
|
668
683
|
"run.error.missingIntent": "Missing command name",
|
|
669
684
|
"run.error.unknownIntent": "Unknown command: {intent}",
|
|
670
685
|
"run.error.statusNotConfigured": 'Command "{intent}" is {status}; only configured commands can be run',
|
package/dist/cli/i18n/es.js
CHANGED
|
@@ -24,6 +24,7 @@ export const esMessages = {
|
|
|
24
24
|
"value.missing": "faltante",
|
|
25
25
|
"value.passed": "superado",
|
|
26
26
|
"value.failed": "fallido",
|
|
27
|
+
"command.api.summary": "Imprime informes API estables legibles por máquinas para agentes",
|
|
27
28
|
"command.adapters.summary": "Inspecciona compatibilidad de adaptadores sin generar archivos",
|
|
28
29
|
"command.init.summary": "Copia el flujo de trabajo de agente mustflow predeterminado",
|
|
29
30
|
"command.check.summary": "Valida los archivos mustflow",
|
|
@@ -86,6 +87,18 @@ export const esMessages = {
|
|
|
86
87
|
"context.help.option.cacheProfile": "Imprime un perfil de caché de prompt: stable, task, volatile o all",
|
|
87
88
|
"context.help.exit.ok": "El contexto se inspeccionó e imprimió",
|
|
88
89
|
"context.title": "contexto mustflow",
|
|
90
|
+
"api.help.summary": "Imprime informes API estables legibles por máquinas para la raíz mustflow actual.",
|
|
91
|
+
"api.help.action.workspaceSummary": "Imprime un briefing de workspace de solo lectura para agentes de código",
|
|
92
|
+
"api.help.action.commandCatalog": "Imprime disponibilidad de intents de comandos sin exponer cadenas de ejecución sin procesar",
|
|
93
|
+
"api.help.action.verificationPlan": "Imprime un verification plan de solo lectura para archivos cambiados",
|
|
94
|
+
"api.help.action.latestEvidence": "Imprime evidencia bounded del último run o verify para agentes",
|
|
95
|
+
"api.help.action.diffRisk": "Imprime un resumen compacto de riesgo y verificación para archivos cambiados",
|
|
96
|
+
"api.help.action.health": "Imprime un resumen compacto de salud del workspace",
|
|
97
|
+
"api.help.exit.ok": "El informe API se inspeccionó e imprimió",
|
|
98
|
+
"api.error.missingAction": "Especifica una acción api: workspace-summary, command-catalog, verification-plan, latest-evidence, diff-risk o health",
|
|
99
|
+
"api.error.unknownAction": "Acción api desconocida: {action}",
|
|
100
|
+
"api.error.actionRequiresJson": "{action} requiere --json",
|
|
101
|
+
"api.error.actionRequiresChanged": "{action} actualmente requiere --changed",
|
|
89
102
|
"label.installed": "Instalado",
|
|
90
103
|
"label.mustflowRoot": "raíz mustflow",
|
|
91
104
|
"label.commandContract": "Especificación de comandos",
|
|
@@ -665,6 +678,8 @@ Lee estos archivos antes de trabajar:
|
|
|
665
678
|
"run.help.exit.ok": "El comando se completo con un codigo de salida permitido",
|
|
666
679
|
"run.help.exit.fail": "El comando no era válido, fue rechazado, agotó el tiempo o falló",
|
|
667
680
|
"run.label.suggestedIntentSnippet": "Snippet sugerido para el contrato de comandos",
|
|
681
|
+
"run.progress.started": "Ejecutando {intent} (timeout: {seconds}s)...",
|
|
682
|
+
"run.progress.timeoutWarning": "{intent} sigue ejecutándose... ({seconds}s transcurridos, {percent}% del timeout)",
|
|
668
683
|
"run.error.missingIntent": "Falta el nombre del comando",
|
|
669
684
|
"run.error.unknownIntent": "Comando desconocido: {intent}",
|
|
670
685
|
"run.error.statusNotConfigured": 'El comando "{intent}" está en estado {status}; sólo se pueden ejecutar comandos configurados',
|
package/dist/cli/i18n/fr.js
CHANGED
|
@@ -24,6 +24,7 @@ export const frMessages = {
|
|
|
24
24
|
"value.missing": "manquant",
|
|
25
25
|
"value.passed": "réussi",
|
|
26
26
|
"value.failed": "échoué",
|
|
27
|
+
"command.api.summary": "Imprime des rapports API stables lisibles par machine pour les agents",
|
|
27
28
|
"command.adapters.summary": "Inspecte la compatibilité des adaptateurs sans générer de fichiers",
|
|
28
29
|
"command.init.summary": "Copie le flux de travail d'agent mustflow par défaut",
|
|
29
30
|
"command.check.summary": "Valide les fichiers mustflow",
|
|
@@ -86,6 +87,18 @@ export const frMessages = {
|
|
|
86
87
|
"context.help.option.cacheProfile": "Imprime un profil de cache de prompt : stable, task, volatile ou all",
|
|
87
88
|
"context.help.exit.ok": "Le contexte a été inspecté et imprimé",
|
|
88
89
|
"context.title": "contexte mustflow",
|
|
90
|
+
"api.help.summary": "Imprime des rapports API stables lisibles par machine pour la racine mustflow actuelle.",
|
|
91
|
+
"api.help.action.workspaceSummary": "Imprime un briefing de workspace en lecture seule pour les agents de code",
|
|
92
|
+
"api.help.action.commandCatalog": "Affiche la disponibilité des intents de commande sans exposer les chaînes d'exécution brutes",
|
|
93
|
+
"api.help.action.verificationPlan": "Affiche un verification plan en lecture seule pour les fichiers modifiés",
|
|
94
|
+
"api.help.action.latestEvidence": "Affiche les dernières preuves bounded de run ou verify pour les agents",
|
|
95
|
+
"api.help.action.diffRisk": "Affiche un résumé compact du risque et de la vérification des fichiers modifiés",
|
|
96
|
+
"api.help.action.health": "Affiche un résumé compact de santé du workspace",
|
|
97
|
+
"api.help.exit.ok": "Le rapport API a été inspecté et imprimé",
|
|
98
|
+
"api.error.missingAction": "Indiquez une action api : workspace-summary, command-catalog, verification-plan, latest-evidence, diff-risk ou health",
|
|
99
|
+
"api.error.unknownAction": "Action api inconnue : {action}",
|
|
100
|
+
"api.error.actionRequiresJson": "{action} exige --json",
|
|
101
|
+
"api.error.actionRequiresChanged": "{action} exige actuellement --changed",
|
|
89
102
|
"label.installed": "Installé",
|
|
90
103
|
"label.mustflowRoot": "racine mustflow",
|
|
91
104
|
"label.commandContract": "Spécification des commandes",
|
|
@@ -665,6 +678,8 @@ Lisez ces fichiers avant de travailler :
|
|
|
665
678
|
"run.help.exit.ok": "La commande s'est terminée avec un code de sortie autorisé",
|
|
666
679
|
"run.help.exit.fail": "La commande était non valide, refusée, expirée ou a échoué",
|
|
667
680
|
"run.label.suggestedIntentSnippet": "Extrait suggéré de contrat de commande",
|
|
681
|
+
"run.progress.started": "Exécution de {intent} (timeout : {seconds}s)...",
|
|
682
|
+
"run.progress.timeoutWarning": "{intent} est toujours en cours... ({seconds}s écoulées, {percent}% du timeout)",
|
|
668
683
|
"run.error.missingIntent": "Nom de commande manquant",
|
|
669
684
|
"run.error.unknownIntent": "Commande inconnue : {intent}",
|
|
670
685
|
"run.error.statusNotConfigured": 'La commande "{intent}" est {status} ; seules les commandes configurées peuvent être exécutées',
|
package/dist/cli/i18n/hi.js
CHANGED
|
@@ -24,6 +24,7 @@ export const hiMessages = {
|
|
|
24
24
|
"value.missing": "गुम",
|
|
25
25
|
"value.passed": "पास",
|
|
26
26
|
"value.failed": "फेल",
|
|
27
|
+
"command.api.summary": "एजेंटों के लिए स्थिर machine-readable API रिपोर्ट प्रिंट करें",
|
|
27
28
|
"command.adapters.summary": "एडाप्टर फ़ाइलें बनाए बिना होस्ट संगतता जाँचें",
|
|
28
29
|
"command.init.summary": "डिफ़ॉल्ट mustflow एजेंट वर्कफ़्लो कॉपी करें",
|
|
29
30
|
"command.check.summary": "mustflow फ़ाइलों की जाँच करें",
|
|
@@ -86,6 +87,18 @@ export const hiMessages = {
|
|
|
86
87
|
"context.help.option.cacheProfile": "prompt cache profile प्रिंट करें: stable, task, volatile, या all",
|
|
87
88
|
"context.help.exit.ok": "संदर्भ जाँचा और प्रिंट किया गया",
|
|
88
89
|
"context.title": "mustflow संदर्भ",
|
|
90
|
+
"api.help.summary": "वर्तमान mustflow रूट के लिए स्थिर machine-readable API रिपोर्ट प्रिंट करें।",
|
|
91
|
+
"api.help.action.workspaceSummary": "कोडिंग एजेंटों के लिए read-only workspace briefing प्रिंट करें",
|
|
92
|
+
"api.help.action.commandCatalog": "raw command execution strings दिखाए बिना command intent availability प्रिंट करें",
|
|
93
|
+
"api.help.action.verificationPlan": "बदली गई फ़ाइलों के लिए read-only verification plan प्रिंट करें",
|
|
94
|
+
"api.help.action.latestEvidence": "agents के लिए bounded latest run या verify evidence प्रिंट करें",
|
|
95
|
+
"api.help.action.diffRisk": "बदली गई files के लिए compact risk और verification summary प्रिंट करें",
|
|
96
|
+
"api.help.action.health": "workspace health की compact summary प्रिंट करें",
|
|
97
|
+
"api.help.exit.ok": "API रिपोर्ट जाँची और प्रिंट की गई",
|
|
98
|
+
"api.error.missingAction": "api action बताएँ: workspace-summary, command-catalog, verification-plan, latest-evidence, diff-risk, या health",
|
|
99
|
+
"api.error.unknownAction": "अज्ञात api action: {action}",
|
|
100
|
+
"api.error.actionRequiresJson": "{action} के लिए --json चाहिए",
|
|
101
|
+
"api.error.actionRequiresChanged": "{action} को अभी --changed चाहिए",
|
|
89
102
|
"label.installed": "इंस्टॉल किया गया",
|
|
90
103
|
"label.mustflowRoot": "mustflow रूट",
|
|
91
104
|
"label.commandContract": "कमांड विनिर्देश",
|
|
@@ -665,6 +678,8 @@ export const hiMessages = {
|
|
|
665
678
|
"run.help.exit.ok": "कमांड अनुमत exit code के साथ पूरी हुई",
|
|
666
679
|
"run.help.exit.fail": "कमांड अमान्य थी, अस्वीकार हुई, timed out हुई या विफल हुई",
|
|
667
680
|
"run.label.suggestedIntentSnippet": "Suggested command contract snippet",
|
|
681
|
+
"run.progress.started": "{intent} चल रहा है (timeout: {seconds}s)...",
|
|
682
|
+
"run.progress.timeoutWarning": "{intent} अभी भी चल रहा है... ({seconds}s बीते, timeout का {percent}%)",
|
|
668
683
|
"run.error.missingIntent": "कमांड नाम नहीं दिया गया",
|
|
669
684
|
"run.error.unknownIntent": "अज्ञात कमांड: {intent}",
|
|
670
685
|
"run.error.statusNotConfigured": 'कमांड "{intent}" {status} है; केवल configured कमांड चलाई जा सकती हैं',
|
package/dist/cli/i18n/ko.js
CHANGED
|
@@ -24,6 +24,7 @@ export const koMessages = {
|
|
|
24
24
|
"value.missing": "없음",
|
|
25
25
|
"value.passed": "통과",
|
|
26
26
|
"value.failed": "실패",
|
|
27
|
+
"command.api.summary": "에이전트용 안정적 JSON API 보고서를 출력합니다",
|
|
27
28
|
"command.adapters.summary": "어댑터 파일을 만들지 않고 호스트 호환성을 확인합니다",
|
|
28
29
|
"command.init.summary": "기본 mustflow 에이전트 워크플로우를 복사합니다",
|
|
29
30
|
"command.check.summary": "mustflow 파일을 검사합니다",
|
|
@@ -86,6 +87,18 @@ export const koMessages = {
|
|
|
86
87
|
"context.help.option.cacheProfile": "프롬프트 캐시 프로필을 출력합니다: stable, task, volatile, all",
|
|
87
88
|
"context.help.exit.ok": "맥락을 확인하고 출력했습니다",
|
|
88
89
|
"context.title": "mustflow 맥락",
|
|
90
|
+
"api.help.summary": "현재 mustflow 루트의 안정적 JSON API 보고서를 출력합니다.",
|
|
91
|
+
"api.help.action.workspaceSummary": "코딩 에이전트용 읽기 전용 workspace briefing을 출력합니다",
|
|
92
|
+
"api.help.action.commandCatalog": "원본 실행 문자열을 노출하지 않고 command intent 실행 가능성을 출력합니다",
|
|
93
|
+
"api.help.action.verificationPlan": "변경 파일에 대한 읽기 전용 verification plan을 출력합니다",
|
|
94
|
+
"api.help.action.latestEvidence": "에이전트용 bounded 최신 run 또는 verify evidence를 출력합니다",
|
|
95
|
+
"api.help.action.diffRisk": "변경 파일 risk와 verification 요약을 작게 출력합니다",
|
|
96
|
+
"api.help.action.health": "workspace health 요약을 작게 출력합니다",
|
|
97
|
+
"api.help.exit.ok": "API 보고서를 확인하고 출력했습니다",
|
|
98
|
+
"api.error.missingAction": "api 작업을 지정하세요: workspace-summary, command-catalog, verification-plan, latest-evidence, diff-risk 또는 health",
|
|
99
|
+
"api.error.unknownAction": "알 수 없는 api 작업: {action}",
|
|
100
|
+
"api.error.actionRequiresJson": "{action}에는 --json이 필요합니다",
|
|
101
|
+
"api.error.actionRequiresChanged": "{action}은 현재 --changed가 필요합니다",
|
|
89
102
|
"label.installed": "설치됨",
|
|
90
103
|
"label.mustflowRoot": "mustflow 루트",
|
|
91
104
|
"label.commandContract": "명령 계약",
|
|
@@ -665,6 +678,8 @@ export const koMessages = {
|
|
|
665
678
|
"run.help.exit.ok": "명령이 허용된 종료 코드로 완료되었습니다",
|
|
666
679
|
"run.help.exit.fail": "명령이 잘못되었거나, 거부되었거나, 시간 초과되었거나, 실패했습니다",
|
|
667
680
|
"run.label.suggestedIntentSnippet": "제안 명령 계약 조각",
|
|
681
|
+
"run.progress.started": "{intent} 실행 중(timeout: {seconds}초)...",
|
|
682
|
+
"run.progress.timeoutWarning": "{intent} 계속 실행 중... ({seconds}초 경과, timeout의 {percent}%)",
|
|
668
683
|
"run.error.missingIntent": "명령 이름이 없습니다",
|
|
669
684
|
"run.error.unknownIntent": "알 수 없는 명령: {intent}",
|
|
670
685
|
"run.error.statusNotConfigured": '명령 "{intent}"의 상태는 {status}입니다. 설정된 상태(configured)인 명령만 실행할 수 있습니다',
|
package/dist/cli/i18n/zh.js
CHANGED
|
@@ -24,6 +24,7 @@ export const zhMessages = {
|
|
|
24
24
|
"value.missing": "缺失",
|
|
25
25
|
"value.passed": "通过",
|
|
26
26
|
"value.failed": "失败",
|
|
27
|
+
"command.api.summary": "为代理输出稳定的机器可读 API 报告",
|
|
27
28
|
"command.adapters.summary": "不生成适配器文件,检查宿主兼容性",
|
|
28
29
|
"command.init.summary": "复制默认的 mustflow 代理工作流",
|
|
29
30
|
"command.check.summary": "验证 mustflow 文件",
|
|
@@ -86,6 +87,18 @@ export const zhMessages = {
|
|
|
86
87
|
"context.help.option.cacheProfile": "输出提示缓存配置文件:stable、task、volatile 或 all",
|
|
87
88
|
"context.help.exit.ok": "已检查并输出上下文",
|
|
88
89
|
"context.title": "mustflow 上下文",
|
|
90
|
+
"api.help.summary": "为当前 mustflow 根目录输出稳定的机器可读 API 报告。",
|
|
91
|
+
"api.help.action.workspaceSummary": "为代码代理输出只读 workspace 简报",
|
|
92
|
+
"api.help.action.commandCatalog": "输出命令 intent 可用性,但不暴露原始执行字符串",
|
|
93
|
+
"api.help.action.verificationPlan": "为已变更文件输出只读 verification plan",
|
|
94
|
+
"api.help.action.latestEvidence": "为代理输出 bounded 最新 run 或 verify evidence",
|
|
95
|
+
"api.help.action.diffRisk": "为已变更文件输出紧凑 risk 和 verification 摘要",
|
|
96
|
+
"api.help.action.health": "输出紧凑 workspace health 摘要",
|
|
97
|
+
"api.help.exit.ok": "已检查并输出 API 报告",
|
|
98
|
+
"api.error.missingAction": "请指定 api 操作:workspace-summary、command-catalog、verification-plan、latest-evidence、diff-risk 或 health",
|
|
99
|
+
"api.error.unknownAction": "未知 api 操作:{action}",
|
|
100
|
+
"api.error.actionRequiresJson": "{action} 需要 --json",
|
|
101
|
+
"api.error.actionRequiresChanged": "{action} 当前需要 --changed",
|
|
89
102
|
"label.installed": "已安装",
|
|
90
103
|
"label.mustflowRoot": "mustflow 根目录",
|
|
91
104
|
"label.commandContract": "命令规范",
|
|
@@ -665,6 +678,8 @@ export const zhMessages = {
|
|
|
665
678
|
"run.help.exit.ok": "命令已以允许的退出码完成",
|
|
666
679
|
"run.help.exit.fail": "命令无效、被拒绝、超时或失败",
|
|
667
680
|
"run.label.suggestedIntentSnippet": "建议的命令契约片段",
|
|
681
|
+
"run.progress.started": "正在运行 {intent}(超时:{seconds} 秒)...",
|
|
682
|
+
"run.progress.timeoutWarning": "{intent} 仍在运行...(已用 {seconds} 秒,达到超时的 {percent}%)",
|
|
668
683
|
"run.error.missingIntent": "缺少命令名称",
|
|
669
684
|
"run.error.unknownIntent": "未知命令:{intent}",
|
|
670
685
|
"run.error.statusNotConfigured": '命令 "{intent}" 的状态为 {status};只能运行已配置的命令',
|
package/dist/cli/index.js
CHANGED
|
@@ -32,5 +32,5 @@ export function renderCliError(message, helpCommand, lang = 'en') {
|
|
|
32
32
|
}
|
|
33
33
|
export function printUsageError(reporter, message, helpCommand, helpText, lang = 'en') {
|
|
34
34
|
reporter.stderr(renderCliError(message, helpCommand, lang));
|
|
35
|
-
reporter.
|
|
35
|
+
reporter.stderr(helpText);
|
|
36
36
|
}
|
|
@@ -146,6 +146,10 @@ function updateSaveState() {
|
|
|
146
146
|
document.getElementById("save").disabled = pending.size === 0;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
function hasUnsavedChanges() {
|
|
150
|
+
return pending.size > 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
149
153
|
function setPending(id, value) {
|
|
150
154
|
const original = snapshot.settings.find((setting) => setting.id === id)?.value;
|
|
151
155
|
if (Object.is(original, value)) {
|
|
@@ -1899,6 +1903,11 @@ document.getElementById("reload").addEventListener("click", () => {
|
|
|
1899
1903
|
document.getElementById("save").addEventListener("click", () => {
|
|
1900
1904
|
save().catch((error) => statusText(error.message, "error"));
|
|
1901
1905
|
});
|
|
1906
|
+
window.addEventListener("beforeunload", (event) => {
|
|
1907
|
+
if (!hasUnsavedChanges()) return;
|
|
1908
|
+
event.preventDefault();
|
|
1909
|
+
event.returnValue = "";
|
|
1910
|
+
});
|
|
1902
1911
|
document.getElementById("open-mustflow").addEventListener("click", () => {
|
|
1903
1912
|
openMustflowFolder().catch((error) => statusText(error.message, "error"));
|
|
1904
1913
|
});
|
|
@@ -9,6 +9,9 @@ export function renderDashboardStyles() {
|
|
|
9
9
|
--accent: #8fb4ff;
|
|
10
10
|
--danger: #ff9a9a;
|
|
11
11
|
--ok: #9be7ba;
|
|
12
|
+
--control-bg: #11141a;
|
|
13
|
+
--control-hover-bg: #171b23;
|
|
14
|
+
--control-active-bg: #0d1015;
|
|
12
15
|
--row-bg: rgba(255, 255, 255, 0.018);
|
|
13
16
|
--row-bg-alt: rgba(255, 255, 255, 0.035);
|
|
14
17
|
--status-neutral-bg: rgba(174, 182, 197, 0.1);
|
|
@@ -16,6 +19,27 @@ export function renderDashboardStyles() {
|
|
|
16
19
|
--status-warn-bg: rgba(255, 154, 154, 0.1);
|
|
17
20
|
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
18
21
|
}
|
|
22
|
+
@media (prefers-color-scheme: light) {
|
|
23
|
+
:root {
|
|
24
|
+
color-scheme: light;
|
|
25
|
+
--bg: #f6f8fb;
|
|
26
|
+
--panel: #ffffff;
|
|
27
|
+
--line: #d9e0ea;
|
|
28
|
+
--text: #162033;
|
|
29
|
+
--muted: #5d6b82;
|
|
30
|
+
--accent: #285fc2;
|
|
31
|
+
--danger: #b4232d;
|
|
32
|
+
--ok: #197a47;
|
|
33
|
+
--control-bg: #ffffff;
|
|
34
|
+
--control-hover-bg: #eef3f9;
|
|
35
|
+
--control-active-bg: #e4ebf5;
|
|
36
|
+
--row-bg: rgba(40, 95, 194, 0.035);
|
|
37
|
+
--row-bg-alt: rgba(40, 95, 194, 0.065);
|
|
38
|
+
--status-neutral-bg: rgba(93, 107, 130, 0.11);
|
|
39
|
+
--status-ok-bg: rgba(25, 122, 71, 0.11);
|
|
40
|
+
--status-warn-bg: rgba(180, 35, 45, 0.1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
19
43
|
* { box-sizing: border-box; }
|
|
20
44
|
body {
|
|
21
45
|
margin: 0;
|
|
@@ -75,6 +99,11 @@ main {
|
|
|
75
99
|
gap: 8px;
|
|
76
100
|
margin-bottom: 14px;
|
|
77
101
|
overflow-x: auto;
|
|
102
|
+
-webkit-overflow-scrolling: touch;
|
|
103
|
+
scrollbar-width: none;
|
|
104
|
+
}
|
|
105
|
+
.tabs::-webkit-scrollbar {
|
|
106
|
+
display: none;
|
|
78
107
|
}
|
|
79
108
|
.tab {
|
|
80
109
|
border-color: transparent;
|
|
@@ -120,17 +149,35 @@ input:focus-visible {
|
|
|
120
149
|
white-space: nowrap;
|
|
121
150
|
}
|
|
122
151
|
button, select, input {
|
|
123
|
-
background:
|
|
152
|
+
background: var(--control-bg);
|
|
124
153
|
border: 1px solid var(--line);
|
|
125
154
|
border-radius: 6px;
|
|
126
155
|
color: var(--text);
|
|
127
156
|
font: inherit;
|
|
128
157
|
min-height: 38px;
|
|
158
|
+
transition: background-color 160ms ease, border-color 160ms ease;
|
|
129
159
|
}
|
|
130
160
|
button {
|
|
131
161
|
cursor: pointer;
|
|
132
162
|
padding: 0 14px;
|
|
133
163
|
}
|
|
164
|
+
button:not(:disabled):hover,
|
|
165
|
+
select:hover,
|
|
166
|
+
input:hover {
|
|
167
|
+
background: var(--control-hover-bg);
|
|
168
|
+
border-color: var(--accent);
|
|
169
|
+
}
|
|
170
|
+
button:not(:disabled):active {
|
|
171
|
+
background: var(--control-active-bg);
|
|
172
|
+
}
|
|
173
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
174
|
+
button {
|
|
175
|
+
transition: background-color 160ms ease, border-color 160ms ease, transform 120ms ease;
|
|
176
|
+
}
|
|
177
|
+
button:not(:disabled):active {
|
|
178
|
+
transform: translateY(1px);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
134
181
|
button:disabled {
|
|
135
182
|
cursor: not-allowed;
|
|
136
183
|
opacity: 0.6;
|
|
@@ -75,7 +75,7 @@ function readLedgerFile(projectRoot) {
|
|
|
75
75
|
const ledgerPath = path.join(projectRoot, DOC_REVIEW_LEDGER_RELATIVE_PATH);
|
|
76
76
|
const ledgerDirectoryPath = path.dirname(ledgerPath);
|
|
77
77
|
ensureInside(projectRoot, ledgerPath);
|
|
78
|
-
ensureInsideWithoutSymlinks(projectRoot, ledgerDirectoryPath, {
|
|
78
|
+
ensureInsideWithoutSymlinks(projectRoot, ledgerDirectoryPath, { allowMissingDescendant: true });
|
|
79
79
|
if (!existsSync(ledgerDirectoryPath)) {
|
|
80
80
|
return { schema_version: '1', documents: [] };
|
|
81
81
|
}
|