@ontrails/trails 1.0.0-beta.43 → 1.0.0-beta.46
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 +36 -0
- package/README.md +1 -1
- package/package.json +21 -16
- package/src/cli.ts +13 -0
- package/src/regrade/audit.ts +118 -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/release/bindings.ts +22 -3
- package/src/release/index.ts +7 -0
- package/src/release/native-bun-publish.ts +403 -90
- package/src/release/native-bun-registry.ts +102 -37
- package/src/release/policy.ts +2 -2
- package/src/run-regrade-progress.ts +47 -0
- package/src/trails/create-scaffold.ts +1 -0
- package/src/trails/regrade.ts +966 -237
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# trails
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.46
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`701ab85`](https://github.com/outfitter-dev/trails/commit/701ab85bd237e5fcf03725c56b70adb3612d6c15): Reuse fresh Regrade apply preflight evaluations without persisting cache state or weakening completion scans.
|
|
8
|
+
- [`c83d0b6`](https://github.com/outfitter-dev/trails/commit/c83d0b67ac928af1b44c1f2d2c4b36aa09a24a70): Inventory parser-native source comments and TSDoc as exact review-only entries
|
|
9
|
+
for governed classified vocabulary transitions across CLI, MCP, and audit.
|
|
10
|
+
- [`93757ba`](https://github.com/outfitter-dev/trails/commit/93757ba102ae7ba8d9a7a6c17f119cda47d342a7): Expose ordered Regrade lifecycle phases and wall-clock timings across CLI and
|
|
11
|
+
MCP completion results, with concise human CLI progress isolated on stderr.
|
|
12
|
+
Keep topo-scoped JSON and JSONL environment selectors effective when the
|
|
13
|
+
operator does not explicitly choose an output mode.
|
|
14
|
+
- [`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.
|
|
15
|
+
- [`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.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [`768cc79`](https://github.com/outfitter-dev/trails/commit/768cc79ca10947b8808b376e281e1a81131b4acc): Close missed projection vocabulary residue in Regrade internals and public
|
|
20
|
+
error-rendering guidance, and keep lifecycle-ambiguous governed identifiers in
|
|
21
|
+
the Warden review inventory instead of assigning them an unsafe automatic
|
|
22
|
+
target.
|
|
23
|
+
|
|
24
|
+
## 1.0.0-beta.45
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- [`f1bd093`](https://github.com/outfitter-dev/trails/commit/f1bd09395fcf81db0bcb8657030288877c2e26e6): Recognize conditional, aliased, and parenthesized Result provenance while invalidating provenance after reassignment across the implementation-return and redundant-error-wrap rules.
|
|
29
|
+
- [`872a815`](https://github.com/outfitter-dev/trails/commit/872a815243cae63fae5b16022f102d125bc78ac5): Require strict registry checks to prove exact-version consumer availability instead of trusting package access or dist-tags alone.
|
|
30
|
+
|
|
31
|
+
## 1.0.0-beta.44
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- [`b1fbe57`](https://github.com/outfitter-dev/trails/commit/b1fbe574e6f44d1fecb5e3a000270955c0a77b7b): Publish Bun-validated package tarballs through an npm trusted-publishing adapter
|
|
36
|
+
binding, add exact repository metadata for each public workspace package, and
|
|
37
|
+
correct the native Bun release descriptor to its pack-only runtime boundary.
|
|
38
|
+
|
|
3
39
|
## 1.0.0-beta.43
|
|
4
40
|
|
|
5
41
|
### Minor 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,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/trails",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.46",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/outfitter-dev/trails.git",
|
|
7
|
+
"directory": "apps/trails"
|
|
8
|
+
},
|
|
4
9
|
"bin": {
|
|
5
10
|
"trails": "./bin/trails.ts"
|
|
6
11
|
},
|
|
@@ -27,25 +32,25 @@
|
|
|
27
32
|
},
|
|
28
33
|
"dependencies": {
|
|
29
34
|
"@clack/prompts": "^1.1.0",
|
|
30
|
-
"@ontrails/adapter-kit": "^1.0.0-beta.
|
|
31
|
-
"@ontrails/cli": "^1.0.0-beta.
|
|
32
|
-
"@ontrails/commander": "^1.0.0-beta.
|
|
33
|
-
"@ontrails/config": "^1.0.0-beta.
|
|
34
|
-
"@ontrails/core": "^1.0.0-beta.
|
|
35
|
-
"@ontrails/http": "^1.0.0-beta.
|
|
36
|
-
"@ontrails/mcp": "^1.0.0-beta.
|
|
37
|
-
"@ontrails/observability": "^1.0.0-beta.
|
|
38
|
-
"@ontrails/permits": "^1.0.0-beta.
|
|
39
|
-
"@ontrails/regrade": "^1.0.0-beta.
|
|
40
|
-
"@ontrails/source": "^1.0.0-beta.
|
|
41
|
-
"@ontrails/topography": "^1.0.0-beta.
|
|
42
|
-
"@ontrails/warden": "^1.0.0-beta.
|
|
35
|
+
"@ontrails/adapter-kit": "^1.0.0-beta.46",
|
|
36
|
+
"@ontrails/cli": "^1.0.0-beta.46",
|
|
37
|
+
"@ontrails/commander": "^1.0.0-beta.46",
|
|
38
|
+
"@ontrails/config": "^1.0.0-beta.46",
|
|
39
|
+
"@ontrails/core": "^1.0.0-beta.46",
|
|
40
|
+
"@ontrails/http": "^1.0.0-beta.46",
|
|
41
|
+
"@ontrails/mcp": "^1.0.0-beta.46",
|
|
42
|
+
"@ontrails/observability": "^1.0.0-beta.46",
|
|
43
|
+
"@ontrails/permits": "^1.0.0-beta.46",
|
|
44
|
+
"@ontrails/regrade": "^1.0.0-beta.46",
|
|
45
|
+
"@ontrails/source": "^1.0.0-beta.46",
|
|
46
|
+
"@ontrails/topography": "^1.0.0-beta.46",
|
|
47
|
+
"@ontrails/warden": "^1.0.0-beta.46",
|
|
43
48
|
"commander": "^14.0.3",
|
|
44
49
|
"typescript": "^5.9.3",
|
|
45
50
|
"zod": "^4.3.5"
|
|
46
51
|
},
|
|
47
52
|
"devDependencies": {
|
|
48
|
-
"@ontrails/cloudflare": "^1.0.0-beta.
|
|
49
|
-
"@ontrails/testing": "^1.0.0-beta.
|
|
53
|
+
"@ontrails/cloudflare": "^1.0.0-beta.46",
|
|
54
|
+
"@ontrails/testing": "^1.0.0-beta.46"
|
|
50
55
|
}
|
|
51
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,12 +70,12 @@ 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'),
|
|
67
80
|
status: z.enum(['green', 'open']).describe('Transition audit status'),
|
|
68
81
|
})
|
|
@@ -87,11 +100,6 @@ export const regradeAuditOutputSchema = z.object({
|
|
|
87
100
|
.describe('Applied vocabulary transitions audited against current source'),
|
|
88
101
|
});
|
|
89
102
|
|
|
90
|
-
const regradeAuditHistoryPlanSchema = z.object({
|
|
91
|
-
id: z.string().min(1),
|
|
92
|
-
runs: z.array(z.object({ plan: regradePlanArtifactSchema })).min(1),
|
|
93
|
-
});
|
|
94
|
-
|
|
95
103
|
export type RegradeAuditInput = z.output<typeof regradeAuditInputSchema>;
|
|
96
104
|
export type RegradeAuditOutput = z.output<typeof regradeAuditOutputSchema>;
|
|
97
105
|
|
|
@@ -101,18 +109,36 @@ interface RegradeAuditCandidate {
|
|
|
101
109
|
readonly transitionId: string;
|
|
102
110
|
}
|
|
103
111
|
|
|
104
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Read the governed transition id from legacy history or v3 embedded intent.
|
|
114
|
+
*
|
|
115
|
+
* @internal
|
|
116
|
+
*/
|
|
117
|
+
export const historyTransitionId = (
|
|
118
|
+
rawHistory: unknown
|
|
119
|
+
): string | undefined => {
|
|
105
120
|
if (!isPlainObject(rawHistory)) {
|
|
106
121
|
return undefined;
|
|
107
122
|
}
|
|
108
123
|
const { id, runs } = rawHistory;
|
|
109
|
-
const
|
|
124
|
+
const historyRuns = Array.isArray(runs) ? runs : [];
|
|
125
|
+
const latestRun = historyRuns.at(-1);
|
|
110
126
|
const planArtifact = isPlainObject(latestRun) ? latestRun['plan'] : undefined;
|
|
111
127
|
const plan = isPlainObject(planArtifact) ? planArtifact['plan'] : undefined;
|
|
112
128
|
const planId = isPlainObject(plan) ? plan['id'] : undefined;
|
|
113
129
|
if (typeof planId === 'string') {
|
|
114
130
|
return planId;
|
|
115
131
|
}
|
|
132
|
+
for (const run of historyRuns.toReversed()) {
|
|
133
|
+
const intent = isPlainObject(run) ? run['intent'] : undefined;
|
|
134
|
+
const intentPlan = isPlainObject(intent) ? intent['plan'] : undefined;
|
|
135
|
+
const intentPlanId = isPlainObject(intentPlan)
|
|
136
|
+
? intentPlan['id']
|
|
137
|
+
: undefined;
|
|
138
|
+
if (typeof intentPlanId === 'string') {
|
|
139
|
+
return intentPlanId;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
116
142
|
return typeof id === 'string' ? id : undefined;
|
|
117
143
|
};
|
|
118
144
|
|
|
@@ -125,7 +151,9 @@ const selectedHistoryFileNamesFor = (
|
|
|
125
151
|
? []
|
|
126
152
|
: [...selectedTransitionIds].flatMap((transitionId) => {
|
|
127
153
|
const plan = registryPlansById.get(transitionId);
|
|
128
|
-
return plan === undefined
|
|
154
|
+
return plan === undefined
|
|
155
|
+
? []
|
|
156
|
+
: [basename(regradeHistoryPathForPlan('.', plan))];
|
|
129
157
|
})
|
|
130
158
|
);
|
|
131
159
|
|
|
@@ -239,21 +267,17 @@ const readRegradeAuditCandidates = (
|
|
|
239
267
|
) {
|
|
240
268
|
continue;
|
|
241
269
|
}
|
|
242
|
-
const history =
|
|
243
|
-
if (
|
|
244
|
-
return
|
|
245
|
-
new ValidationError('Invalid Regrade history audit plan.', {
|
|
246
|
-
context: { historyFile, issues: history.error.issues },
|
|
247
|
-
})
|
|
248
|
-
);
|
|
270
|
+
const history = readRegradeHistoryArtifact(historyFile);
|
|
271
|
+
if (history.isErr()) {
|
|
272
|
+
return history;
|
|
249
273
|
}
|
|
250
|
-
const latestPlan = history.
|
|
274
|
+
const latestPlan = history.value.runs.at(-1)?.plan.plan as
|
|
251
275
|
| VocabularyRegradePlan
|
|
252
276
|
| undefined;
|
|
253
277
|
if (latestPlan?.kind !== 'vocabulary') {
|
|
254
278
|
continue;
|
|
255
279
|
}
|
|
256
|
-
const transitionId = latestPlan.id ?? history.
|
|
280
|
+
const transitionId = latestPlan.id ?? history.value.id;
|
|
257
281
|
if (
|
|
258
282
|
selectedTransitionIds !== null &&
|
|
259
283
|
!selectedTransitionIds.has(transitionId)
|
|
@@ -281,10 +305,35 @@ type VocabularyPolicyClassified = NonNullable<
|
|
|
281
305
|
NonNullable<VocabularyRegradePlan['scope']>['policyClassified']
|
|
282
306
|
>;
|
|
283
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Select full evidence for classified paths and comments elsewhere.
|
|
310
|
+
*
|
|
311
|
+
* @internal
|
|
312
|
+
*/
|
|
313
|
+
export const sourceKindForRegradeAuditPath = (
|
|
314
|
+
path: string,
|
|
315
|
+
policyClassified: VocabularyPolicyClassified | undefined
|
|
316
|
+
): 'all' | 'comments' => {
|
|
317
|
+
const isPolicyClassified = policyClassified?.some((policy) =>
|
|
318
|
+
matchesAnyPathGlob(path, policy.paths)
|
|
319
|
+
);
|
|
320
|
+
return sourceCommentExtensions.includes(
|
|
321
|
+
extname(path) as (typeof sourceCommentExtensions)[number]
|
|
322
|
+
) && !isPolicyClassified
|
|
323
|
+
? 'comments'
|
|
324
|
+
: 'all';
|
|
325
|
+
};
|
|
326
|
+
|
|
284
327
|
export const projectPolicyClassifiedForMarkdownAudit = (
|
|
285
|
-
plan: VocabularyRegradePlan
|
|
286
|
-
|
|
287
|
-
|
|
328
|
+
plan: VocabularyRegradePlan,
|
|
329
|
+
includeCodeComments = false
|
|
330
|
+
): VocabularyPolicyClassified | undefined => {
|
|
331
|
+
const auditedExtensions = new Set<string>([
|
|
332
|
+
'.md',
|
|
333
|
+
'.mdx',
|
|
334
|
+
...(includeCodeComments ? sourceCommentExtensions : []),
|
|
335
|
+
]);
|
|
336
|
+
return plan.scope?.policyClassified
|
|
288
337
|
?.map((policy) => ({
|
|
289
338
|
...policy,
|
|
290
339
|
paths: policy.paths.filter(
|
|
@@ -297,18 +346,40 @@ export const projectPolicyClassifiedForMarkdownAudit = (
|
|
|
297
346
|
}))
|
|
298
347
|
.filter((policy) => policy.paths.length > 0)
|
|
299
348
|
.map((policy) => {
|
|
300
|
-
const
|
|
349
|
+
const hasAuditablePath = policy.paths.some((path) => {
|
|
301
350
|
const extension = extname(path);
|
|
302
|
-
|
|
351
|
+
if (auditedExtensions.has(extension)) {
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
const terminalPattern = basename(path);
|
|
355
|
+
const trailingWildcards = terminalPattern.match(/[*?]+$/)?.[0];
|
|
356
|
+
const canSelectAuditedExtension =
|
|
357
|
+
extension === '' &&
|
|
358
|
+
trailingWildcards !== undefined &&
|
|
359
|
+
[...auditedExtensions].some(
|
|
360
|
+
(auditedExtension) =>
|
|
361
|
+
trailingWildcards.includes('*') ||
|
|
362
|
+
(trailingWildcards.length >= auditedExtension.length &&
|
|
363
|
+
(terminalPattern.length > trailingWildcards.length ||
|
|
364
|
+
trailingWildcards.length > auditedExtension.length))
|
|
365
|
+
);
|
|
366
|
+
return (
|
|
367
|
+
includeCodeComments &&
|
|
368
|
+
(canSelectAuditedExtension ||
|
|
369
|
+
[...auditedExtensions].some((auditedExtension) =>
|
|
370
|
+
matchesAnyPathGlob(auditedExtension, [extension])
|
|
371
|
+
))
|
|
372
|
+
);
|
|
303
373
|
});
|
|
304
|
-
if (policy.expectMatches !== true ||
|
|
374
|
+
if (policy.expectMatches !== true || hasAuditablePath) {
|
|
305
375
|
return policy;
|
|
306
376
|
}
|
|
307
|
-
//
|
|
308
|
-
//
|
|
377
|
+
// An extension-filtered audit cannot prove evidence for a path whose
|
|
378
|
+
// authored pattern does not identify one of the audited file families.
|
|
309
379
|
const { expectMatches: _, ...markdownPolicy } = policy;
|
|
310
380
|
return markdownPolicy;
|
|
311
381
|
});
|
|
382
|
+
};
|
|
312
383
|
|
|
313
384
|
export const projectExcludesForMarkdownAudit = (
|
|
314
385
|
plan: VocabularyRegradePlan,
|
|
@@ -342,8 +413,12 @@ const runRegradeAuditCandidate = async (
|
|
|
342
413
|
input: RegradeAuditInput,
|
|
343
414
|
rootDir: string
|
|
344
415
|
): Promise<TrailsResult<RegradeAuditOutput['transitions'][number], Error>> => {
|
|
416
|
+
const includeCodeComments =
|
|
417
|
+
vocabularyRegradeTransitionForInput(candidate.plan.from, candidate.plan.to)
|
|
418
|
+
?.target.kind === 'classified';
|
|
345
419
|
const policyClassified = projectPolicyClassifiedForMarkdownAudit(
|
|
346
|
-
candidate.plan
|
|
420
|
+
candidate.plan,
|
|
421
|
+
includeCodeComments
|
|
347
422
|
);
|
|
348
423
|
const exclude = projectExcludesForMarkdownAudit(
|
|
349
424
|
candidate.plan,
|
|
@@ -357,7 +432,11 @@ const runRegradeAuditCandidate = async (
|
|
|
357
432
|
...candidate.plan,
|
|
358
433
|
scope: {
|
|
359
434
|
...candidate.plan.scope,
|
|
360
|
-
extensions: [
|
|
435
|
+
extensions: [
|
|
436
|
+
'.md',
|
|
437
|
+
'.mdx',
|
|
438
|
+
...(includeCodeComments ? sourceCommentExtensions : []),
|
|
439
|
+
],
|
|
361
440
|
...(exclude === undefined ? {} : { exclude }),
|
|
362
441
|
...(include === undefined ? {} : { include }),
|
|
363
442
|
...(policyClassified === undefined ? {} : { policyClassified }),
|
|
@@ -378,6 +457,12 @@ const runRegradeAuditCandidate = async (
|
|
|
378
457
|
? {}
|
|
379
458
|
: { preserveInventory: preserveResult.value }),
|
|
380
459
|
root: rootDir,
|
|
460
|
+
...(includeCodeComments
|
|
461
|
+
? {
|
|
462
|
+
sourceKindForPath: (path: string) =>
|
|
463
|
+
sourceKindForRegradeAuditPath(path, policyClassified),
|
|
464
|
+
}
|
|
465
|
+
: {}),
|
|
381
466
|
});
|
|
382
467
|
if (reportResult.isErr()) {
|
|
383
468
|
return reportResult;
|