@ontrails/warden 1.0.0-beta.13 → 1.0.0-beta.14

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 (60) hide show
  1. package/.turbo/turbo-lint.log +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/README.md +12 -10
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +11 -3
  6. package/dist/cli.js.map +1 -1
  7. package/dist/draft.d.ts +5 -0
  8. package/dist/draft.d.ts.map +1 -0
  9. package/dist/draft.js +16 -0
  10. package/dist/draft.js.map +1 -0
  11. package/dist/drift.d.ts +9 -6
  12. package/dist/drift.d.ts.map +1 -1
  13. package/dist/drift.js +49 -15
  14. package/dist/drift.js.map +1 -1
  15. package/dist/formatters.d.ts +2 -1
  16. package/dist/formatters.d.ts.map +1 -1
  17. package/dist/formatters.js +15 -4
  18. package/dist/formatters.js.map +1 -1
  19. package/dist/index.d.ts +5 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +6 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/rules/ast.d.ts +7 -0
  24. package/dist/rules/ast.d.ts.map +1 -1
  25. package/dist/rules/ast.js +22 -0
  26. package/dist/rules/ast.js.map +1 -1
  27. package/dist/rules/draft-file-marking.d.ts +6 -0
  28. package/dist/rules/draft-file-marking.d.ts.map +1 -0
  29. package/dist/rules/draft-file-marking.js +65 -0
  30. package/dist/rules/draft-file-marking.js.map +1 -0
  31. package/dist/rules/draft-visible-debt.d.ts +12 -0
  32. package/dist/rules/draft-visible-debt.d.ts.map +1 -0
  33. package/dist/rules/draft-visible-debt.js +45 -0
  34. package/dist/rules/draft-visible-debt.js.map +1 -0
  35. package/dist/rules/index.d.ts +2 -0
  36. package/dist/rules/index.d.ts.map +1 -1
  37. package/dist/rules/index.js +6 -0
  38. package/dist/rules/index.js.map +1 -1
  39. package/dist/rules/provision-exists.d.ts.map +1 -1
  40. package/dist/rules/provision-exists.js +2 -1
  41. package/dist/rules/provision-exists.js.map +1 -1
  42. package/dist/rules/valid-detour-refs.d.ts.map +1 -1
  43. package/dist/rules/valid-detour-refs.js +3 -2
  44. package/dist/rules/valid-detour-refs.js.map +1 -1
  45. package/package.json +4 -4
  46. package/src/__tests__/cli.test.ts +114 -1
  47. package/src/__tests__/drift.test.ts +74 -4
  48. package/src/__tests__/formatters.test.ts +2 -2
  49. package/src/cli.ts +11 -3
  50. package/src/draft.ts +22 -0
  51. package/src/drift.ts +60 -18
  52. package/src/formatters.ts +15 -4
  53. package/src/index.ts +21 -0
  54. package/src/rules/ast.ts +38 -0
  55. package/src/rules/draft-file-marking.ts +112 -0
  56. package/src/rules/draft-visible-debt.ts +62 -0
  57. package/src/rules/index.ts +6 -0
  58. package/src/rules/provision-exists.ts +3 -1
  59. package/src/rules/valid-detour-refs.ts +4 -2
  60. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,65 @@
1
+ import { isDraftId } from '@ontrails/core';
2
+ import { isDraftMarkedFile } from '../draft.js';
3
+ import { findStringLiterals, offsetToLine, parse } from './ast.js';
4
+ const messageForMissingMarker = (draftId) => `Draft id "${draftId}" appears in source, but the file is not draft-marked. ` +
5
+ 'Rename it with an _draft. prefix or a .draft. trailing segment.';
6
+ const makeDiagnostic = (sourceCode, filePath, start, message, severity) => ({
7
+ filePath,
8
+ line: offsetToLine(sourceCode, start),
9
+ message,
10
+ rule: 'draft-file-marking',
11
+ severity,
12
+ });
13
+ const draftMissingMarkerDiagnostic = (sourceCode, filePath, ast) => {
14
+ const draftMatches = findStringLiterals(ast, (value) => isDraftId(value));
15
+ if (!draftMatches.length || isDraftMarkedFile(filePath)) {
16
+ return null;
17
+ }
18
+ const [first] = draftMatches;
19
+ if (!first) {
20
+ return null;
21
+ }
22
+ return makeDiagnostic(sourceCode, filePath, first.start, messageForMissingMarker(first.value), 'error');
23
+ };
24
+ const draftMarkedWithoutIdsDiagnostic = (filePath, ast) => {
25
+ if (findStringLiterals(ast, (value) => isDraftId(value)).length > 0) {
26
+ return null;
27
+ }
28
+ if (!isDraftMarkedFile(filePath)) {
29
+ return null;
30
+ }
31
+ return {
32
+ filePath,
33
+ line: 1,
34
+ message: 'File is draft-marked but no longer contains draft ids. Remove the draft filename marker or finish the promotion cleanup.',
35
+ rule: 'draft-file-marking',
36
+ severity: 'warn',
37
+ };
38
+ };
39
+ const collectDraftFileMarkingDiagnostics = (sourceCode, filePath, ast) => {
40
+ const missingMarkerDiagnostic = draftMissingMarkerDiagnostic(sourceCode, filePath, ast);
41
+ if (missingMarkerDiagnostic) {
42
+ return [missingMarkerDiagnostic];
43
+ }
44
+ const markedWithoutIdsDiagnostic = draftMarkedWithoutIdsDiagnostic(filePath, ast);
45
+ if (markedWithoutIdsDiagnostic) {
46
+ return [markedWithoutIdsDiagnostic];
47
+ }
48
+ return [];
49
+ };
50
+ /**
51
+ * Ensures files containing draft ids are visibly marked as draft-bearing files.
52
+ */
53
+ export const draftFileMarking = {
54
+ check(sourceCode, filePath) {
55
+ const ast = parse(filePath, sourceCode);
56
+ if (!ast) {
57
+ return [];
58
+ }
59
+ return collectDraftFileMarkingDiagnostics(sourceCode, filePath, ast);
60
+ },
61
+ description: 'Require draft-bearing files to use _draft.* or *.draft.* filename markers.',
62
+ name: 'draft-file-marking',
63
+ severity: 'error',
64
+ };
65
+ //# sourceMappingURL=draft-file-marking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft-file-marking.js","sourceRoot":"","sources":["../../src/rules/draft-file-marking.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { WardenRule } from './types.js';
2
+ /**
3
+ * Warns when draft ids are still present so the debt stays visible during
4
+ * review even when the file is correctly marked.
5
+ *
6
+ * Severity is intentionally `warn`, not `error`. The hard rejection gate for
7
+ * draft state leaking into established outputs is `validateEstablishedTopo` at
8
+ * runtime — it blocks topo export, trailhead projection, and lockfile writes.
9
+ * This rule surfaces the debt for human reviewers without duplicating that gate.
10
+ */
11
+ export declare const draftVisibleDebt: WardenRule;
12
+ //# sourceMappingURL=draft-visible-debt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft-visible-debt.d.ts","sourceRoot":"","sources":["../../src/rules/draft-visible-debt.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAoB,UAAU,EAAE,MAAM,YAAY,CAAC;AAoC/D;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,EAAE,UAa9B,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { isDraftId } from '@ontrails/core';
2
+ import { findStringLiterals, offsetToLine, parse } from './ast.js';
3
+ const createDiagnostic = (sourceCode, filePath, match) => ({
4
+ filePath,
5
+ line: offsetToLine(sourceCode, match.start),
6
+ message: `Draft id "${match.value}" is still visible debt. ` +
7
+ 'Established trailheads, lock export, and OpenAPI generation will reject it until it is promoted.',
8
+ rule: 'draft-visible-debt',
9
+ severity: 'warn',
10
+ });
11
+ const collectDraftVisibleDebtDiagnostics = (sourceCode, filePath, ast) => {
12
+ const seen = new Set();
13
+ const diagnostics = [];
14
+ for (const match of findStringLiterals(ast, (value) => isDraftId(value))) {
15
+ const key = `${match.value}:${String(match.start)}`;
16
+ if (seen.has(key)) {
17
+ continue;
18
+ }
19
+ seen.add(key);
20
+ diagnostics.push(createDiagnostic(sourceCode, filePath, match));
21
+ }
22
+ return diagnostics;
23
+ };
24
+ /**
25
+ * Warns when draft ids are still present so the debt stays visible during
26
+ * review even when the file is correctly marked.
27
+ *
28
+ * Severity is intentionally `warn`, not `error`. The hard rejection gate for
29
+ * draft state leaking into established outputs is `validateEstablishedTopo` at
30
+ * runtime — it blocks topo export, trailhead projection, and lockfile writes.
31
+ * This rule surfaces the debt for human reviewers without duplicating that gate.
32
+ */
33
+ export const draftVisibleDebt = {
34
+ check(sourceCode, filePath) {
35
+ const ast = parse(filePath, sourceCode);
36
+ if (!ast) {
37
+ return [];
38
+ }
39
+ return collectDraftVisibleDebtDiagnostics(sourceCode, filePath, ast);
40
+ },
41
+ description: 'Warn when draft ids remain in source so the debt stays visible during review.',
42
+ name: 'draft-visible-debt',
43
+ severity: 'warn',
44
+ };
45
+ //# sourceMappingURL=draft-visible-debt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft-visible-debt.js","sourceRoot":"","sources":["../../src/rules/draft-visible-debt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAGnE,MAAM,gBAAgB,GAAG,CACvB,UAAkB,EAClB,QAAgB,EAChB,KAAuC,EACrB,EAAE,CAAC,CAAC;IACtB,QAAQ;IACR,IAAI,EAAE,YAAY,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC;IAC3C,OAAO,EACL,aAAa,KAAK,CAAC,KAAK,2BAA2B;QACnD,kGAAkG;IACpG,IAAI,EAAE,oBAAoB;IAC1B,QAAQ,EAAE,MAAM;CACjB,CAAC,CAAC;AAEH,MAAM,kCAAkC,GAAG,CACzC,UAAkB,EAClB,QAAgB,EAChB,GAA0C,EACtB,EAAE;IACtB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,WAAW,GAAuB,EAAE,CAAC;IAE3C,KAAK,MAAM,KAAK,IAAI,kBAAkB,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACzE,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAe;IAC1C,KAAK,CAAC,UAAkB,EAAE,QAAgB;QACxC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,kCAAkC,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;IACvE,CAAC;IACD,WAAW,EACT,+EAA+E;IACjF,IAAI,EAAE,oBAAoB;IAC1B,QAAQ,EAAE,MAAM;CACjB,CAAC"}
@@ -3,6 +3,8 @@ export type { ProjectAwareWardenRule, ProjectContext, WardenDiagnostic, WardenRu
3
3
  export { noThrowInImplementation } from './no-throw-in-implementation.js';
4
4
  export { contextNoTrailheadTypes } from './context-no-trailhead-types.js';
5
5
  export { crossDeclarations } from './cross-declarations.js';
6
+ export { draftFileMarking } from './draft-file-marking.js';
7
+ export { draftVisibleDebt } from './draft-visible-debt.js';
6
8
  export { validDetourRefs } from './valid-detour-refs.js';
7
9
  export { noDirectImplInRoute } from './no-direct-impl-in-route.js';
8
10
  export { noDirectImplementationCall } from './no-direct-implementation-call.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,YAAY,EACV,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,qDAAqD;AACrD,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAiBtD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,YAAY,EACV,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,qDAAqD;AACrD,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAmBtD,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import { contextNoTrailheadTypes } from './context-no-trailhead-types.js';
2
2
  import { crossDeclarations } from './cross-declarations.js';
3
+ import { draftFileMarking } from './draft-file-marking.js';
4
+ import { draftVisibleDebt } from './draft-visible-debt.js';
3
5
  import { implementationReturnsResult } from './implementation-returns-result.js';
4
6
  import { noDirectImplInRoute } from './no-direct-impl-in-route.js';
5
7
  import { noDirectImplementationCall } from './no-direct-implementation-call.js';
@@ -14,6 +16,8 @@ import { validDetourRefs } from './valid-detour-refs.js';
14
16
  export { noThrowInImplementation } from './no-throw-in-implementation.js';
15
17
  export { contextNoTrailheadTypes } from './context-no-trailhead-types.js';
16
18
  export { crossDeclarations } from './cross-declarations.js';
19
+ export { draftFileMarking } from './draft-file-marking.js';
20
+ export { draftVisibleDebt } from './draft-visible-debt.js';
17
21
  export { validDetourRefs } from './valid-detour-refs.js';
18
22
  export { noDirectImplInRoute } from './no-direct-impl-in-route.js';
19
23
  export { noDirectImplementationCall } from './no-direct-implementation-call.js';
@@ -29,6 +33,8 @@ export const wardenRules = new Map([
29
33
  [noThrowInImplementation.name, noThrowInImplementation],
30
34
  [contextNoTrailheadTypes.name, contextNoTrailheadTypes],
31
35
  [crossDeclarations.name, crossDeclarations],
36
+ [draftFileMarking.name, draftFileMarking],
37
+ [draftVisibleDebt.name, draftVisibleDebt],
32
38
  [provisionDeclarations.name, provisionDeclarations],
33
39
  [provisionExists.name, provisionExists],
34
40
  [preferSchemaInference.name, preferSchemaInference],
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAUzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,qDAAqD;AACrD,MAAM,CAAC,MAAM,WAAW,GAAoC,IAAI,GAAG,CAGjE;IACA,CAAC,uBAAuB,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvD,CAAC,uBAAuB,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvD,CAAC,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAC3C,CAAC,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACnD,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC;IACvC,CAAC,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACnD,CAAC,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAC3C,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC;IACvC,CAAC,0BAA0B,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAC7D,CAAC,sBAAsB,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACrD,CAAC,2BAA2B,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC/D,CAAC,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACnD,CAAC,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,CAAC;CAChD,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"provision-exists.d.ts","sourceRoot":"","sources":["../../src/rules/provision-exists.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,YAAY,CAAC;AAiIpB;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,sBA+B7B,CAAC"}
1
+ {"version":3,"file":"provision-exists.d.ts","sourceRoot":"","sources":["../../src/rules/provision-exists.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,YAAY,CAAC;AAiIpB;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,sBA+B7B,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { isDraftId } from '@ontrails/core';
1
2
  import { collectNamedProvisionIds, collectProvisionDefinitionIds, extractFirstStringArg, findConfigProperty, findTrailDefinitions, getStringValue, identifierName, isStringLiteral, offsetToLine, parse, } from './ast.js';
2
3
  import { isTestFile } from './scan.js';
3
4
  const isProvisionCall = (node) => node.type === 'CallExpression' &&
@@ -41,7 +42,7 @@ const buildMissingProvisionDiagnostic = (trailId, provisionId, filePath, line) =
41
42
  const reportMissingProvisions = (def, sourceCode, provisionIdsByName, filePath, knownProvisionIds, diagnostics) => {
42
43
  const line = offsetToLine(sourceCode, def.start);
43
44
  for (const provisionId of extractDeclaredProvisionIds(def.config, provisionIdsByName)) {
44
- if (!knownProvisionIds.has(provisionId)) {
45
+ if (!knownProvisionIds.has(provisionId) && !isDraftId(provisionId)) {
45
46
  diagnostics.push(buildMissingProvisionDiagnostic(def.id, provisionId, filePath, line));
46
47
  }
47
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"provision-exists.js","sourceRoot":"","sources":["../../src/rules/provision-exists.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provision-exists.js","sourceRoot":"","sources":["../../src/rules/provision-exists.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"valid-detour-refs.d.ts","sourceRoot":"","sources":["../../src/rules/valid-detour-refs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,YAAY,CAAC;AAoKpB;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,sBAc7B,CAAC"}
1
+ {"version":3,"file":"valid-detour-refs.d.ts","sourceRoot":"","sources":["../../src/rules/valid-detour-refs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,YAAY,CAAC;AAoKpB;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,sBAc7B,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { isDraftId } from '@ontrails/core';
1
2
  import { collectTrailIds } from './specs.js';
2
3
  const trackBraces = (line, state) => {
3
4
  for (const ch of line) {
@@ -28,7 +29,7 @@ const findMissingDetourTargets = (text, knownIds) => {
28
29
  const missing = [];
29
30
  for (const m of text.matchAll(/target\s*:\s*["'`]([^"'`]+)["'`]/g)) {
30
31
  const [, id] = m;
31
- if (id && !knownIds.has(id)) {
32
+ if (id && !knownIds.has(id) && !isDraftId(id)) {
32
33
  missing.push(id);
33
34
  }
34
35
  }
@@ -39,7 +40,7 @@ const findMissingPlainDetours = (text, knownIds) => {
39
40
  const cleaned = text.replaceAll(/target\s*:\s*["'`][^"'`]+["'`]/g, '');
40
41
  for (const m of cleaned.matchAll(/["'`]([^"'`]+)["'`]/g)) {
41
42
  const [, id] = m;
42
- if (id && id.includes('.') && !knownIds.has(id)) {
43
+ if (id && id.includes('.') && !knownIds.has(id) && !isDraftId(id)) {
43
44
  missing.push(id);
44
45
  }
45
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"valid-detour-refs.js","sourceRoot":"","sources":["../../src/rules/valid-detour-refs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"valid-detour-refs.js","sourceRoot":"","sources":["../../src/rules/valid-detour-refs.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ontrails/warden",
3
- "version": "1.0.0-beta.13",
3
+ "version": "1.0.0-beta.14",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/index.ts",
@@ -14,13 +14,13 @@
14
14
  "clean": "rm -rf dist *.tsbuildinfo"
15
15
  },
16
16
  "devDependencies": {
17
- "@ontrails/testing": "^1.0.0-beta.12",
17
+ "@ontrails/testing": "^1.0.0-beta.13",
18
18
  "@oxc-project/types": "^0.122.0",
19
19
  "oxc-parser": "^0.121.0",
20
20
  "zod": "^4.3.5"
21
21
  },
22
22
  "peerDependencies": {
23
- "@ontrails/core": "^1.0.0-beta.12",
24
- "@ontrails/schema": "^1.0.0-beta.12"
23
+ "@ontrails/core": "^1.0.0-beta.13",
24
+ "@ontrails/schema": "^1.0.0-beta.13"
25
25
  }
26
26
  }
@@ -5,6 +5,24 @@ import { join } from 'node:path';
5
5
 
6
6
  import { formatWardenReport, runWarden } from '../cli.js';
7
7
 
8
+ const isDraftFileMarking = (rule: string): boolean =>
9
+ rule === 'draft-file-marking';
10
+
11
+ const isDraftFileMarkingError = (diagnostic: {
12
+ rule: string;
13
+ severity?: string;
14
+ }): boolean =>
15
+ isDraftFileMarking(diagnostic.rule) && diagnostic.severity === 'error';
16
+
17
+ const isDraftFileMarkingWarn = (diagnostic: {
18
+ rule: string;
19
+ severity?: string;
20
+ }): boolean =>
21
+ isDraftFileMarking(diagnostic.rule) && diagnostic.severity === 'warn';
22
+
23
+ const isDraftVisibleDebt = (rule: string): boolean =>
24
+ rule === 'draft-visible-debt';
25
+
8
26
  const makeTempDir = (): string => {
9
27
  const dir = join(
10
28
  tmpdir(),
@@ -146,6 +164,83 @@ describe('runWarden', () => {
146
164
  rmSync(dir, { force: true, recursive: true });
147
165
  }
148
166
  });
167
+
168
+ test('requires draft-bearing files to be visibly marked', async () => {
169
+ const dir = makeTempDir();
170
+ try {
171
+ writeFileSync(
172
+ join(dir, 'draft-id.ts'),
173
+ `trail("_draft.entity.prepare", {
174
+ blaze: async () => Result.ok({ ok: true }),
175
+ input: z.object({})
176
+ })`
177
+ );
178
+
179
+ const report = await runWarden({ rootDir: dir });
180
+
181
+ const hasDraftFileMarking = report.diagnostics.some((diagnostic) =>
182
+ isDraftFileMarking(diagnostic.rule)
183
+ );
184
+ const hasDraftVisibleDebt = report.diagnostics.some((diagnostic) =>
185
+ isDraftVisibleDebt(diagnostic.rule)
186
+ );
187
+
188
+ expect(hasDraftFileMarking).toBe(true);
189
+ expect(hasDraftVisibleDebt).toBe(true);
190
+ } finally {
191
+ rmSync(dir, { force: true, recursive: true });
192
+ }
193
+ });
194
+
195
+ test('allows correctly marked draft files while keeping the debt visible', async () => {
196
+ const dir = makeTempDir();
197
+ try {
198
+ writeFileSync(
199
+ join(dir, '_draft.entity.ts'),
200
+ `trail("_draft.entity.prepare", {
201
+ blaze: async () => Result.ok({ ok: true }),
202
+ input: z.object({})
203
+ })`
204
+ );
205
+
206
+ const report = await runWarden({ rootDir: dir });
207
+
208
+ const hasDraftFileMarkingError = report.diagnostics.some((diagnostic) =>
209
+ isDraftFileMarkingError(diagnostic)
210
+ );
211
+ const hasDraftVisibleDebt = report.diagnostics.some((diagnostic) =>
212
+ isDraftVisibleDebt(diagnostic.rule)
213
+ );
214
+
215
+ expect(hasDraftFileMarkingError).toBe(false);
216
+ expect(hasDraftVisibleDebt).toBe(true);
217
+ } finally {
218
+ rmSync(dir, { force: true, recursive: true });
219
+ }
220
+ });
221
+
222
+ test('warns when a draft-marked file no longer contains draft ids', async () => {
223
+ const dir = makeTempDir();
224
+ try {
225
+ writeFileSync(
226
+ join(dir, 'entity.draft.ts'),
227
+ `trail("entity.prepare", {
228
+ blaze: async () => Result.ok({ ok: true }),
229
+ input: z.object({})
230
+ })`
231
+ );
232
+
233
+ const report = await runWarden({ rootDir: dir });
234
+
235
+ const hasDraftFileMarkingWarn = report.diagnostics.some((diagnostic) =>
236
+ isDraftFileMarkingWarn(diagnostic)
237
+ );
238
+
239
+ expect(hasDraftFileMarkingWarn).toBe(true);
240
+ } finally {
241
+ rmSync(dir, { force: true, recursive: true });
242
+ }
243
+ });
149
244
  });
150
245
 
151
246
  describe('formatWardenReport', () => {
@@ -192,7 +287,25 @@ describe('formatWardenReport', () => {
192
287
  passed: false,
193
288
  warnCount: 0,
194
289
  });
195
- expect(output).toContain('trailhead.lock is stale');
290
+ expect(output).toContain('trails.lock is stale');
196
291
  expect(output).toContain('Result: FAIL');
197
292
  });
293
+
294
+ test('formats a report with blocked established exports', () => {
295
+ const output = formatWardenReport({
296
+ diagnostics: [],
297
+ drift: {
298
+ blockedReason:
299
+ 'Established topo validation failed with 1 draft issue(s)',
300
+ committedHash: null,
301
+ currentHash: 'blocked',
302
+ stale: true,
303
+ },
304
+ errorCount: 0,
305
+ passed: false,
306
+ warnCount: 0,
307
+ });
308
+ expect(output).toContain('Drift: blocked');
309
+ expect(output).toContain('established exports blocked');
310
+ });
198
311
  });
@@ -3,8 +3,17 @@ import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
4
  import { tmpdir } from 'node:os';
5
5
 
6
- import { trail, topo, Result } from '@ontrails/core';
7
- import { hashTrailheadMap, generateTrailheadMap } from '@ontrails/schema';
6
+ import { createTopoStore, trail, topo, Result } from '@ontrails/core';
7
+ import { persistEstablishedTopoSave } from '@ontrails/core/internal/topo-store';
8
+ import {
9
+ openWriteTrailsDb,
10
+ resolveTrailsDir,
11
+ } from '@ontrails/core/internal/trails-db';
12
+ import {
13
+ hashTrailheadMap,
14
+ generateTrailheadMap,
15
+ writeTrailheadLock,
16
+ } from '@ontrails/schema';
8
17
  import { z } from 'zod';
9
18
 
10
19
  import { checkDrift } from '../drift.js';
@@ -24,6 +33,28 @@ const createTempDir = (): string => {
24
33
  return dir;
25
34
  };
26
35
 
36
+ const committedLockDir = (dir: string): string => {
37
+ const trailsDir = resolveTrailsDir({ rootDir: dir });
38
+ mkdirSync(trailsDir, { recursive: true });
39
+ return trailsDir;
40
+ };
41
+
42
+ const seedSavedTopo = (dir: string): string | undefined => {
43
+ const db = openWriteTrailsDb({ rootDir: dir });
44
+ try {
45
+ const result = persistEstablishedTopoSave(db, makeTopo(), {
46
+ createdAt: '2026-04-03T15:00:00.000Z',
47
+ });
48
+ if (result.isErr()) {
49
+ throw result.error;
50
+ }
51
+ } finally {
52
+ db.close();
53
+ }
54
+
55
+ return createTopoStore({ rootDir: dir }).exports.get()?.trailheadHash;
56
+ };
57
+
27
58
  describe('checkDrift', () => {
28
59
  test('returns stale: false when no topo is provided', async () => {
29
60
  const result = await checkDrift('/tmp');
@@ -43,12 +74,28 @@ describe('checkDrift', () => {
43
74
  }
44
75
  });
45
76
 
77
+ test('uses the latest saved topo hash when no live topo is provided', async () => {
78
+ const dir = createTempDir();
79
+ try {
80
+ const expectedHash = seedSavedTopo(dir);
81
+ const result = await checkDrift(dir);
82
+
83
+ expect(result.stale).toBe(false);
84
+ expect(result.currentHash).toBe(expectedHash);
85
+ } finally {
86
+ rmSync(dir, { force: true, recursive: true });
87
+ }
88
+ });
89
+
46
90
  test('returns stale: false when lock matches current hash', async () => {
47
91
  const dir = createTempDir();
48
92
  try {
49
93
  const tp = makeTopo();
50
94
  const hash = hashTrailheadMap(generateTrailheadMap(tp));
51
- writeFileSync(join(dir, 'trailhead.lock'), `${hash}\n`);
95
+ await writeTrailheadLock(
96
+ { hash, version: 1 },
97
+ { dir: committedLockDir(dir) }
98
+ );
52
99
 
53
100
  const result = await checkDrift(dir, tp);
54
101
  expect(result.stale).toBe(false);
@@ -62,7 +109,10 @@ describe('checkDrift', () => {
62
109
  test('returns stale: true when lock does not match', async () => {
63
110
  const dir = createTempDir();
64
111
  try {
65
- writeFileSync(join(dir, 'trailhead.lock'), 'outdated-hash\n');
112
+ writeFileSync(
113
+ join(committedLockDir(dir), 'trailhead.lock'),
114
+ 'outdated-hash\n'
115
+ );
66
116
 
67
117
  const result = await checkDrift(dir, makeTopo());
68
118
  expect(result.stale).toBe(true);
@@ -71,4 +121,24 @@ describe('checkDrift', () => {
71
121
  rmSync(dir, { force: true, recursive: true });
72
122
  }
73
123
  });
124
+
125
+ test('blocks drift calculation when draft state remains in the topo', async () => {
126
+ const dir = createTempDir();
127
+ try {
128
+ const draftTrail = trail('test.hello', {
129
+ blaze: () => Result.ok({ greeting: 'hi' }),
130
+ crosses: ['_draft.test.prepare'],
131
+ input: z.object({ name: z.string() }),
132
+ output: z.object({ greeting: z.string() }),
133
+ });
134
+
135
+ const result = await checkDrift(dir, topo('test-app', { draftTrail }));
136
+
137
+ expect(result.stale).toBe(true);
138
+ expect(result.blockedReason).toContain('draft');
139
+ expect(result.currentHash).toBe('blocked');
140
+ } finally {
141
+ rmSync(dir, { force: true, recursive: true });
142
+ }
143
+ });
74
144
  });
@@ -67,7 +67,7 @@ describe('formatGitHubAnnotations', () => {
67
67
 
68
68
  test('emits drift as a single ::error annotation', () => {
69
69
  const output = formatGitHubAnnotations(reportWithDrift);
70
- expect(output).toContain('::error::drift: trailhead.lock is stale');
70
+ expect(output).toContain('::error::drift: trails.lock is stale');
71
71
  });
72
72
 
73
73
  test('produces one line per diagnostic', () => {
@@ -148,7 +148,7 @@ describe('formatSummary', () => {
148
148
  test('includes drift section when stale', () => {
149
149
  const output = formatSummary(reportWithDrift);
150
150
  expect(output).toContain('### Drift');
151
- expect(output).toContain('trailhead.lock is stale');
151
+ expect(output).toContain('trails.lock is stale');
152
152
  });
153
153
 
154
154
  test('omits drift section when clean', () => {
package/src/cli.ts CHANGED
@@ -293,7 +293,10 @@ export const runWarden = async (
293
293
  diagnostics: allDiagnostics,
294
294
  drift,
295
295
  errorCount,
296
- passed: errorCount === 0 && !(drift?.stale ?? false),
296
+ passed:
297
+ errorCount === 0 &&
298
+ !(drift?.stale ?? false) &&
299
+ drift?.blockedReason === undefined,
297
300
  warnCount,
298
301
  };
299
302
  };
@@ -327,8 +330,11 @@ const formatDriftSection = (drift: DriftResult | null): string[] => {
327
330
  if (drift === null) {
328
331
  return [];
329
332
  }
333
+ if (drift.blockedReason !== undefined) {
334
+ return [`Drift: blocked (${drift.blockedReason})`, ''];
335
+ }
330
336
  const label = drift.stale
331
- ? 'Drift: trailhead.lock is stale (regenerate with `trails survey generate`)'
337
+ ? 'Drift: trails.lock is stale (regenerate with `trails topo export`)'
332
338
  : 'Drift: clean';
333
339
  return [label, ''];
334
340
  };
@@ -344,7 +350,9 @@ const formatResultLine = (report: WardenReport): string => {
344
350
  if (report.errorCount > 0) {
345
351
  parts.push(`${report.errorCount} errors`);
346
352
  }
347
- if (report.drift?.stale) {
353
+ if (report.drift?.blockedReason !== undefined) {
354
+ parts.push('established exports blocked');
355
+ } else if (report.drift?.stale) {
348
356
  parts.push('drift detected');
349
357
  }
350
358
  return `Result: FAIL (${parts.join(', ')})`;
package/src/draft.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { basename } from 'node:path';
2
+
3
+ export const DRAFT_FILE_PREFIX = '_draft.';
4
+ export const DRAFT_FILE_SEGMENT = '.draft.';
5
+
6
+ const DRAFT_TRAILING_SEGMENT = /\.draft(?=\.[^.]+$)/;
7
+
8
+ export const isDraftMarkedFile = (filePath: string): boolean => {
9
+ const fileName = basename(filePath);
10
+ return (
11
+ fileName.startsWith(DRAFT_FILE_PREFIX) ||
12
+ fileName.includes(DRAFT_FILE_SEGMENT)
13
+ );
14
+ };
15
+
16
+ export const stripDraftFileMarkers = (fileName: string): string => {
17
+ if (fileName.startsWith(DRAFT_FILE_PREFIX)) {
18
+ return fileName.slice(DRAFT_FILE_PREFIX.length);
19
+ }
20
+
21
+ return fileName.replace(DRAFT_TRAILING_SEGMENT, '');
22
+ };