mustflow 2.22.3 → 2.22.5
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 +9 -75
- package/dist/cli/commands/contract-lint.js +2 -2
- package/dist/cli/commands/dashboard.js +14 -6
- package/dist/cli/commands/help.js +8 -9
- package/dist/cli/commands/impact.js +2 -3
- package/dist/cli/commands/init.js +61 -5
- package/dist/cli/commands/update.js +2 -2
- package/dist/cli/commands/version-sources.js +2 -3
- package/dist/cli/i18n/en.js +2 -0
- package/dist/cli/i18n/es.js +2 -0
- package/dist/cli/i18n/fr.js +2 -0
- package/dist/cli/i18n/hi.js +2 -0
- package/dist/cli/i18n/ko.js +2 -0
- package/dist/cli/i18n/zh.js +2 -0
- package/dist/cli/lib/agent-context.js +6 -11
- package/dist/cli/lib/local-index/index.js +14 -11
- package/dist/cli/lib/mustflow-read.js +41 -0
- package/dist/cli/lib/project-root.js +1 -2
- package/dist/cli/lib/repo-map.js +65 -16
- package/dist/cli/lib/templates.js +124 -8
- package/dist/cli/lib/toml.js +6 -1
- package/dist/cli/lib/validation/constants.js +2 -0
- package/dist/cli/lib/validation/index.js +291 -22
- package/dist/cli/lib/validation/primitives.js +2 -2
- package/dist/cli/lib/validation/test-selection.js +2 -2
- package/dist/core/bounded-output.js +32 -7
- package/dist/core/check-issues.js +7 -1
- package/dist/core/command-contract-validation.js +28 -4
- package/dist/core/command-env.js +1 -1
- package/dist/core/config-loading.js +9 -3
- package/dist/core/contract-lint.js +2 -1
- package/dist/core/safe-filesystem.js +11 -4
- package/dist/core/skill-route-alignment.js +1 -0
- package/dist/core/skill-route-explanation.js +9 -3
- package/dist/core/test-selection.js +2 -3
- package/dist/core/verification-scheduler.js +7 -6
- package/dist/core/version-sources.js +2 -3
- package/package.json +4 -2
- package/schemas/commands.schema.json +1 -0
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +10 -6
- package/templates/default/locales/en/.mustflow/skills/routes.toml +2 -2
- package/templates/default/manifest.toml +1 -1
package/dist/cli/lib/repo-map.js
CHANGED
|
@@ -4,7 +4,7 @@ import { existsSync, lstatSync, readdirSync, realpathSync, statSync } from 'node
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { toPosixPath } from './filesystem.js';
|
|
6
6
|
import { writeUtf8FileInsideWithoutSymlinks } from '../../core/safe-filesystem.js';
|
|
7
|
-
import {
|
|
7
|
+
import { readMustflowTomlFile } from './toml.js';
|
|
8
8
|
const DEFAULT_DEPTH = 3;
|
|
9
9
|
const REPO_MAP_DOC_ID = 'repo-map';
|
|
10
10
|
const REPO_MAP_LIFECYCLE = 'generated';
|
|
@@ -214,7 +214,7 @@ function readMustflowConfig(projectRoot) {
|
|
|
214
214
|
return {};
|
|
215
215
|
}
|
|
216
216
|
try {
|
|
217
|
-
const parsed =
|
|
217
|
+
const parsed = readMustflowTomlFile(projectRoot, '.mustflow/config/mustflow.toml');
|
|
218
218
|
return isRecord(parsed) ? parsed : {};
|
|
219
219
|
}
|
|
220
220
|
catch {
|
|
@@ -243,7 +243,19 @@ function getRepoMapConfig(projectRoot) {
|
|
|
243
243
|
},
|
|
244
244
|
};
|
|
245
245
|
}
|
|
246
|
-
|
|
246
|
+
function classifyGitLsFilesFailure(result) {
|
|
247
|
+
const errorRecord = result.error;
|
|
248
|
+
const errorCode = typeof errorRecord?.code === 'string' ? errorRecord.code : undefined;
|
|
249
|
+
const errorMessage = result.error?.message ?? '';
|
|
250
|
+
if (errorCode === 'ETIMEDOUT' || /timed?\s*out|ETIMEDOUT/iu.test(errorMessage)) {
|
|
251
|
+
return 'timeout';
|
|
252
|
+
}
|
|
253
|
+
if (errorCode === 'ENOBUFS' || /maxBuffer|ENOBUFS|buffer/iu.test(errorMessage)) {
|
|
254
|
+
return 'max_buffer';
|
|
255
|
+
}
|
|
256
|
+
return 'error';
|
|
257
|
+
}
|
|
258
|
+
export function discoverGitFilesForRepoMap(projectRoot, options = {}) {
|
|
247
259
|
const spawnGit = options.spawnGit ??
|
|
248
260
|
((command, args, spawnOptions) => spawnSync(command, [...args], spawnOptions));
|
|
249
261
|
const result = spawnGit('git', ['ls-files', '-z'], {
|
|
@@ -254,12 +266,21 @@ export function listGitFilesForRepoMap(projectRoot, options = {}) {
|
|
|
254
266
|
windowsHide: true,
|
|
255
267
|
});
|
|
256
268
|
if (result.status !== 0 || result.error) {
|
|
257
|
-
return
|
|
269
|
+
return {
|
|
270
|
+
files: [],
|
|
271
|
+
status: classifyGitLsFilesFailure(result),
|
|
272
|
+
};
|
|
258
273
|
}
|
|
259
|
-
return
|
|
260
|
-
.
|
|
261
|
-
|
|
262
|
-
|
|
274
|
+
return {
|
|
275
|
+
files: result.stdout
|
|
276
|
+
.split('\0')
|
|
277
|
+
.map((line) => toPosixPath(line))
|
|
278
|
+
.filter(Boolean),
|
|
279
|
+
status: 'ok',
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
export function listGitFilesForRepoMap(projectRoot, options = {}) {
|
|
283
|
+
return discoverGitFilesForRepoMap(projectRoot, options).files;
|
|
263
284
|
}
|
|
264
285
|
function isAnchorCandidatePath(relativePath, priorityPaths) {
|
|
265
286
|
return priorityPaths.has(relativePath) || Boolean(getAnchorDescription(relativePath));
|
|
@@ -290,13 +311,17 @@ function listAnchorCandidateFilesRecursive(rootPath, depth, priorityPaths) {
|
|
|
290
311
|
}
|
|
291
312
|
function getRepositoryFiles(projectRoot, depth, priorityPaths) {
|
|
292
313
|
const files = new Set();
|
|
293
|
-
|
|
314
|
+
const gitFiles = discoverGitFilesForRepoMap(projectRoot);
|
|
315
|
+
for (const relativePath of gitFiles.files) {
|
|
294
316
|
files.add(relativePath);
|
|
295
317
|
}
|
|
296
318
|
for (const relativePath of listAnchorCandidateFilesRecursive(projectRoot, depth, priorityPaths)) {
|
|
297
319
|
files.add(relativePath);
|
|
298
320
|
}
|
|
299
|
-
return
|
|
321
|
+
return {
|
|
322
|
+
files: Array.from(files),
|
|
323
|
+
gitLsFilesStatus: gitFiles.status,
|
|
324
|
+
};
|
|
300
325
|
}
|
|
301
326
|
function shouldIncludePath(relativePath) {
|
|
302
327
|
if (GENERATED_FILES.has(relativePath)) {
|
|
@@ -341,7 +366,8 @@ function isUnderExcludedPrefix(relativePath, excludedPrefixes) {
|
|
|
341
366
|
return excludedPrefixes.some((prefix) => relativePath === prefix.slice(0, -1) || relativePath.startsWith(prefix));
|
|
342
367
|
}
|
|
343
368
|
function discoverAnchors(projectRoot, depth, priorityPaths, nestedRepositories, excludedPrefixes) {
|
|
344
|
-
|
|
369
|
+
const repositoryFiles = getRepositoryFiles(projectRoot, depth, priorityPaths);
|
|
370
|
+
const anchors = repositoryFiles.files
|
|
345
371
|
.filter(shouldIncludePath)
|
|
346
372
|
.filter((relativePath) => !isUnderNestedRepository(relativePath, nestedRepositories))
|
|
347
373
|
.filter((relativePath) => !isUnderExcludedPrefix(relativePath, excludedPrefixes))
|
|
@@ -352,6 +378,10 @@ function discoverAnchors(projectRoot, depth, priorityPaths, nestedRepositories,
|
|
|
352
378
|
.filter((anchor) => Boolean(anchor))
|
|
353
379
|
.filter((anchor) => priorityPaths.has(anchor.relativePath) || getDirectoryDepth(anchor.relativePath) <= depth)
|
|
354
380
|
.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
|
|
381
|
+
return {
|
|
382
|
+
anchors,
|
|
383
|
+
gitLsFilesStatus: repositoryFiles.gitLsFilesStatus,
|
|
384
|
+
};
|
|
355
385
|
}
|
|
356
386
|
function renderAnchorList(anchors) {
|
|
357
387
|
return anchors.map((anchor) => `- \`${anchor.relativePath}\`: ${anchor.description}`);
|
|
@@ -594,10 +624,11 @@ function countNestedEntrypoints(repository) {
|
|
|
594
624
|
...repository.editingPolicies,
|
|
595
625
|
].filter(Boolean).length;
|
|
596
626
|
}
|
|
597
|
-
function getSourceFingerprint(depth, includeNested, configuredPriorityPaths, anchors, nestedRepositories) {
|
|
627
|
+
function getSourceFingerprint(depth, includeNested, configuredPriorityPaths, gitLsFilesStatus, anchors, nestedRepositories) {
|
|
598
628
|
const payload = {
|
|
599
629
|
depth,
|
|
600
630
|
includeNested,
|
|
631
|
+
gitLsFilesStatus,
|
|
601
632
|
priorityPaths: [...configuredPriorityPaths].sort(),
|
|
602
633
|
anchors: anchors.map((anchor) => anchor.relativePath).sort(),
|
|
603
634
|
nestedRepositories: nestedRepositories
|
|
@@ -621,7 +652,8 @@ function getSourceFingerprint(depth, includeNested, configuredPriorityPaths, anc
|
|
|
621
652
|
const digest = createHash('sha256').update(JSON.stringify(payload)).digest('hex');
|
|
622
653
|
return `sha256:${digest}`;
|
|
623
654
|
}
|
|
624
|
-
function renderRepoMapFrontmatter(anchorCount, sourceFingerprint) {
|
|
655
|
+
function renderRepoMapFrontmatter(anchorCount, sourceFingerprint, gitLsFilesStatus) {
|
|
656
|
+
const degraded = gitLsFilesStatus !== 'ok';
|
|
625
657
|
return [
|
|
626
658
|
'---',
|
|
627
659
|
`mustflow_doc: ${REPO_MAP_DOC_ID}`,
|
|
@@ -631,11 +663,25 @@ function renderRepoMapFrontmatter(anchorCount, sourceFingerprint) {
|
|
|
631
663
|
`source_policy: ${REPO_MAP_SOURCE_POLICY}`,
|
|
632
664
|
`privacy_mode: ${REPO_MAP_PRIVACY_MODE}`,
|
|
633
665
|
`anchor_count: ${anchorCount}`,
|
|
666
|
+
`degraded: ${degraded ? 'true' : 'false'}`,
|
|
667
|
+
`git_ls_files_status: ${gitLsFilesStatus}`,
|
|
634
668
|
`source_fingerprint: "${sourceFingerprint}"`,
|
|
635
669
|
'---',
|
|
636
670
|
'',
|
|
637
671
|
];
|
|
638
672
|
}
|
|
673
|
+
function renderSourceQuality(gitLsFilesStatus) {
|
|
674
|
+
if (gitLsFilesStatus === 'ok') {
|
|
675
|
+
return [];
|
|
676
|
+
}
|
|
677
|
+
return [
|
|
678
|
+
'## Source Quality',
|
|
679
|
+
'',
|
|
680
|
+
`- \`git ls-files\` status: \`${gitLsFilesStatus}\``,
|
|
681
|
+
'- Anchor discovery used the bounded recursive fallback. Treat this map as incomplete until regenerated after Git file discovery succeeds.',
|
|
682
|
+
'',
|
|
683
|
+
];
|
|
684
|
+
}
|
|
639
685
|
export function generateRepoMap(projectRoot, options = {}) {
|
|
640
686
|
const depth = options.depth ?? DEFAULT_DEPTH;
|
|
641
687
|
const config = getRepoMapConfig(projectRoot);
|
|
@@ -647,15 +693,17 @@ export function generateRepoMap(projectRoot, options = {}) {
|
|
|
647
693
|
};
|
|
648
694
|
const nestedRepositories = discoverNestedRepositories(projectRoot, mapConfig, config.workspace);
|
|
649
695
|
const workspaceRootPrefixes = getWorkspaceRootPrefixes(projectRoot, config.workspace);
|
|
650
|
-
const
|
|
696
|
+
const anchorDiscovery = discoverAnchors(projectRoot, depth, priorityPathSet, nestedRepositories, workspaceRootPrefixes);
|
|
697
|
+
const anchors = anchorDiscovery.anchors;
|
|
698
|
+
const gitLsFilesStatus = anchorDiscovery.gitLsFilesStatus;
|
|
651
699
|
const priorityAnchors = configuredPriorityPaths
|
|
652
700
|
.map((relativePath) => anchors.find((anchor) => anchor.relativePath === relativePath))
|
|
653
701
|
.filter((anchor) => Boolean(anchor));
|
|
654
702
|
const otherAnchors = anchors.filter((anchor) => !priorityPathSet.has(anchor.relativePath));
|
|
655
703
|
const anchorCount = anchors.length + nestedRepositories.reduce((total, repository) => total + countNestedEntrypoints(repository), 0);
|
|
656
|
-
const sourceFingerprint = getSourceFingerprint(depth, mapConfig.includeNested, configuredPriorityPaths, anchors, nestedRepositories);
|
|
704
|
+
const sourceFingerprint = getSourceFingerprint(depth, mapConfig.includeNested, configuredPriorityPaths, gitLsFilesStatus, anchors, nestedRepositories);
|
|
657
705
|
return [
|
|
658
|
-
...renderRepoMapFrontmatter(anchorCount, sourceFingerprint),
|
|
706
|
+
...renderRepoMapFrontmatter(anchorCount, sourceFingerprint, gitLsFilesStatus),
|
|
659
707
|
'# REPO_MAP.md',
|
|
660
708
|
'',
|
|
661
709
|
'This file is an agent navigation map for the current mustflow root. It is not a full file listing.',
|
|
@@ -670,6 +718,7 @@ export function generateRepoMap(projectRoot, options = {}) {
|
|
|
670
718
|
: []),
|
|
671
719
|
'- Use `git ls-files` or your editor when you need the complete file list.',
|
|
672
720
|
'',
|
|
721
|
+
...renderSourceQuality(gitLsFilesStatus),
|
|
673
722
|
'## Priority Anchors',
|
|
674
723
|
'',
|
|
675
724
|
...(priorityAnchors.length > 0 ? renderAnchorList(priorityAnchors) : ['No mustflow priority anchors were found.']),
|
|
@@ -2,6 +2,8 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { parse } from 'smol-toml';
|
|
5
|
+
const DEV_TEMPLATE_ROOT_ENV = 'MUSTFLOW_DEV_TEMPLATE_ROOT';
|
|
6
|
+
const ALLOW_DEV_TEMPLATE_ROOT_ENV = 'MUSTFLOW_ALLOW_DEV_TEMPLATE_ROOT';
|
|
5
7
|
function readStringGroup(raw, label) {
|
|
6
8
|
if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
|
|
7
9
|
throw new Error(`Template manifest is missing table: ${label}`);
|
|
@@ -69,15 +71,124 @@ function shouldIncludeTemplatePath(relativePath, selectedSkills) {
|
|
|
69
71
|
}
|
|
70
72
|
return selectedSkills.includes(skillName);
|
|
71
73
|
}
|
|
74
|
+
const SKILL_INDEX_SKILL_PATH_PATTERN = /`\.mustflow\/skills\/([^/]+)\/SKILL\.md`/u;
|
|
75
|
+
const SKILL_INDEX_HEADING_PATTERN = /^(#{2,3})\s+(.+?)\s*$/u;
|
|
76
|
+
const SKILL_INDEX_ROUTE_CATEGORY_NAMES = [
|
|
77
|
+
'Bug and Failure',
|
|
78
|
+
'General Code Change',
|
|
79
|
+
'Tests and Regression',
|
|
80
|
+
'Documentation and Release',
|
|
81
|
+
'Security and Privacy',
|
|
82
|
+
'Data and External Systems',
|
|
83
|
+
'UI and Assets',
|
|
84
|
+
'Architecture Patterns',
|
|
85
|
+
'Workflow and Contract Maintenance',
|
|
86
|
+
];
|
|
87
|
+
function skillNameFromSkillIndexLine(line) {
|
|
88
|
+
return SKILL_INDEX_SKILL_PATH_PATTERN.exec(line)?.[1];
|
|
89
|
+
}
|
|
90
|
+
function parseMarkdownTableCells(line) {
|
|
91
|
+
const trimmedLine = line.trim();
|
|
92
|
+
if (!trimmedLine.startsWith('|') || !trimmedLine.endsWith('|')) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
return trimmedLine
|
|
96
|
+
.slice(1, -1)
|
|
97
|
+
.split('|')
|
|
98
|
+
.map((cell) => cell.trim());
|
|
99
|
+
}
|
|
100
|
+
function isMarkdownTableDivider(cells) {
|
|
101
|
+
return cells.every((cell) => /^:?-{3,}:?$/u.test(cell));
|
|
102
|
+
}
|
|
103
|
+
function isMarkdownTableHeading(cells) {
|
|
104
|
+
const firstCell = cells[0] ?? '';
|
|
105
|
+
return [
|
|
106
|
+
'Category',
|
|
107
|
+
'Classification evidence',
|
|
108
|
+
'Trigger',
|
|
109
|
+
].includes(firstCell);
|
|
110
|
+
}
|
|
111
|
+
function referencedSkillIndexCategories(text) {
|
|
112
|
+
return SKILL_INDEX_ROUTE_CATEGORY_NAMES.filter((categoryName) => text.includes(categoryName));
|
|
113
|
+
}
|
|
114
|
+
function collectSelectedSkillIndexCategories(lines, selectedSkillSet) {
|
|
115
|
+
const selectedCategories = new Set();
|
|
116
|
+
let inSpecificRoutes = false;
|
|
117
|
+
let currentCategory;
|
|
118
|
+
for (const line of lines) {
|
|
119
|
+
const heading = SKILL_INDEX_HEADING_PATTERN.exec(line);
|
|
120
|
+
if (heading) {
|
|
121
|
+
const [, level, title] = heading;
|
|
122
|
+
if (level === '##') {
|
|
123
|
+
inSpecificRoutes = title === 'Specific Routes';
|
|
124
|
+
currentCategory = undefined;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (inSpecificRoutes && level === '###') {
|
|
128
|
+
currentCategory = title;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const skillName = skillNameFromSkillIndexLine(line);
|
|
132
|
+
if (inSpecificRoutes && currentCategory && skillName && selectedSkillSet.has(skillName)) {
|
|
133
|
+
selectedCategories.add(currentCategory);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return selectedCategories;
|
|
137
|
+
}
|
|
138
|
+
function shouldKeepSkillIndexTableRow(line, currentSection, selectedCategories) {
|
|
139
|
+
const cells = parseMarkdownTableCells(line);
|
|
140
|
+
if (!cells || isMarkdownTableDivider(cells) || isMarkdownTableHeading(cells)) {
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
if (currentSection === 'Route Category Gate') {
|
|
144
|
+
const categoryName = cells[0] ?? '';
|
|
145
|
+
return !SKILL_INDEX_ROUTE_CATEGORY_NAMES.includes(categoryName) ||
|
|
146
|
+
selectedCategories.has(categoryName);
|
|
147
|
+
}
|
|
148
|
+
if (currentSection === 'Classification Prefilter') {
|
|
149
|
+
const categoryNames = referencedSkillIndexCategories(cells.join(' '));
|
|
150
|
+
return categoryNames.length === 0 || categoryNames.some((categoryName) => selectedCategories.has(categoryName));
|
|
151
|
+
}
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
72
154
|
function filterSkillIndexContent(content, selectedSkills) {
|
|
73
155
|
const selectedSkillSet = new Set(selectedSkills);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
.
|
|
156
|
+
const lines = content.split(/\r?\n/u);
|
|
157
|
+
const selectedCategories = collectSelectedSkillIndexCategories(lines, selectedSkillSet);
|
|
158
|
+
const filteredLines = [];
|
|
159
|
+
let currentSection;
|
|
160
|
+
let skipCurrentSpecificCategory = false;
|
|
161
|
+
for (const line of lines) {
|
|
162
|
+
const heading = SKILL_INDEX_HEADING_PATTERN.exec(line);
|
|
163
|
+
if (heading) {
|
|
164
|
+
const [, level, title] = heading;
|
|
165
|
+
if (level === '##') {
|
|
166
|
+
currentSection = title;
|
|
167
|
+
skipCurrentSpecificCategory = false;
|
|
168
|
+
filteredLines.push(line);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (currentSection === 'Specific Routes' && level === '###') {
|
|
172
|
+
skipCurrentSpecificCategory = !selectedCategories.has(title);
|
|
173
|
+
if (!skipCurrentSpecificCategory) {
|
|
174
|
+
filteredLines.push(line);
|
|
175
|
+
}
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (skipCurrentSpecificCategory) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
const skillName = skillNameFromSkillIndexLine(line);
|
|
183
|
+
if (skillName && !selectedSkillSet.has(skillName)) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (!shouldKeepSkillIndexTableRow(line, currentSection, selectedCategories)) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
filteredLines.push(line);
|
|
190
|
+
}
|
|
191
|
+
return filteredLines.join('\n').replace(/\n{3,}/gu, '\n\n');
|
|
81
192
|
}
|
|
82
193
|
function filterSkillRouteMetadataContent(content, selectedSkills) {
|
|
83
194
|
const selectedSkillSet = new Set(selectedSkills);
|
|
@@ -166,7 +277,12 @@ function readManifest(manifestPath) {
|
|
|
166
277
|
};
|
|
167
278
|
}
|
|
168
279
|
export function getDefaultTemplate() {
|
|
169
|
-
const
|
|
280
|
+
const packagedTemplateRoot = fileURLToPath(new URL('../../../templates/default', import.meta.url));
|
|
281
|
+
const templateRootOverride = process.env[DEV_TEMPLATE_ROOT_ENV];
|
|
282
|
+
const selectedTemplateRoot = templateRootOverride && process.env[ALLOW_DEV_TEMPLATE_ROOT_ENV] === '1'
|
|
283
|
+
? templateRootOverride
|
|
284
|
+
: packagedTemplateRoot;
|
|
285
|
+
const templateRoot = path.resolve(selectedTemplateRoot);
|
|
170
286
|
const manifestPath = path.join(templateRoot, 'manifest.toml');
|
|
171
287
|
const manifest = readManifest(manifestPath);
|
|
172
288
|
return {
|
package/dist/cli/lib/toml.js
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { parseTomlText, readTomlFile, stringifyToml } from '../../core/toml.js';
|
|
2
|
+
import { MUSTFLOW_TOML_MAX_BYTES, readMustflowTextFile } from './mustflow-read.js';
|
|
3
|
+
export { parseTomlText, readTomlFile, stringifyToml };
|
|
4
|
+
export function readMustflowTomlFile(projectRoot, relativePath) {
|
|
5
|
+
return parseTomlText(readMustflowTextFile(projectRoot, relativePath, { maxBytes: MUSTFLOW_TOML_MAX_BYTES }));
|
|
6
|
+
}
|
|
@@ -198,6 +198,8 @@ export const REPO_MAP_RELATIVE_ROOT = '.';
|
|
|
198
198
|
export const REPO_MAP_SOURCE_POLICY = 'anchors_only';
|
|
199
199
|
export const REPO_MAP_PRIVACY_MODE = 'minimal';
|
|
200
200
|
export const REPO_MAP_SOURCE_FINGERPRINT_PATTERN = /^sha256:[a-f0-9]{64}$/u;
|
|
201
|
+
export const ALLOWED_REPO_MAP_DEGRADED_VALUES = new Set(['true', 'false']);
|
|
202
|
+
export const ALLOWED_REPO_MAP_GIT_LS_FILES_STATUSES = new Set(['ok', 'timeout', 'max_buffer', 'error']);
|
|
201
203
|
export const SKILL_RESOURCE_MANIFEST = 'resources.toml';
|
|
202
204
|
export const SKILL_RESOURCE_ROOTS = new Set(['references', 'assets', 'scripts']);
|
|
203
205
|
export const ALLOWED_SKILL_RESOURCE_TYPES = new Set(['reference', 'asset', 'script']);
|