@ontrails/trails 1.0.0-beta.45 → 1.0.0-beta.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/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/package.json +16 -16
- package/src/cli.ts +13 -0
- package/src/regrade/audit.ts +122 -33
- package/src/regrade/history.ts +423 -425
- package/src/regrade/lifecycle.ts +76 -0
- package/src/regrade/plan-artifact.ts +0 -3
- package/src/regrade/prepared-run.ts +259 -0
- package/src/regrade/receipt-history.ts +445 -0
- package/src/regrade/source-transaction.ts +121 -11
- package/src/run-regrade-progress.ts +47 -0
- package/src/trails/create-scaffold.ts +1 -0
- package/src/trails/regrade.ts +965 -236
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# trails
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.47
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`90d394c`](https://github.com/outfitter-dev/trails/commit/90d394c005fdf6b898ba7052d0b56755af0f4954): Derive nested worktree, repository, and submodule collection boundaries in the
|
|
8
|
+
shared Source walker. Regrade and Warden now observe one directly targeted
|
|
9
|
+
working tree per run, and Regrade audit summaries expose boundary skip counts.
|
|
10
|
+
|
|
11
|
+
## 1.0.0-beta.46
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [`701ab85`](https://github.com/outfitter-dev/trails/commit/701ab85bd237e5fcf03725c56b70adb3612d6c15): Reuse fresh Regrade apply preflight evaluations without persisting cache state or weakening completion scans.
|
|
16
|
+
- [`c83d0b6`](https://github.com/outfitter-dev/trails/commit/c83d0b67ac928af1b44c1f2d2c4b36aa09a24a70): Inventory parser-native source comments and TSDoc as exact review-only entries
|
|
17
|
+
for governed classified vocabulary transitions across CLI, MCP, and audit.
|
|
18
|
+
- [`93757ba`](https://github.com/outfitter-dev/trails/commit/93757ba102ae7ba8d9a7a6c17f119cda47d342a7): Expose ordered Regrade lifecycle phases and wall-clock timings across CLI and
|
|
19
|
+
MCP completion results, with concise human CLI progress isolated on stderr.
|
|
20
|
+
Keep topo-scoped JSON and JSONL environment selectors effective when the
|
|
21
|
+
operator does not explicitly choose an output mode.
|
|
22
|
+
- [`fb0ba0a`](https://github.com/outfitter-dev/trails/commit/fb0ba0ab706bbdce470123e9a6fb2ef9f1822806): Convert the eight committed governed Regrade histories to canonical v3 receipts and remove the temporary schema-v2 compatibility path after migration.
|
|
23
|
+
- [`9a8b6e4`](https://github.com/outfitter-dev/trails/commit/9a8b6e4af394c76c11e6d0007e0f5f94d0be2cb3): Persist Regrade lifecycle runs as canonical v3 receipts with exact Git blob evidence and authored field provenance, and validate their compact classified-form projection independently in Warden.
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- [`768cc79`](https://github.com/outfitter-dev/trails/commit/768cc79ca10947b8808b376e281e1a81131b4acc): Close missed projection vocabulary residue in Regrade internals and public
|
|
28
|
+
error-rendering guidance, and keep lifecycle-ambiguous governed identifiers in
|
|
29
|
+
the Warden review inventory instead of assigning them an unsafe automatic
|
|
30
|
+
target.
|
|
31
|
+
|
|
3
32
|
## 1.0.0-beta.45
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Common workflows:
|
|
|
18
18
|
- `trails wayfind`, `trails wayfind --trails --intent read`, `trails wayfind <id> --contract`, `trails wayfind <id> --deps`, `trails wayfind <id> --impact`, `trails wayfind pattern "wayfind.*"`, `trails wayfind query "release drift"`, and `trails wayfind diff ...` read graph artifacts through Wayfinder. `trails wayfind file <file> --outline` is the operator-owned live-source exception, assembled with `@ontrails/source` and enriched with saved graph context when available.
|
|
19
19
|
- `trails schema <command...>` shows accepted CLI routes, aliases, flags, and schemas for an operator command or command namespace.
|
|
20
20
|
- `trails warden` runs Trails governance checks for contract and architecture drift. Use `--scope-exclude <glob>` or project `warden.scope.exclude` config when local notes, scratch space, or generated state should not be governed by Warden.
|
|
21
|
-
- `trails regrade plan <from> <to> --root-dir <path> --json` writes an active Regrade plan, `trails regrade plan --expand` stages wide-net review candidates in that plan, `trails regrade preview` reruns it without writing, and `trails regrade apply` consumes the plan and writes history. The minimal `from`/`to` seed is the primary workflow: planning deterministically derives morphology proposals, source-observed naming and public-identifier review candidates, review-only filename moves with reference-closure evidence, a namespace census, and current live-topo API preserves into the artifact's `derivation` section. Each derived item records provenance; uncertain forms and file moves remain review inventory until explicitly authored into the plan. A malformed or incompatible `trails.lock` fails planning instead of silently dropping live-API preserves. Use `plan --expand --dry-run` to inspect additional observed candidates without writing the active plan, and add `--dry-run` to `apply` to prove the apply path without mutating source. Use `trails regrade plans` and `trails regrade check` when a workspace has active plans that need inspection before apply. MCP
|
|
21
|
+
- `trails regrade plan <from> <to> --root-dir <path> --json` writes an active Regrade plan, `trails regrade plan --expand` stages wide-net review candidates in that plan, `trails regrade preview` reruns it without writing, and `trails regrade apply` consumes the plan and writes history. The minimal `from`/`to` seed is the primary workflow: planning deterministically derives morphology proposals, source-observed naming and public-identifier review candidates, review-only filename moves with reference-closure evidence, a namespace census, and current live-topo API preserves into the artifact's `derivation` section. Each derived item records provenance; uncertain forms and file moves remain review inventory until explicitly authored into the plan. A malformed or incompatible `trails.lock` fails planning instead of silently dropping live-API preserves. Use `plan --expand --dry-run` to inspect additional observed candidates without writing the active plan, and add `--dry-run` to `apply` to prove the apply path without mutating source. Use `trails regrade plans` and `trails regrade check` when a workspace has active plans that need inspection before apply. Human CLI runs stream concise phase progress to stderr; `--json` and `--jsonl` keep that channel quiet while returning phase names and timings in the structured result. MCP returns the same lifecycle facts from `trails_plan_regrade`, `trails_check_regrade`, `trails_preview_regrade`, `trails_apply_regrade`, and `trails_adjust_regrade` and forwards progress notifications when the caller supplies a progress token. Lifecycle timings describe the command invocation and are never persisted into plans or history receipts. Apply reuses its command-local preflight evaluation only when exact source bytes plus plan, policy, scope, lock, and tool identities still match. Any stale or unreadable fact fails closed; no prepared handle is written to disk or required for receipt regeneration, and the post-apply completion scan still runs independently.
|
|
22
22
|
- `trails guide` remains available for compatibility; prefer `trails wayfind --source live --module <app-module>` or saved-artifact Wayfinder reads for agent navigation.
|
|
23
23
|
|
|
24
24
|
Trails is contract-first: define trails once with typed input, Result output, examples, and meta; the framework derives CLI, MCP, HTTP, and future surfaces from the same contracts.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/trails",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.47",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/outfitter-dev/trails.git",
|
|
@@ -32,25 +32,25 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@clack/prompts": "^1.1.0",
|
|
35
|
-
"@ontrails/adapter-kit": "^1.0.0-beta.
|
|
36
|
-
"@ontrails/cli": "^1.0.0-beta.
|
|
37
|
-
"@ontrails/commander": "^1.0.0-beta.
|
|
38
|
-
"@ontrails/config": "^1.0.0-beta.
|
|
39
|
-
"@ontrails/core": "^1.0.0-beta.
|
|
40
|
-
"@ontrails/http": "^1.0.0-beta.
|
|
41
|
-
"@ontrails/mcp": "^1.0.0-beta.
|
|
42
|
-
"@ontrails/observability": "^1.0.0-beta.
|
|
43
|
-
"@ontrails/permits": "^1.0.0-beta.
|
|
44
|
-
"@ontrails/regrade": "^1.0.0-beta.
|
|
45
|
-
"@ontrails/source": "^1.0.0-beta.
|
|
46
|
-
"@ontrails/topography": "^1.0.0-beta.
|
|
47
|
-
"@ontrails/warden": "^1.0.0-beta.
|
|
35
|
+
"@ontrails/adapter-kit": "^1.0.0-beta.47",
|
|
36
|
+
"@ontrails/cli": "^1.0.0-beta.47",
|
|
37
|
+
"@ontrails/commander": "^1.0.0-beta.47",
|
|
38
|
+
"@ontrails/config": "^1.0.0-beta.47",
|
|
39
|
+
"@ontrails/core": "^1.0.0-beta.47",
|
|
40
|
+
"@ontrails/http": "^1.0.0-beta.47",
|
|
41
|
+
"@ontrails/mcp": "^1.0.0-beta.47",
|
|
42
|
+
"@ontrails/observability": "^1.0.0-beta.47",
|
|
43
|
+
"@ontrails/permits": "^1.0.0-beta.47",
|
|
44
|
+
"@ontrails/regrade": "^1.0.0-beta.47",
|
|
45
|
+
"@ontrails/source": "^1.0.0-beta.47",
|
|
46
|
+
"@ontrails/topography": "^1.0.0-beta.47",
|
|
47
|
+
"@ontrails/warden": "^1.0.0-beta.47",
|
|
48
48
|
"commander": "^14.0.3",
|
|
49
49
|
"typescript": "^5.9.3",
|
|
50
50
|
"zod": "^4.3.5"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@ontrails/cloudflare": "^1.0.0-beta.
|
|
54
|
-
"@ontrails/testing": "^1.0.0-beta.
|
|
53
|
+
"@ontrails/cloudflare": "^1.0.0-beta.47",
|
|
54
|
+
"@ontrails/testing": "^1.0.0-beta.47"
|
|
55
55
|
}
|
|
56
56
|
}
|
package/src/cli.ts
CHANGED
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
} from '@ontrails/cli';
|
|
19
19
|
import { createProgram } from '@ontrails/commander';
|
|
20
20
|
import type { CreateProgramOptions } from '@ontrails/commander';
|
|
21
|
+
import { createTrailContext } from '@ontrails/core';
|
|
21
22
|
import { resolvePermitFromBearerToken } from '@ontrails/permits';
|
|
22
23
|
import { deriveTopoGraph } from '@ontrails/topography';
|
|
23
24
|
|
|
@@ -25,6 +26,7 @@ import { app, trailsCliIncludedTrails, trailsOverlays } from './app.js';
|
|
|
25
26
|
import { resolveInputWithClack } from './clack.js';
|
|
26
27
|
import { getRetiredTopoCommandDiagnostic } from './retired-topo-command.js';
|
|
27
28
|
import { attachCompletionsInstallCommand } from './run-completions-install.js';
|
|
29
|
+
import { usesStructuredCliOutput } from './run-regrade-progress.js';
|
|
28
30
|
import { attachSchemaCommand } from './run-schema.js';
|
|
29
31
|
import {
|
|
30
32
|
applyAdapterCheckExitCode,
|
|
@@ -302,6 +304,17 @@ const runSurfaceOnce = async (): Promise<void> => {
|
|
|
302
304
|
const session = maybeInstallTraceSession();
|
|
303
305
|
try {
|
|
304
306
|
const surfaceOptions = {
|
|
307
|
+
createContext: () =>
|
|
308
|
+
createTrailContext({
|
|
309
|
+
progress: (event) => {
|
|
310
|
+
if (
|
|
311
|
+
!usesStructuredCliOutput(process.argv, process.env) &&
|
|
312
|
+
event.message?.startsWith('Regrade:') === true
|
|
313
|
+
) {
|
|
314
|
+
process.stderr.write(`${event.message}\n`);
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
}),
|
|
305
318
|
description: 'Agent-native, contract-first TypeScript framework',
|
|
306
319
|
include: trailsCliIncludedTrails,
|
|
307
320
|
name: 'trails',
|
package/src/regrade/audit.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
runVocabularyRegrade,
|
|
14
14
|
vocabularyDispositionValues,
|
|
15
15
|
vocabularyRegradePlanForInput,
|
|
16
|
+
vocabularyRegradeTransitionForInput,
|
|
16
17
|
} from '@ontrails/regrade';
|
|
17
18
|
import type { VocabularyRegradePlan } from '@ontrails/regrade';
|
|
18
19
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
@@ -21,9 +22,21 @@ import { z } from 'zod';
|
|
|
21
22
|
|
|
22
23
|
import { deriveLiveApiPreserveInventory } from './live-api-preserve.js';
|
|
23
24
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} from './
|
|
25
|
+
readRegradeHistoryArtifact,
|
|
26
|
+
regradeHistoryPathForPlan,
|
|
27
|
+
} from './history.js';
|
|
28
|
+
import { rootRelativePath } from './plan-artifact.js';
|
|
29
|
+
|
|
30
|
+
const sourceCommentExtensions = [
|
|
31
|
+
'.cjs',
|
|
32
|
+
'.cts',
|
|
33
|
+
'.js',
|
|
34
|
+
'.jsx',
|
|
35
|
+
'.mjs',
|
|
36
|
+
'.mts',
|
|
37
|
+
'.ts',
|
|
38
|
+
'.tsx',
|
|
39
|
+
] as const;
|
|
27
40
|
|
|
28
41
|
export const regradeAuditInputSchema = z.object({
|
|
29
42
|
failOnOpen: z
|
|
@@ -49,7 +62,7 @@ const regradeAuditTransitionSchema = z.object({
|
|
|
49
62
|
z.enum(vocabularyDispositionValues),
|
|
50
63
|
z.number().int().nonnegative()
|
|
51
64
|
)
|
|
52
|
-
.describe('Current
|
|
65
|
+
.describe('Current source occurrence counts by classification'),
|
|
53
66
|
entries: regradeReportOutput.shape.entries
|
|
54
67
|
.readonly()
|
|
55
68
|
.describe('Actionable file-level residue details'),
|
|
@@ -57,13 +70,16 @@ const regradeAuditTransitionSchema = z.object({
|
|
|
57
70
|
.number()
|
|
58
71
|
.int()
|
|
59
72
|
.nonnegative()
|
|
60
|
-
.describe('Total classified
|
|
73
|
+
.describe('Total classified current-source occurrences'),
|
|
61
74
|
open: z
|
|
62
75
|
.number()
|
|
63
76
|
.int()
|
|
64
77
|
.nonnegative()
|
|
65
|
-
.describe('Unresolved
|
|
78
|
+
.describe('Unresolved current-source occurrences'),
|
|
66
79
|
scanned: z.number().int().nonnegative().describe('Files scanned'),
|
|
80
|
+
skippedByReason: z
|
|
81
|
+
.record(z.string(), z.number().int().nonnegative())
|
|
82
|
+
.describe('Collection skips grouped by machine-readable reason'),
|
|
67
83
|
status: z.enum(['green', 'open']).describe('Transition audit status'),
|
|
68
84
|
})
|
|
69
85
|
.describe('Concise current-tree audit of the latest applied plan'),
|
|
@@ -87,11 +103,6 @@ export const regradeAuditOutputSchema = z.object({
|
|
|
87
103
|
.describe('Applied vocabulary transitions audited against current source'),
|
|
88
104
|
});
|
|
89
105
|
|
|
90
|
-
const regradeAuditHistoryPlanSchema = z.object({
|
|
91
|
-
id: z.string().min(1),
|
|
92
|
-
runs: z.array(z.object({ plan: regradePlanArtifactSchema })).min(1),
|
|
93
|
-
});
|
|
94
|
-
|
|
95
106
|
export type RegradeAuditInput = z.output<typeof regradeAuditInputSchema>;
|
|
96
107
|
export type RegradeAuditOutput = z.output<typeof regradeAuditOutputSchema>;
|
|
97
108
|
|
|
@@ -101,18 +112,36 @@ interface RegradeAuditCandidate {
|
|
|
101
112
|
readonly transitionId: string;
|
|
102
113
|
}
|
|
103
114
|
|
|
104
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Read the governed transition id from legacy history or v3 embedded intent.
|
|
117
|
+
*
|
|
118
|
+
* @internal
|
|
119
|
+
*/
|
|
120
|
+
export const historyTransitionId = (
|
|
121
|
+
rawHistory: unknown
|
|
122
|
+
): string | undefined => {
|
|
105
123
|
if (!isPlainObject(rawHistory)) {
|
|
106
124
|
return undefined;
|
|
107
125
|
}
|
|
108
126
|
const { id, runs } = rawHistory;
|
|
109
|
-
const
|
|
127
|
+
const historyRuns = Array.isArray(runs) ? runs : [];
|
|
128
|
+
const latestRun = historyRuns.at(-1);
|
|
110
129
|
const planArtifact = isPlainObject(latestRun) ? latestRun['plan'] : undefined;
|
|
111
130
|
const plan = isPlainObject(planArtifact) ? planArtifact['plan'] : undefined;
|
|
112
131
|
const planId = isPlainObject(plan) ? plan['id'] : undefined;
|
|
113
132
|
if (typeof planId === 'string') {
|
|
114
133
|
return planId;
|
|
115
134
|
}
|
|
135
|
+
for (const run of historyRuns.toReversed()) {
|
|
136
|
+
const intent = isPlainObject(run) ? run['intent'] : undefined;
|
|
137
|
+
const intentPlan = isPlainObject(intent) ? intent['plan'] : undefined;
|
|
138
|
+
const intentPlanId = isPlainObject(intentPlan)
|
|
139
|
+
? intentPlan['id']
|
|
140
|
+
: undefined;
|
|
141
|
+
if (typeof intentPlanId === 'string') {
|
|
142
|
+
return intentPlanId;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
116
145
|
return typeof id === 'string' ? id : undefined;
|
|
117
146
|
};
|
|
118
147
|
|
|
@@ -125,7 +154,9 @@ const selectedHistoryFileNamesFor = (
|
|
|
125
154
|
? []
|
|
126
155
|
: [...selectedTransitionIds].flatMap((transitionId) => {
|
|
127
156
|
const plan = registryPlansById.get(transitionId);
|
|
128
|
-
return plan === undefined
|
|
157
|
+
return plan === undefined
|
|
158
|
+
? []
|
|
159
|
+
: [basename(regradeHistoryPathForPlan('.', plan))];
|
|
129
160
|
})
|
|
130
161
|
);
|
|
131
162
|
|
|
@@ -239,21 +270,17 @@ const readRegradeAuditCandidates = (
|
|
|
239
270
|
) {
|
|
240
271
|
continue;
|
|
241
272
|
}
|
|
242
|
-
const history =
|
|
243
|
-
if (
|
|
244
|
-
return
|
|
245
|
-
new ValidationError('Invalid Regrade history audit plan.', {
|
|
246
|
-
context: { historyFile, issues: history.error.issues },
|
|
247
|
-
})
|
|
248
|
-
);
|
|
273
|
+
const history = readRegradeHistoryArtifact(historyFile);
|
|
274
|
+
if (history.isErr()) {
|
|
275
|
+
return history;
|
|
249
276
|
}
|
|
250
|
-
const latestPlan = history.
|
|
277
|
+
const latestPlan = history.value.runs.at(-1)?.plan.plan as
|
|
251
278
|
| VocabularyRegradePlan
|
|
252
279
|
| undefined;
|
|
253
280
|
if (latestPlan?.kind !== 'vocabulary') {
|
|
254
281
|
continue;
|
|
255
282
|
}
|
|
256
|
-
const transitionId = latestPlan.id ?? history.
|
|
283
|
+
const transitionId = latestPlan.id ?? history.value.id;
|
|
257
284
|
if (
|
|
258
285
|
selectedTransitionIds !== null &&
|
|
259
286
|
!selectedTransitionIds.has(transitionId)
|
|
@@ -281,10 +308,35 @@ type VocabularyPolicyClassified = NonNullable<
|
|
|
281
308
|
NonNullable<VocabularyRegradePlan['scope']>['policyClassified']
|
|
282
309
|
>;
|
|
283
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Select full evidence for classified paths and comments elsewhere.
|
|
313
|
+
*
|
|
314
|
+
* @internal
|
|
315
|
+
*/
|
|
316
|
+
export const sourceKindForRegradeAuditPath = (
|
|
317
|
+
path: string,
|
|
318
|
+
policyClassified: VocabularyPolicyClassified | undefined
|
|
319
|
+
): 'all' | 'comments' => {
|
|
320
|
+
const isPolicyClassified = policyClassified?.some((policy) =>
|
|
321
|
+
matchesAnyPathGlob(path, policy.paths)
|
|
322
|
+
);
|
|
323
|
+
return sourceCommentExtensions.includes(
|
|
324
|
+
extname(path) as (typeof sourceCommentExtensions)[number]
|
|
325
|
+
) && !isPolicyClassified
|
|
326
|
+
? 'comments'
|
|
327
|
+
: 'all';
|
|
328
|
+
};
|
|
329
|
+
|
|
284
330
|
export const projectPolicyClassifiedForMarkdownAudit = (
|
|
285
|
-
plan: VocabularyRegradePlan
|
|
286
|
-
|
|
287
|
-
|
|
331
|
+
plan: VocabularyRegradePlan,
|
|
332
|
+
includeCodeComments = false
|
|
333
|
+
): VocabularyPolicyClassified | undefined => {
|
|
334
|
+
const auditedExtensions = new Set<string>([
|
|
335
|
+
'.md',
|
|
336
|
+
'.mdx',
|
|
337
|
+
...(includeCodeComments ? sourceCommentExtensions : []),
|
|
338
|
+
]);
|
|
339
|
+
return plan.scope?.policyClassified
|
|
288
340
|
?.map((policy) => ({
|
|
289
341
|
...policy,
|
|
290
342
|
paths: policy.paths.filter(
|
|
@@ -297,18 +349,40 @@ export const projectPolicyClassifiedForMarkdownAudit = (
|
|
|
297
349
|
}))
|
|
298
350
|
.filter((policy) => policy.paths.length > 0)
|
|
299
351
|
.map((policy) => {
|
|
300
|
-
const
|
|
352
|
+
const hasAuditablePath = policy.paths.some((path) => {
|
|
301
353
|
const extension = extname(path);
|
|
302
|
-
|
|
354
|
+
if (auditedExtensions.has(extension)) {
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
const terminalPattern = basename(path);
|
|
358
|
+
const trailingWildcards = terminalPattern.match(/[*?]+$/)?.[0];
|
|
359
|
+
const canSelectAuditedExtension =
|
|
360
|
+
extension === '' &&
|
|
361
|
+
trailingWildcards !== undefined &&
|
|
362
|
+
[...auditedExtensions].some(
|
|
363
|
+
(auditedExtension) =>
|
|
364
|
+
trailingWildcards.includes('*') ||
|
|
365
|
+
(trailingWildcards.length >= auditedExtension.length &&
|
|
366
|
+
(terminalPattern.length > trailingWildcards.length ||
|
|
367
|
+
trailingWildcards.length > auditedExtension.length))
|
|
368
|
+
);
|
|
369
|
+
return (
|
|
370
|
+
includeCodeComments &&
|
|
371
|
+
(canSelectAuditedExtension ||
|
|
372
|
+
[...auditedExtensions].some((auditedExtension) =>
|
|
373
|
+
matchesAnyPathGlob(auditedExtension, [extension])
|
|
374
|
+
))
|
|
375
|
+
);
|
|
303
376
|
});
|
|
304
|
-
if (policy.expectMatches !== true ||
|
|
377
|
+
if (policy.expectMatches !== true || hasAuditablePath) {
|
|
305
378
|
return policy;
|
|
306
379
|
}
|
|
307
|
-
//
|
|
308
|
-
//
|
|
380
|
+
// An extension-filtered audit cannot prove evidence for a path whose
|
|
381
|
+
// authored pattern does not identify one of the audited file families.
|
|
309
382
|
const { expectMatches: _, ...markdownPolicy } = policy;
|
|
310
383
|
return markdownPolicy;
|
|
311
384
|
});
|
|
385
|
+
};
|
|
312
386
|
|
|
313
387
|
export const projectExcludesForMarkdownAudit = (
|
|
314
388
|
plan: VocabularyRegradePlan,
|
|
@@ -342,8 +416,12 @@ const runRegradeAuditCandidate = async (
|
|
|
342
416
|
input: RegradeAuditInput,
|
|
343
417
|
rootDir: string
|
|
344
418
|
): Promise<TrailsResult<RegradeAuditOutput['transitions'][number], Error>> => {
|
|
419
|
+
const includeCodeComments =
|
|
420
|
+
vocabularyRegradeTransitionForInput(candidate.plan.from, candidate.plan.to)
|
|
421
|
+
?.target.kind === 'classified';
|
|
345
422
|
const policyClassified = projectPolicyClassifiedForMarkdownAudit(
|
|
346
|
-
candidate.plan
|
|
423
|
+
candidate.plan,
|
|
424
|
+
includeCodeComments
|
|
347
425
|
);
|
|
348
426
|
const exclude = projectExcludesForMarkdownAudit(
|
|
349
427
|
candidate.plan,
|
|
@@ -357,7 +435,11 @@ const runRegradeAuditCandidate = async (
|
|
|
357
435
|
...candidate.plan,
|
|
358
436
|
scope: {
|
|
359
437
|
...candidate.plan.scope,
|
|
360
|
-
extensions: [
|
|
438
|
+
extensions: [
|
|
439
|
+
'.md',
|
|
440
|
+
'.mdx',
|
|
441
|
+
...(includeCodeComments ? sourceCommentExtensions : []),
|
|
442
|
+
],
|
|
361
443
|
...(exclude === undefined ? {} : { exclude }),
|
|
362
444
|
...(include === undefined ? {} : { include }),
|
|
363
445
|
...(policyClassified === undefined ? {} : { policyClassified }),
|
|
@@ -378,6 +460,12 @@ const runRegradeAuditCandidate = async (
|
|
|
378
460
|
? {}
|
|
379
461
|
: { preserveInventory: preserveResult.value }),
|
|
380
462
|
root: rootDir,
|
|
463
|
+
...(includeCodeComments
|
|
464
|
+
? {
|
|
465
|
+
sourceKindForPath: (path: string) =>
|
|
466
|
+
sourceKindForRegradeAuditPath(path, policyClassified),
|
|
467
|
+
}
|
|
468
|
+
: {}),
|
|
381
469
|
});
|
|
382
470
|
if (reportResult.isErr()) {
|
|
383
471
|
return reportResult;
|
|
@@ -404,6 +492,7 @@ const runRegradeAuditCandidate = async (
|
|
|
404
492
|
occurrences: run.ledger.occurrences.length,
|
|
405
493
|
open: run.report.open,
|
|
406
494
|
scanned: reportResult.value.scanned,
|
|
495
|
+
skippedByReason: reportResult.value.skipsByReason,
|
|
407
496
|
status: run.report.gate.status,
|
|
408
497
|
},
|
|
409
498
|
source: candidate.source,
|