mustflow 2.75.1 → 2.84.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.
Files changed (41) hide show
  1. package/README.md +31 -3
  2. package/dist/cli/commands/docs.js +86 -2
  3. package/dist/cli/commands/script-pack.js +5 -0
  4. package/dist/cli/i18n/en.js +101 -2
  5. package/dist/cli/i18n/es.js +101 -2
  6. package/dist/cli/i18n/fr.js +101 -2
  7. package/dist/cli/i18n/hi.js +101 -2
  8. package/dist/cli/i18n/ko.js +101 -2
  9. package/dist/cli/i18n/zh.js +101 -2
  10. package/dist/cli/lib/script-pack-registry.js +162 -7
  11. package/dist/cli/script-packs/code-export-diff.js +160 -0
  12. package/dist/cli/script-packs/code-outline.js +33 -5
  13. package/dist/cli/script-packs/code-route-outline.js +155 -0
  14. package/dist/cli/script-packs/docs-reference-drift.js +150 -0
  15. package/dist/cli/script-packs/repo-config-chain.js +163 -0
  16. package/dist/cli/script-packs/repo-related-files.js +161 -0
  17. package/dist/core/code-outline.js +527 -80
  18. package/dist/core/config-chain.js +595 -0
  19. package/dist/core/export-diff.js +359 -0
  20. package/dist/core/public-json-contracts.js +75 -0
  21. package/dist/core/reference-drift.js +388 -0
  22. package/dist/core/related-files.js +493 -0
  23. package/dist/core/route-outline.js +912 -0
  24. package/dist/core/script-pack-suggestions.js +111 -5
  25. package/dist/core/source-anchors.js +13 -1
  26. package/package.json +1 -1
  27. package/schemas/README.md +28 -5
  28. package/schemas/code-outline-report.schema.json +47 -1
  29. package/schemas/code-symbol-read-report.schema.json +64 -4
  30. package/schemas/config-chain-report.schema.json +187 -0
  31. package/schemas/export-diff-report.schema.json +220 -0
  32. package/schemas/reference-drift-report.schema.json +166 -0
  33. package/schemas/related-files-report.schema.json +145 -0
  34. package/schemas/route-outline-report.schema.json +200 -0
  35. package/templates/default/common/.mustflow/config/commands.toml +21 -0
  36. package/templates/default/i18n.toml +7 -1
  37. package/templates/default/locales/en/.mustflow/docs/agent-workflow.md +1 -1
  38. package/templates/default/locales/en/.mustflow/skills/INDEX.md +2 -1
  39. package/templates/default/locales/en/.mustflow/skills/cross-agent-session-reference/SKILL.md +131 -0
  40. package/templates/default/locales/en/.mustflow/skills/routes.toml +6 -0
  41. package/templates/default/manifest.toml +8 -1
@@ -1,5 +1,14 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import path from 'node:path';
3
+ const CODE_NAVIGATION_SCRIPT_REFS = new Set([
4
+ 'code/outline',
5
+ 'code/symbol-read',
6
+ 'code/route-outline',
7
+ 'code/export-diff',
8
+ 'repo/related-files',
9
+ ]);
10
+ const CONFIG_CHAIN_SURFACES = new Set(['config', 'package', 'source', 'test']);
11
+ const CONFIG_FILE_PATTERN = /(?:^|\/)(?:tsconfig(?:\..*)?\.json|eslint\.config\.[cm]?[jt]s|\.eslintrc(?:\.json)?|\.prettierrc(?:\.json)?|prettier\.config\.[cm]?[jt]s|vite\.config\.[cm]?[jt]s|vitest\.config\.[cm]?[jt]s|tailwind\.config\.[cm]?[jt]s|jest\.config\.[cm]?[jt]s|playwright\.config\.[cm]?[jt]s|astro\.config\.mjs|svelte\.config\.js)$/u;
3
12
  export function isScriptPackSuggestionPhase(value) {
4
13
  return ['before_change', 'during_change', 'after_change', 'review'].includes(value);
5
14
  }
@@ -12,6 +21,9 @@ function uniqueSortedPhases(values) {
12
21
  function uniqueSortedSurfaces(values) {
13
22
  return uniqueSortedStrings(values);
14
23
  }
24
+ function quoteCliArg(value) {
25
+ return /^[A-Za-z0-9_./:@=-]+$/u.test(value) ? value : JSON.stringify(value);
26
+ }
15
27
  function normalizeReportPath(mustflowRoot, value) {
16
28
  const absolute = path.resolve(mustflowRoot, value);
17
29
  const relative = path.relative(mustflowRoot, absolute);
@@ -31,7 +43,7 @@ export function classifyScriptPackPathSurface(relativePath) {
31
43
  normalized.startsWith('.mustflow/state/')) {
32
44
  surfaces.push('generated');
33
45
  }
34
- if (normalized.startsWith('.mustflow/config/') || normalized.startsWith('config/')) {
46
+ if (normalized.startsWith('.mustflow/config/') || normalized.startsWith('config/') || CONFIG_FILE_PATTERN.test(normalized)) {
35
47
  surfaces.push('config');
36
48
  }
37
49
  if (normalized.startsWith('.mustflow/skills/') || normalized.includes('/.mustflow/skills/')) {
@@ -59,7 +71,8 @@ export function classifyScriptPackPathSurface(relativePath) {
59
71
  normalized.startsWith('.github/workflows/')) {
60
72
  surfaces.push('package');
61
73
  }
62
- if (normalized.startsWith('src/') || normalized.endsWith('.ts') || normalized.endsWith('.tsx')) {
74
+ if (normalized.startsWith('src/') ||
75
+ /\.(?:astro|cjs|go|js|jsx|mjs|py|rs|svelte|ts|tsx)$/u.test(normalized)) {
63
76
  surfaces.push('source');
64
77
  }
65
78
  return surfaces.length > 0 ? uniqueSortedSurfaces(surfaces) : ['unknown'];
@@ -108,7 +121,7 @@ function surfacesForScript(script) {
108
121
  addIf('generated', /generated|protected|vendor|cache|boundary/u);
109
122
  addIf('config', /config|command/u);
110
123
  addIf('package', /package|release/u);
111
- addIf('source', /code|source|path/u);
124
+ addIf('source', /code|source|symbol/u);
112
125
  return uniqueSortedSurfaces(surfaces);
113
126
  }
114
127
  function confidenceForScore(score) {
@@ -120,14 +133,99 @@ function confidenceForScore(score) {
120
133
  }
121
134
  return 'low';
122
135
  }
136
+ function pathsWithSurface(analyzedPaths, surface) {
137
+ return analyzedPaths.filter((entry) => entry.surfaces.includes(surface)).map((entry) => entry.path);
138
+ }
139
+ function hasPathWithSurface(analyzedPaths, surface) {
140
+ return analyzedPaths.some((entry) => entry.surfaces.includes(surface));
141
+ }
142
+ function firstAvailablePath(analyzedPaths, preferredSurfaces) {
143
+ for (const surface of preferredSurfaces) {
144
+ const [candidate] = pathsWithSurface(analyzedPaths, surface);
145
+ if (candidate) {
146
+ return candidate;
147
+ }
148
+ }
149
+ return analyzedPaths[0]?.path ?? null;
150
+ }
151
+ function createConcretePathHint(commandPrefix, paths, fallbackUsage) {
152
+ if (paths.length === 0) {
153
+ return fallbackUsage;
154
+ }
155
+ return `${commandPrefix} ${paths.map(quoteCliArg).join(' ')} --json`;
156
+ }
157
+ function createRunHint(script, analyzedPaths) {
158
+ if (script.ref === 'code/outline') {
159
+ const sourcePaths = pathsWithSurface(analyzedPaths, 'source');
160
+ return createConcretePathHint('mf script-pack run code/outline scan', sourcePaths, script.usage);
161
+ }
162
+ if (script.ref === 'code/symbol-read') {
163
+ const sourcePath = firstAvailablePath(analyzedPaths, ['source']);
164
+ if (sourcePath) {
165
+ return `After code/outline returns a symbol line or anchor, run: mf script-pack run code/symbol-read read ${quoteCliArg(sourcePath)} --start-line <line> --json`;
166
+ }
167
+ return 'After code/outline returns a source anchor, run: mf script-pack run code/symbol-read read --anchor <anchor-id> --json';
168
+ }
169
+ if (script.ref === 'code/route-outline') {
170
+ const sourcePaths = pathsWithSurface(analyzedPaths, 'source');
171
+ return createConcretePathHint('mf script-pack run code/route-outline scan', sourcePaths, script.usage);
172
+ }
173
+ if (script.ref === 'code/export-diff') {
174
+ const sourcePaths = pathsWithSurface(analyzedPaths, 'source');
175
+ const pathPart = sourcePaths.length > 0 ? ` ${sourcePaths.map(quoteCliArg).join(' ')}` : '';
176
+ return `mf script-pack run code/export-diff compare${pathPart} --base HEAD --json`;
177
+ }
178
+ if (script.ref === 'core/text-budget') {
179
+ const packageJson = analyzedPaths.find((entry) => entry.path === 'package.json');
180
+ if (packageJson) {
181
+ return 'mf script-pack run core/text-budget check package.json --json-pointer /description --max 80 --json';
182
+ }
183
+ const textPaths = analyzedPaths
184
+ .filter((entry) => entry.surfaces.some((surface) => surface === 'docs' || surface === 'package' || surface === 'schema'))
185
+ .map((entry) => entry.path);
186
+ return createConcretePathHint('mf script-pack run core/text-budget check', textPaths, script.usage);
187
+ }
188
+ if (script.ref === 'docs/reference-drift') {
189
+ const docsPaths = analyzedPaths
190
+ .filter((entry) => entry.surfaces.some((surface) => surface === 'docs' || surface === 'schema' || surface === 'package'))
191
+ .map((entry) => entry.path);
192
+ return createConcretePathHint('mf script-pack run docs/reference-drift check', docsPaths, script.usage);
193
+ }
194
+ if (script.ref === 'repo/generated-boundary') {
195
+ return createConcretePathHint('mf script-pack run repo/generated-boundary check', analyzedPaths.map((entry) => entry.path), script.usage);
196
+ }
197
+ if (script.ref === 'repo/config-chain') {
198
+ const configPaths = analyzedPaths
199
+ .filter((entry) => entry.surfaces.some((surface) => CONFIG_CHAIN_SURFACES.has(surface)))
200
+ .map((entry) => entry.path);
201
+ return createConcretePathHint('mf script-pack run repo/config-chain inspect', configPaths, script.usage);
202
+ }
203
+ if (script.ref === 'repo/related-files') {
204
+ const relatedPaths = analyzedPaths
205
+ .filter((entry) => entry.surfaces.some((surface) => surface === 'source' || surface === 'test'))
206
+ .map((entry) => entry.path);
207
+ return createConcretePathHint('mf script-pack run repo/related-files map', relatedPaths, script.usage);
208
+ }
209
+ return script.usage;
210
+ }
123
211
  export function createScriptPackSuggestionReport(mustflowRoot, options) {
124
212
  const issues = [];
125
213
  const changedPaths = options.changed ? readChangedPaths(mustflowRoot, issues) : [];
126
214
  const inputPaths = uniqueSortedStrings([...options.paths, ...changedPaths].map((value) => normalizeReportPath(mustflowRoot, value)));
127
215
  const analyzedPaths = inputPaths.map((entry) => ({ path: entry, surfaces: classifyScriptPackPathSurface(entry) }));
128
216
  const requestedSurfaces = new Set(analyzedPaths.flatMap((entry) => entry.surfaces));
217
+ const hasSourcePath = hasPathWithSurface(analyzedPaths, 'source');
129
218
  const suggestions = options.scripts
130
219
  .map((script) => {
220
+ if (CODE_NAVIGATION_SCRIPT_REFS.has(script.ref) && inputPaths.length > 0 && !hasSourcePath) {
221
+ return null;
222
+ }
223
+ if (script.ref === 'repo/config-chain' && inputPaths.length > 0) {
224
+ const hasConfigChainSurface = analyzedPaths.some((entry) => entry.surfaces.some((surface) => CONFIG_CHAIN_SURFACES.has(surface)));
225
+ if (!hasConfigChainSurface) {
226
+ return null;
227
+ }
228
+ }
131
229
  let score = 0;
132
230
  const reasons = [];
133
231
  const matchedPhases = options.phases.filter((phase) => script.phases.includes(phase));
@@ -150,10 +248,18 @@ export function createScriptPackSuggestionReport(mustflowRoot, options) {
150
248
  score += 1;
151
249
  reasons.push('Accepts explicit path inputs.');
152
250
  }
153
- if (script.readOnly && !script.mutates && !script.network) {
251
+ if (script.ref === 'code/symbol-read' && inputPaths.length > 0) {
252
+ score = Math.max(1, score - 1);
253
+ reasons.push('Follow-up helper after code/outline identifies a symbol line or source anchor.');
254
+ }
255
+ if (score > 0 && script.readOnly && !script.mutates && !script.network) {
154
256
  score += 1;
155
257
  reasons.push('Read-only, non-mutating, offline helper.');
156
258
  }
259
+ if (script.ref === 'repo/generated-boundary' && requestedSurfaces.has('generated')) {
260
+ score += 2;
261
+ reasons.push('Prioritizes generated-boundary checks for generated paths.');
262
+ }
157
263
  if (score === 0) {
158
264
  return null;
159
265
  }
@@ -173,7 +279,7 @@ export function createScriptPackSuggestionReport(mustflowRoot, options) {
173
279
  risk_level: script.riskLevel,
174
280
  cost: script.cost,
175
281
  report_schema_file: script.reportSchemaFile,
176
- run_hint: script.usage,
282
+ run_hint: createRunHint(script, analyzedPaths),
177
283
  };
178
284
  })
179
285
  .filter((suggestion) => suggestion !== null)
@@ -1,7 +1,19 @@
1
1
  import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { SECRET_LIKE_PATTERNS, textContainsSecretLike } from './secret-redaction.js';
4
- export const SOURCE_ANCHOR_EXTENSIONS = new Set(['.cjs', '.go', '.js', '.jsx', '.mjs', '.py', '.rs', '.ts', '.tsx']);
4
+ export const SOURCE_ANCHOR_EXTENSIONS = new Set([
5
+ '.astro',
6
+ '.cjs',
7
+ '.go',
8
+ '.js',
9
+ '.jsx',
10
+ '.mjs',
11
+ '.py',
12
+ '.rs',
13
+ '.svelte',
14
+ '.ts',
15
+ '.tsx',
16
+ ]);
5
17
  export const SOURCE_ANCHOR_DEFAULT_EXCLUDED_PATH_PARTS = new Set([
6
18
  '.git',
7
19
  '.mustflow',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mustflow",
3
- "version": "2.75.1",
3
+ "version": "2.84.0",
4
4
  "description": "Agent workflow documents and CLI for mustflow repository roots.",
5
5
  "type": "module",
6
6
  "license": "MIT-0",
package/schemas/README.md CHANGED
@@ -65,13 +65,32 @@ Current schemas:
65
65
  - `script-pack-suggestion-report.schema.json`: output of `mf script-pack suggest --json`, containing
66
66
  path, skill, phase, and changed-file evidence used to recommend optional script-pack helpers
67
67
  - `code-outline-report.schema.json`: output of
68
- `mf script-pack run code/outline scan <path...> --json`, containing a bounded TypeScript and
69
- JavaScript source outline with file hashes, symbol names, declaration kinds, line ranges,
70
- signatures, export flags, static return metadata, and stable input-limit finding codes
68
+ `mf script-pack run code/outline scan <path...> --json`, containing a bounded source outline with
69
+ file hashes, language metadata, symbol names, declaration kinds, line ranges, signatures, export
70
+ flags, source-anchor navigation metadata, static return metadata, and stable input-limit finding
71
+ codes
71
72
  - `code-symbol-read-report.schema.json`: output of
72
73
  `mf script-pack run code/symbol-read read <path> --start-line <line> --json`, containing a
73
- focused source snippet selected by outline symbol line or explicit line range with file hash,
74
- resolved line metadata, optional symbol and static return metadata, and stable range/read finding codes
74
+ focused source snippet selected by source anchor, outline symbol line, or explicit line range with
75
+ file hash, resolved line metadata, optional anchor, symbol and static return metadata, and stable
76
+ range/read finding codes
77
+ - `route-outline-report.schema.json`: output of
78
+ `mf script-pack run code/route-outline scan <path...> --json`, containing a bounded Hono,
79
+ Elysia, Axum, and NestJS route outline with file hashes, framework evidence, route methods,
80
+ route paths, optional handler names, line ranges, lifecycle-chain metadata, and stable input-limit
81
+ finding codes
82
+ - `export-diff-report.schema.json`: output of
83
+ `mf script-pack run code/export-diff compare [path...] --json`, containing a bounded git-based
84
+ comparison of exported TypeScript and JavaScript declarations, signatures, return metadata,
85
+ package surface hints, and unresolved re-export findings
86
+ - `reference-drift-report.schema.json`: output of
87
+ `mf script-pack run docs/reference-drift check [path...] --json`, containing checked
88
+ documentation references to `mf` commands, script-pack refs, schema files, repository paths,
89
+ and stable stale-reference finding codes
90
+ - `config-chain-report.schema.json`: output of
91
+ `mf script-pack run repo/config-chain inspect <path...> --json`, containing nearby package,
92
+ TypeScript, ESLint, Prettier, Vite, Vitest, Tailwind, Jest, Playwright, and mustflow config files
93
+ with static inheritance, reference, workspace, dynamic-config, path, and content-hash metadata
75
94
  - `text-budget-report.schema.json`: output of
76
95
  `mf script-pack run core/text-budget check <path...> --json`, containing
77
96
  exact text-budget metrics, input content hashes, policy metadata, findings, and JSON Pointer field
@@ -79,6 +98,10 @@ Current schemas:
79
98
  - `generated-boundary-report.schema.json`: output of
80
99
  `mf script-pack run repo/generated-boundary check <path...> --json`, containing candidate path
81
100
  classifications for generated, ignored, protected, vendor, and cache boundaries before or after edits
101
+ - `related-files-report.schema.json`: output of
102
+ `mf script-pack run repo/related-files map <path...> --json`, containing conservative related-file
103
+ candidates from direct imports, importers, same-basename siblings, parent configuration files, and
104
+ package boundaries for source-oriented repository navigation
82
105
  - `skill-route-report.schema.json`: output of `mf skill route --json`, containing compact route
83
106
  candidates, selected main and adjunct skills, score breakdowns, route read plans, source route
84
107
  shards, and optional read-only script-pack helper suggestions without granting command authority
@@ -17,6 +17,7 @@
17
17
  "policy",
18
18
  "input_hash",
19
19
  "files",
20
+ "anchors",
20
21
  "symbols",
21
22
  "findings",
22
23
  "issues"
@@ -37,6 +38,10 @@
37
38
  "type": "array",
38
39
  "items": { "$ref": "#/$defs/file" }
39
40
  },
41
+ "anchors": {
42
+ "type": "array",
43
+ "items": { "$ref": "#/$defs/anchor" }
44
+ },
40
45
  "symbols": {
41
46
  "type": "array",
42
47
  "items": { "$ref": "#/$defs/symbol" }
@@ -56,7 +61,7 @@
56
61
  "pattern": "^sha256:[a-f0-9]{64}$"
57
62
  },
58
63
  "language": {
59
- "enum": ["typescript", "tsx", "javascript", "jsx", "javascript-module", "javascript-commonjs"]
64
+ "enum": ["typescript", "tsx", "javascript", "jsx", "javascript-module", "javascript-commonjs", "astro", "svelte", "go", "rust", "python"]
60
65
  },
61
66
  "symbolKind": {
62
67
  "enum": ["function", "class", "interface", "type", "enum", "variable"]
@@ -90,6 +95,47 @@
90
95
  "symbol_count": { "type": "integer", "minimum": 0 }
91
96
  }
92
97
  },
98
+ "anchor": {
99
+ "type": "object",
100
+ "additionalProperties": false,
101
+ "required": [
102
+ "id",
103
+ "path",
104
+ "line_start",
105
+ "line_end",
106
+ "purpose",
107
+ "search",
108
+ "invariant",
109
+ "risk",
110
+ "navigation_only",
111
+ "can_instruct_agent",
112
+ "target_symbol_id",
113
+ "target_kind",
114
+ "target_name",
115
+ "target_start_line"
116
+ ],
117
+ "properties": {
118
+ "id": { "type": "string" },
119
+ "path": { "type": "string" },
120
+ "line_start": { "type": "integer", "minimum": 1 },
121
+ "line_end": { "type": "integer", "minimum": 1 },
122
+ "purpose": { "type": ["string", "null"] },
123
+ "search": { "$ref": "#/$defs/stringArray" },
124
+ "invariant": { "type": ["string", "null"] },
125
+ "risk": { "$ref": "#/$defs/stringArray" },
126
+ "navigation_only": { "const": true },
127
+ "can_instruct_agent": { "const": false },
128
+ "target_symbol_id": { "type": ["string", "null"] },
129
+ "target_kind": {
130
+ "anyOf": [
131
+ { "$ref": "#/$defs/symbolKind" },
132
+ { "type": "null" }
133
+ ]
134
+ },
135
+ "target_name": { "type": ["string", "null"] },
136
+ "target_start_line": { "type": ["integer", "null"], "minimum": 1 }
137
+ }
138
+ },
93
139
  "symbol": {
94
140
  "type": "object",
95
141
  "additionalProperties": false,
@@ -60,7 +60,7 @@
60
60
  "pattern": "^sha256:[a-f0-9]{64}$"
61
61
  },
62
62
  "language": {
63
- "enum": ["typescript", "tsx", "javascript", "jsx", "javascript-module", "javascript-commonjs"]
63
+ "enum": ["typescript", "tsx", "javascript", "jsx", "javascript-module", "javascript-commonjs", "astro", "svelte", "go", "rust", "python"]
64
64
  },
65
65
  "symbolKind": {
66
66
  "enum": ["function", "class", "interface", "type", "enum", "variable"]
@@ -68,9 +68,10 @@
68
68
  "policy": {
69
69
  "type": "object",
70
70
  "additionalProperties": false,
71
- "required": ["start_line", "end_line", "context_lines", "max_file_bytes", "max_snippet_lines"],
71
+ "required": ["anchor_id", "start_line", "end_line", "context_lines", "max_file_bytes", "max_snippet_lines"],
72
72
  "properties": {
73
- "start_line": { "type": "integer", "minimum": 1 },
73
+ "anchor_id": { "type": ["string", "null"] },
74
+ "start_line": { "type": ["integer", "null"], "minimum": 1 },
74
75
  "end_line": { "type": ["integer", "null"], "minimum": 1 },
75
76
  "context_lines": { "type": "integer", "minimum": 0 },
76
77
  "max_file_bytes": { "type": "integer", "minimum": 1 },
@@ -124,6 +125,53 @@
124
125
  "content_sha256": { "$ref": "#/$defs/sha256" }
125
126
  }
126
127
  },
128
+ "anchor": {
129
+ "type": "object",
130
+ "additionalProperties": false,
131
+ "required": [
132
+ "id",
133
+ "path",
134
+ "line_start",
135
+ "line_end",
136
+ "purpose",
137
+ "search",
138
+ "invariant",
139
+ "risk",
140
+ "navigation_only",
141
+ "can_instruct_agent",
142
+ "target_symbol_id",
143
+ "target_kind",
144
+ "target_name",
145
+ "target_start_line"
146
+ ],
147
+ "properties": {
148
+ "id": { "type": "string" },
149
+ "path": { "type": "string" },
150
+ "line_start": { "type": "integer", "minimum": 1 },
151
+ "line_end": { "type": "integer", "minimum": 1 },
152
+ "purpose": { "type": ["string", "null"] },
153
+ "search": {
154
+ "type": "array",
155
+ "items": { "type": "string" }
156
+ },
157
+ "invariant": { "type": ["string", "null"] },
158
+ "risk": {
159
+ "type": "array",
160
+ "items": { "type": "string" }
161
+ },
162
+ "navigation_only": { "const": true },
163
+ "can_instruct_agent": { "const": false },
164
+ "target_symbol_id": { "type": ["string", "null"] },
165
+ "target_kind": {
166
+ "anyOf": [
167
+ { "$ref": "#/$defs/symbolKind" },
168
+ { "type": "null" }
169
+ ]
170
+ },
171
+ "target_name": { "type": ["string", "null"] },
172
+ "target_start_line": { "type": ["integer", "null"], "minimum": 1 }
173
+ }
174
+ },
127
175
  "target": {
128
176
  "type": "object",
129
177
  "additionalProperties": false,
@@ -133,12 +181,14 @@
133
181
  "sha256",
134
182
  "size_bytes",
135
183
  "line_count",
184
+ "requested_anchor_id",
136
185
  "requested_start_line",
137
186
  "requested_end_line",
138
187
  "resolved_start_line",
139
188
  "resolved_end_line",
140
189
  "context_start_line",
141
190
  "context_end_line",
191
+ "anchor",
142
192
  "symbol"
143
193
  ],
144
194
  "properties": {
@@ -147,12 +197,19 @@
147
197
  "sha256": { "$ref": "#/$defs/sha256" },
148
198
  "size_bytes": { "type": "integer", "minimum": 0 },
149
199
  "line_count": { "type": "integer", "minimum": 0 },
150
- "requested_start_line": { "type": "integer", "minimum": 1 },
200
+ "requested_anchor_id": { "type": ["string", "null"] },
201
+ "requested_start_line": { "type": ["integer", "null"], "minimum": 1 },
151
202
  "requested_end_line": { "type": ["integer", "null"], "minimum": 1 },
152
203
  "resolved_start_line": { "type": ["integer", "null"], "minimum": 1 },
153
204
  "resolved_end_line": { "type": ["integer", "null"], "minimum": 1 },
154
205
  "context_start_line": { "type": ["integer", "null"], "minimum": 1 },
155
206
  "context_end_line": { "type": ["integer", "null"], "minimum": 1 },
207
+ "anchor": {
208
+ "anyOf": [
209
+ { "$ref": "#/$defs/anchor" },
210
+ { "type": "null" }
211
+ ]
212
+ },
156
213
  "symbol": {
157
214
  "anyOf": [
158
215
  { "$ref": "#/$defs/symbol" },
@@ -183,6 +240,9 @@
183
240
  "code_symbol_read_unreadable_path",
184
241
  "code_symbol_read_invalid_range",
185
242
  "code_symbol_read_no_symbol_at_line",
243
+ "code_symbol_read_anchor_not_found",
244
+ "code_symbol_read_anchor_ambiguous",
245
+ "code_symbol_read_anchor_without_symbol",
186
246
  "code_symbol_read_snippet_too_large"
187
247
  ]
188
248
  },
@@ -0,0 +1,187 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://mustflow.github.io/schemas/config-chain-report.schema.json",
4
+ "title": "mustflow config-chain report",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schema_version",
9
+ "command",
10
+ "pack_id",
11
+ "script_id",
12
+ "script_ref",
13
+ "action",
14
+ "status",
15
+ "ok",
16
+ "mustflow_root",
17
+ "policy",
18
+ "input_hash",
19
+ "targets",
20
+ "configs",
21
+ "edges",
22
+ "findings",
23
+ "issues"
24
+ ],
25
+ "properties": {
26
+ "schema_version": { "const": "1" },
27
+ "command": { "const": "script-pack" },
28
+ "pack_id": { "const": "repo" },
29
+ "script_id": { "const": "config-chain" },
30
+ "script_ref": { "const": "repo/config-chain" },
31
+ "action": { "const": "inspect" },
32
+ "status": { "enum": ["passed", "failed", "error"] },
33
+ "ok": { "type": "boolean" },
34
+ "mustflow_root": { "type": "string" },
35
+ "policy": { "$ref": "#/$defs/policy" },
36
+ "input_hash": { "$ref": "#/$defs/sha256" },
37
+ "targets": {
38
+ "type": "array",
39
+ "items": { "$ref": "#/$defs/target" }
40
+ },
41
+ "configs": {
42
+ "type": "array",
43
+ "items": { "$ref": "#/$defs/config" }
44
+ },
45
+ "edges": {
46
+ "type": "array",
47
+ "items": { "$ref": "#/$defs/edge" }
48
+ },
49
+ "findings": {
50
+ "type": "array",
51
+ "items": { "$ref": "#/$defs/finding" }
52
+ },
53
+ "issues": {
54
+ "type": "array",
55
+ "items": { "type": "string" }
56
+ }
57
+ },
58
+ "$defs": {
59
+ "sha256": {
60
+ "type": "string",
61
+ "pattern": "^sha256:[a-f0-9]{64}$"
62
+ },
63
+ "nullableSha256": {
64
+ "type": ["string", "null"],
65
+ "pattern": "^sha256:[a-f0-9]{64}$"
66
+ },
67
+ "stringArray": {
68
+ "type": "array",
69
+ "items": { "type": "string" }
70
+ },
71
+ "policy": {
72
+ "type": "object",
73
+ "additionalProperties": false,
74
+ "required": ["max_file_bytes", "max_configs", "config_names", "ignored_directories"],
75
+ "properties": {
76
+ "max_file_bytes": { "type": "integer", "minimum": 1 },
77
+ "max_configs": { "type": "integer", "minimum": 1 },
78
+ "config_names": { "$ref": "#/$defs/stringArray" },
79
+ "ignored_directories": { "$ref": "#/$defs/stringArray" }
80
+ }
81
+ },
82
+ "target": {
83
+ "type": "object",
84
+ "additionalProperties": false,
85
+ "required": ["input", "path", "exists", "kind"],
86
+ "properties": {
87
+ "input": { "type": "string" },
88
+ "path": { "type": "string" },
89
+ "exists": { "type": ["boolean", "null"] },
90
+ "kind": { "enum": ["file", "directory", "missing", "other", "unknown"] }
91
+ }
92
+ },
93
+ "kind": {
94
+ "enum": [
95
+ "package_json",
96
+ "tsconfig",
97
+ "eslint",
98
+ "prettier",
99
+ "vite",
100
+ "vitest",
101
+ "tailwind",
102
+ "jest",
103
+ "playwright",
104
+ "mustflow",
105
+ "other"
106
+ ]
107
+ },
108
+ "format": {
109
+ "enum": ["json", "jsonc", "javascript", "typescript", "yaml", "toml", "unknown"]
110
+ },
111
+ "config": {
112
+ "type": "object",
113
+ "additionalProperties": false,
114
+ "required": [
115
+ "path",
116
+ "kind",
117
+ "format",
118
+ "source",
119
+ "sha256",
120
+ "size_bytes",
121
+ "parseable",
122
+ "dynamic",
123
+ "package_name",
124
+ "workspaces",
125
+ "scripts",
126
+ "extends",
127
+ "references",
128
+ "include",
129
+ "exclude",
130
+ "compiler_options",
131
+ "summary"
132
+ ],
133
+ "properties": {
134
+ "path": { "type": "string" },
135
+ "kind": { "$ref": "#/$defs/kind" },
136
+ "format": { "$ref": "#/$defs/format" },
137
+ "source": { "enum": ["target", "parent", "discovered"] },
138
+ "sha256": { "$ref": "#/$defs/nullableSha256" },
139
+ "size_bytes": { "type": ["integer", "null"], "minimum": 0 },
140
+ "parseable": { "type": "boolean" },
141
+ "dynamic": { "type": "boolean" },
142
+ "package_name": { "type": ["string", "null"] },
143
+ "workspaces": { "$ref": "#/$defs/stringArray" },
144
+ "scripts": { "$ref": "#/$defs/stringArray" },
145
+ "extends": { "$ref": "#/$defs/stringArray" },
146
+ "references": { "$ref": "#/$defs/stringArray" },
147
+ "include": { "$ref": "#/$defs/stringArray" },
148
+ "exclude": { "$ref": "#/$defs/stringArray" },
149
+ "compiler_options": { "$ref": "#/$defs/stringArray" },
150
+ "summary": { "$ref": "#/$defs/stringArray" }
151
+ }
152
+ },
153
+ "edge": {
154
+ "type": "object",
155
+ "additionalProperties": false,
156
+ "required": ["from_path", "to_path", "kind", "specifier", "resolved"],
157
+ "properties": {
158
+ "from_path": { "type": "string" },
159
+ "to_path": { "type": ["string", "null"] },
160
+ "kind": { "enum": ["parent_config", "extends", "reference", "workspace"] },
161
+ "specifier": { "type": "string" },
162
+ "resolved": { "type": "boolean" }
163
+ }
164
+ },
165
+ "finding": {
166
+ "type": "object",
167
+ "additionalProperties": false,
168
+ "required": ["code", "severity", "message", "path"],
169
+ "properties": {
170
+ "code": {
171
+ "enum": [
172
+ "config_chain_path_outside_root",
173
+ "config_chain_unreadable_path",
174
+ "config_chain_parse_error",
175
+ "config_chain_dynamic_config",
176
+ "config_chain_external_reference",
177
+ "config_chain_missing_reference",
178
+ "config_chain_max_configs_exceeded"
179
+ ]
180
+ },
181
+ "severity": { "enum": ["low", "medium", "high", "critical"] },
182
+ "message": { "type": "string" },
183
+ "path": { "type": "string" }
184
+ }
185
+ }
186
+ }
187
+ }