laymos 0.0.7 → 0.0.8

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 (69) hide show
  1. package/dist/architecture-analysis-schema/architecture-analysis-schema.d.ts +4 -0
  2. package/dist/architecture-analysis-schema/architecture-analysis-schema.d.ts.map +1 -1
  3. package/dist/architecture-analysis-schema/documentation-schema.d.ts +36 -0
  4. package/dist/architecture-analysis-schema/documentation-schema.d.ts.map +1 -0
  5. package/dist/architecture-analysis-schema/documentation-schema.js +19 -0
  6. package/dist/architecture-analysis-schema/index.d.ts +2 -0
  7. package/dist/architecture-analysis-schema/index.d.ts.map +1 -1
  8. package/dist/architecture-analysis-schema/index.js +1 -0
  9. package/dist/architecture-analysis-schema/project-config-schema.d.ts +9 -0
  10. package/dist/architecture-analysis-schema/project-config-schema.d.ts.map +1 -1
  11. package/dist/architecture-analysis-schema/project-config-schema.js +13 -0
  12. package/dist/change-set-schema/change-set-schema.d.ts +6 -0
  13. package/dist/change-set-schema/change-set-schema.d.ts.map +1 -1
  14. package/dist/change-set-schema/change-set-schema.js +8 -0
  15. package/dist/change-set-schema/index.d.ts +2 -2
  16. package/dist/change-set-schema/index.d.ts.map +1 -1
  17. package/dist/change-set-schema/index.js +1 -1
  18. package/dist/domain/project-config/project-config.d.ts +4 -0
  19. package/dist/domain/project-config/project-config.d.ts.map +1 -1
  20. package/dist/domain/project-config/validation/paths.js +20 -4
  21. package/dist/index.d.ts +7 -3
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +7 -2
  24. package/dist/orchestrator/analyze-project/analyze-project.d.ts +4 -0
  25. package/dist/orchestrator/analyze-project/analyze-project.d.ts.map +1 -1
  26. package/dist/orchestrator/inspect/inspect.d.ts +6 -0
  27. package/dist/orchestrator/inspect/inspect.d.ts.map +1 -1
  28. package/dist/orchestrator/load-changes/index.d.ts +1 -1
  29. package/dist/orchestrator/load-changes/index.d.ts.map +1 -1
  30. package/dist/orchestrator/load-changes/index.js +1 -1
  31. package/dist/orchestrator/load-changes/load-changes.d.ts +2 -1
  32. package/dist/orchestrator/load-changes/load-changes.d.ts.map +1 -1
  33. package/dist/orchestrator/load-changes/load-changes.js +6 -0
  34. package/dist/orchestrator/load-documentation/errors.d.ts +18 -0
  35. package/dist/orchestrator/load-documentation/errors.d.ts.map +1 -0
  36. package/dist/orchestrator/load-documentation/errors.js +5 -0
  37. package/dist/orchestrator/load-documentation/index.d.ts +2 -0
  38. package/dist/orchestrator/load-documentation/index.d.ts.map +1 -0
  39. package/dist/orchestrator/load-documentation/index.js +1 -0
  40. package/dist/orchestrator/load-documentation/load-documentation.d.ts +23 -0
  41. package/dist/orchestrator/load-documentation/load-documentation.d.ts.map +1 -0
  42. package/dist/orchestrator/load-documentation/load-documentation.js +66 -0
  43. package/dist/orchestrator/load-project/load-project.d.ts +4 -0
  44. package/dist/orchestrator/load-project/load-project.d.ts.map +1 -1
  45. package/dist/orchestrator/load-source-files/errors.d.ts +10 -0
  46. package/dist/orchestrator/load-source-files/errors.d.ts.map +1 -0
  47. package/dist/orchestrator/load-source-files/errors.js +3 -0
  48. package/dist/orchestrator/load-source-files/index.d.ts +2 -0
  49. package/dist/orchestrator/load-source-files/index.d.ts.map +1 -0
  50. package/dist/orchestrator/load-source-files/index.js +1 -0
  51. package/dist/orchestrator/load-source-files/load-source-files.d.ts +16 -0
  52. package/dist/orchestrator/load-source-files/load-source-files.d.ts.map +1 -0
  53. package/dist/orchestrator/load-source-files/load-source-files.js +30 -0
  54. package/dist/orchestrator/run-stories/errors.d.ts +1 -1
  55. package/dist/orchestrator/run-stories/errors.d.ts.map +1 -1
  56. package/dist/orchestrator/run-stories/run-stories.d.ts.map +1 -1
  57. package/dist/orchestrator/run-stories/run-stories.js +41 -10
  58. package/dist/services/git/changed-paths.d.ts +2 -1
  59. package/dist/services/git/changed-paths.d.ts.map +1 -1
  60. package/dist/services/git/changed-paths.js +16 -1
  61. package/dist/services/git/git.d.ts +2 -1
  62. package/dist/services/git/git.d.ts.map +1 -1
  63. package/dist/services/git/git.js +5 -1
  64. package/dist/story/schema/story-report-schema.d.ts +0 -30
  65. package/dist/story/schema/story-report-schema.d.ts.map +1 -1
  66. package/dist/story/story.d.ts +3 -1
  67. package/dist/story/story.d.ts.map +1 -1
  68. package/package.json +2 -2
  69. package/schema.json +31 -0
@@ -0,0 +1,5 @@
1
+ import { Data } from 'effect';
2
+ export class DocumentationScopeNotFound extends Data.TaggedError('DocumentationScopeNotFound') {
3
+ }
4
+ export class DocumentationReadError extends Data.TaggedError('DocumentationReadError') {
5
+ }
@@ -0,0 +1,2 @@
1
+ export { loadDocumentation, DocumentationReadError, DocumentationScopeNotFound, } from './load-documentation.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-documentation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1 @@
1
+ export { loadDocumentation, DocumentationReadError, DocumentationScopeNotFound, } from './load-documentation.js';
@@ -0,0 +1,23 @@
1
+ import { Effect } from 'effect';
2
+ import type { DocumentationScope } from '../../architecture-analysis-schema/index.js';
3
+ import { DocumentationReadError, DocumentationScopeNotFound } from './errors.js';
4
+ export { DocumentationReadError, DocumentationScopeNotFound, } from './errors.js';
5
+ export declare function loadDocumentation(configPath: string, scope: DocumentationScope): Effect.Effect<{
6
+ scope: {
7
+ readonly kind: "module";
8
+ readonly modulePath: string;
9
+ } | {
10
+ readonly kind: "module-graph";
11
+ readonly layerId: string;
12
+ readonly graphId: string;
13
+ } | {
14
+ readonly kind: "layer";
15
+ readonly layerId: string;
16
+ } | {
17
+ readonly kind: "layer-graph";
18
+ readonly graphId: string;
19
+ };
20
+ path: string | undefined;
21
+ content: string | undefined;
22
+ }, import("../../services/config/errors.js").ConfigError | import("../../services/file-cruiser/errors.js").CruiseError | DocumentationReadError | DocumentationScopeNotFound, never>;
23
+ //# sourceMappingURL=load-documentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-documentation.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-documentation/load-documentation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAE5C,OAAO,KAAK,EAIV,kBAAkB,EACnB,MAAM,6CAA6C,CAAC;AAKrD,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC3B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAErB,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,kBAAkB;;;;;;;;;;;;;;;;;qLA0C1B"}
@@ -0,0 +1,66 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { NodeServices } from '@effect/platform-node';
3
+ import { Effect, FileSystem } from 'effect';
4
+ import { analyzeArchitecture } from '../../domain/architecture-analysis/index.js';
5
+ import { ConfigServiceLive } from '../../services/config/index.js';
6
+ import { CruiserLive } from '../../services/file-cruiser/index.js';
7
+ import { loadProject } from '../load-project/index.js';
8
+ import { DocumentationReadError, DocumentationScopeNotFound, } from './errors.js';
9
+ export { DocumentationReadError, DocumentationScopeNotFound, } from './errors.js';
10
+ export function loadDocumentation(configPath, scope) {
11
+ const absoluteConfigPath = resolve(configPath);
12
+ const baseDir = dirname(absoluteConfigPath);
13
+ return Effect.gen(function* () {
14
+ const { config, fileGraph } = yield* loadProject(absoluteConfigPath);
15
+ const analysis = analyzeArchitecture(fileGraph, config);
16
+ const fileSystem = yield* FileSystem.FileSystem;
17
+ const declaredPath = yield* resolveDeclaredPath(config, scope, analysis);
18
+ if (declaredPath === undefined) {
19
+ return {
20
+ scope,
21
+ path: undefined,
22
+ content: undefined,
23
+ };
24
+ }
25
+ const content = yield* fileSystem
26
+ .readFileString(resolve(baseDir, declaredPath))
27
+ .pipe(Effect.catchIf((cause) => scope.kind === 'module' && cause.reason._tag === 'NotFound', () => Effect.succeed(undefined)), Effect.mapError((cause) => new DocumentationReadError({ path: declaredPath, cause })));
28
+ return {
29
+ scope,
30
+ path: content === undefined ? undefined : declaredPath,
31
+ content,
32
+ };
33
+ }).pipe(Effect.provide(ConfigServiceLive), Effect.provide(CruiserLive), Effect.provide(NodeServices.layer));
34
+ }
35
+ function resolveDeclaredPath(config, scope, analysis) {
36
+ switch (scope.kind) {
37
+ case 'module': {
38
+ const module = analysis.moduleAnalysis.modules.find(({ path }) => path === scope.modulePath);
39
+ if (module === undefined) {
40
+ return Effect.fail(new DocumentationScopeNotFound({ scope }));
41
+ }
42
+ return Effect.succeed(module.shape === 'directory' ? `${module.path}/README.md` : undefined);
43
+ }
44
+ case 'module-graph': {
45
+ const graph = config.layers[scope.layerId]?.moduleGraphs[scope.graphId];
46
+ if (graph === undefined) {
47
+ return Effect.fail(new DocumentationScopeNotFound({ scope }));
48
+ }
49
+ return Effect.succeed(graph.docsPath);
50
+ }
51
+ case 'layer': {
52
+ const layer = config.layers[scope.layerId];
53
+ if (layer === undefined) {
54
+ return Effect.fail(new DocumentationScopeNotFound({ scope }));
55
+ }
56
+ return Effect.succeed(layer.docsPath);
57
+ }
58
+ case 'layer-graph': {
59
+ const layerGraph = config.layerGraphs[scope.graphId];
60
+ if (layerGraph === undefined) {
61
+ return Effect.fail(new DocumentationScopeNotFound({ scope }));
62
+ }
63
+ return Effect.succeed(layerGraph.docsPath);
64
+ }
65
+ }
66
+ }
@@ -13,10 +13,12 @@ export declare function loadProject(configPath: string): Effect.Effect<{
13
13
  readonly sourceRoots: readonly string[];
14
14
  readonly ignoredPaths: readonly string[];
15
15
  readonly storiesPath?: string | undefined;
16
+ readonly storyTimeout?: string | undefined;
16
17
  readonly layers: {
17
18
  readonly [x: string]: {
18
19
  readonly paths: readonly string[];
19
20
  readonly description?: string | undefined;
21
+ readonly docsPath?: string | undefined;
20
22
  readonly modules: {
21
23
  readonly [x: string]: {
22
24
  readonly shared: boolean;
@@ -27,6 +29,7 @@ export declare function loadProject(configPath: string): Effect.Effect<{
27
29
  readonly [x: string]: {
28
30
  readonly description?: string | undefined;
29
31
  readonly path: string;
32
+ readonly docsPath?: string | undefined;
30
33
  readonly modules: {
31
34
  readonly [x: string]: {
32
35
  readonly shared: boolean;
@@ -43,6 +46,7 @@ export declare function loadProject(configPath: string): Effect.Effect<{
43
46
  readonly layerGraphs: {
44
47
  readonly [x: string]: {
45
48
  readonly description?: string | undefined;
49
+ readonly docsPath?: string | undefined;
46
50
  readonly rules: {
47
51
  readonly [x: string]: readonly string[];
48
52
  };
@@ -1 +1 @@
1
- {"version":3,"file":"load-project.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-project/load-project.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EACL,KAAK,MAAM,EAEZ,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA4B7C"}
1
+ {"version":3,"file":"load-project.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-project/load-project.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EACL,KAAK,MAAM,EAEZ,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA4B7C"}
@@ -0,0 +1,10 @@
1
+ declare const SourceFileReadError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
2
+ readonly _tag: "SourceFileReadError";
3
+ } & Readonly<A>;
4
+ export declare class SourceFileReadError extends SourceFileReadError_base<{
5
+ readonly filePath: string;
6
+ readonly cause: unknown;
7
+ }> {
8
+ }
9
+ export {};
10
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-source-files/errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,mBAAoB,SAAQ,yBAEvC;IACA,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;CAAG"}
@@ -0,0 +1,3 @@
1
+ import { Data } from 'effect';
2
+ export class SourceFileReadError extends Data.TaggedError('SourceFileReadError') {
3
+ }
@@ -0,0 +1,2 @@
1
+ export { loadSourceFiles, SourceFileReadError } from './load-source-files.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-source-files/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1 @@
1
+ export { loadSourceFiles, SourceFileReadError } from './load-source-files.js';
@@ -0,0 +1,16 @@
1
+ import { Effect } from 'effect';
2
+ import { SourceFileReadError } from './errors.js';
3
+ export { SourceFileReadError } from './errors.js';
4
+ /**
5
+ * Reads every analyzed file at or below one of the given project-relative
6
+ * path prefixes — a Configured Module's, Module Graph's, or Layer scope's
7
+ * own root. A prefix outside the analysis universe matches nothing, so a
8
+ * caller can never use this to read a file outside the Project.
9
+ */
10
+ export declare function loadSourceFiles(configPath: string, pathPrefixes: readonly string[]): Effect.Effect<{
11
+ files: {
12
+ readonly path: string;
13
+ readonly content: string;
14
+ }[];
15
+ }, import("../../services/config/errors.js").ConfigError | import("../../services/file-cruiser/errors.js").CruiseError | SourceFileReadError, never>;
16
+ //# sourceMappingURL=load-source-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-source-files.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-source-files/load-source-files.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAM5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,SAAS,MAAM,EAAE;;;;;qJA2BhC"}
@@ -0,0 +1,30 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { NodeServices } from '@effect/platform-node';
3
+ import { Effect, FileSystem } from 'effect';
4
+ import { ConfigServiceLive } from '../../services/config/index.js';
5
+ import { CruiserLive } from '../../services/file-cruiser/index.js';
6
+ import { loadProject } from '../load-project/index.js';
7
+ import { SourceFileReadError } from './errors.js';
8
+ export { SourceFileReadError } from './errors.js';
9
+ /**
10
+ * Reads every analyzed file at or below one of the given project-relative
11
+ * path prefixes — a Configured Module's, Module Graph's, or Layer scope's
12
+ * own root. A prefix outside the analysis universe matches nothing, so a
13
+ * caller can never use this to read a file outside the Project.
14
+ */
15
+ export function loadSourceFiles(configPath, pathPrefixes) {
16
+ const absoluteConfigPath = resolve(configPath);
17
+ const baseDir = dirname(absoluteConfigPath);
18
+ return Effect.gen(function* () {
19
+ const { fileGraph } = yield* loadProject(absoluteConfigPath);
20
+ const paths = [...fileGraph.keys()]
21
+ .filter((path) => underAnyPrefix(path, pathPrefixes))
22
+ .sort((left, right) => left.localeCompare(right));
23
+ const fileSystem = yield* FileSystem.FileSystem;
24
+ const files = yield* Effect.forEach(paths, (path) => fileSystem.readFileString(resolve(baseDir, path)).pipe(Effect.map((content) => ({ path, content })), Effect.mapError((cause) => new SourceFileReadError({ filePath: path, cause }))));
25
+ return { files };
26
+ }).pipe(Effect.provide(ConfigServiceLive), Effect.provide(CruiserLive), Effect.provide(NodeServices.layer));
27
+ }
28
+ function underAnyPrefix(path, pathPrefixes) {
29
+ return pathPrefixes.some((prefix) => prefix === '.' || path === prefix || path.startsWith(`${prefix}/`));
30
+ }
@@ -2,7 +2,7 @@ declare const StoriesError_base: new <A extends Record<string, any> = {}>(args:
2
2
  readonly _tag: "StoriesError";
3
3
  } & Readonly<A>;
4
4
  export declare class StoriesError extends StoriesError_base<{
5
- readonly reason: 'no-stories-path' | 'load' | 'invalid-root' | 'duplicate-title' | 'duplicate-question' | 'snippet-extraction' | 'unknown-scope';
5
+ readonly reason: 'no-stories-path' | 'load' | 'invalid-root' | 'duplicate-title' | 'duplicate-question' | 'snippet-extraction' | 'unknown-scope' | 'invalid-timeout';
6
6
  readonly path: string;
7
7
  readonly cause: unknown;
8
8
  }> {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/run-stories/errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,MAAM,EACX,iBAAiB,GACjB,MAAM,GACN,cAAc,GACd,iBAAiB,GACjB,oBAAoB,GACpB,oBAAoB,GACpB,eAAe,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;CAAG"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/run-stories/errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,MAAM,EACX,iBAAiB,GACjB,MAAM,GACN,cAAc,GACd,iBAAiB,GACjB,oBAAoB,GACpB,oBAAoB,GACpB,eAAe,GACf,iBAAiB,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;CAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"run-stories.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/run-stories/run-stories.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,MAAM,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAC;AAWrD,OAAO,KAAK,EAQV,WAAW,EAEX,SAAS,EAEV,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAUlE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3C,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,GAAG,YAAY,CAAC,CAEtD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;CAC9C;AAID,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,GAAG,YAAY,CAAC,CAYvD;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,YAAY,CAAC,CAIxD"}
1
+ {"version":3,"file":"run-stories.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/run-stories/run-stories.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,MAAM,EAKN,MAAM,EACP,MAAM,QAAQ,CAAC;AAWhB,OAAO,KAAK,EAQV,WAAW,EAEX,SAAS,EAEV,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAUlE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3C,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,GAAG,YAAY,CAAC,CAEtD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;CAC9C;AAmBD,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,GAAG,YAAY,CAAC,CAkBvD;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,YAAY,CAAC,CAIxD"}
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { dirname, join, relative, resolve, sep } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
- import { Cause, Effect, Exit, Stream } from 'effect';
4
+ import { Cause, Duration, Effect, Exit, Logger, Option, References, Stream, } from 'effect';
5
5
  import { NodeServices } from '@effect/platform-node';
6
6
  import { tsImport } from 'tsx/esm/api';
7
7
  import { isStory, isStoryGroup, StoryContext, } from '../../story/index.js';
@@ -13,22 +13,34 @@ export function getStoryTree(configPath) {
13
13
  return Effect.map(loadRoot(configPath), ({ tree }) => tree);
14
14
  }
15
15
  const DEFAULT_CONCURRENCY = 16;
16
+ const DEFAULT_STORY_TIMEOUT = Duration.seconds(10);
17
+ // The config names a Duration as text; a Story carries a typed DurationInput.
18
+ function resolveTimeout(input, fallback, path) {
19
+ if (input === undefined)
20
+ return Effect.succeed(fallback);
21
+ return Option.match(Duration.fromInput(input), {
22
+ onNone: () => new StoriesError({ reason: 'invalid-timeout', path, cause: input }),
23
+ onSome: Effect.succeed,
24
+ });
25
+ }
16
26
  export function planStories(configPath, options) {
17
27
  return Effect.gen(function* () {
18
- const { stories } = yield* loadRoot(configPath);
28
+ const { stories, storyTimeout } = yield* loadRoot(configPath);
29
+ const timeout = yield* resolveTimeout(storyTimeout, DEFAULT_STORY_TIMEOUT, configPath);
19
30
  const planned = yield* scopeStories(stories, options?.scope);
20
31
  return {
21
32
  total: planned.length,
22
- reports: runEachStory(planned, options?.concurrency ?? DEFAULT_CONCURRENCY),
33
+ reports: yield* runEachStory(planned, options?.concurrency ?? DEFAULT_CONCURRENCY, timeout),
23
34
  };
24
35
  });
25
36
  }
26
37
  export function runStories(configPath, options) {
27
38
  return Stream.unwrap(Effect.map(planStories(configPath, options), ({ reports }) => reports));
28
39
  }
29
- function runEachStory(stories, concurrency) {
40
+ function runEachStory(stories, concurrency, timeout) {
41
+ return Effect.map(Effect.forEach(stories, (indexed) => Effect.map(resolveTimeout(indexed.story.timeout, timeout, indexed.id), (budget) => ({ indexed, budget }))), (planned) =>
30
42
  // Ordered concurrent mapping needs three slots; anything less runs one at a time.
31
- return Stream.fromArray(stories).pipe(Stream.mapEffect(runStory, concurrency >= 3 ? { concurrency } : undefined));
43
+ Stream.fromArray(planned).pipe(Stream.mapEffect(({ indexed, budget }) => runStory(indexed, budget), concurrency >= 3 ? { concurrency } : undefined)));
32
44
  }
33
45
  function scopeStories(stories, scope) {
34
46
  if (scope === undefined)
@@ -74,6 +86,7 @@ function loadRoot(configPath) {
74
86
  const indexed = yield* indexGroup(root, [root.title], entryPoint, options);
75
87
  return {
76
88
  ...indexed,
89
+ storyTimeout: config.storyTimeout,
77
90
  tree: attachGroupPages(indexed.tree, indexed.directory, options.projectRoot, options.groupDirectories),
78
91
  };
79
92
  }).pipe(Effect.provide(ConfigServiceLive), Effect.provide(NodeServices.layer));
@@ -283,12 +296,27 @@ function checkUniqueTitles(children, path, entryPoint) {
283
296
  }
284
297
  return Effect.void;
285
298
  }
286
- function runStory({ id, story }) {
299
+ function runStory({ id, story }, timeout) {
287
300
  return Effect.gen(function* () {
288
301
  const questions = [];
289
- for (const question of story.questions) {
290
- questions.push(yield* runQuestion(question));
291
- }
302
+ // One budget for the whole Story: a hanging proof becomes an errored
303
+ // verdict instead of wedging the run.
304
+ yield* Effect.gen(function* () {
305
+ for (const question of story.questions) {
306
+ questions.push(yield* runQuestion(question));
307
+ }
308
+ }).pipe(Effect.timeout(timeout), Effect.catchTag('TimeoutError', () => Effect.sync(() => {
309
+ const interrupted = story.questions[questions.length];
310
+ if (interrupted !== undefined) {
311
+ questions.push({
312
+ slug: slugifyQuestion(interrupted.question),
313
+ verdict: 'errored',
314
+ error: `Story timed out after ${Duration.format(timeout)}`,
315
+ assertions: [],
316
+ sections: [],
317
+ });
318
+ }
319
+ })));
292
320
  const verdict = questions.some(({ verdict }) => verdict === 'errored')
293
321
  ? 'errored'
294
322
  : questions.some(({ verdict }) => verdict === 'failed')
@@ -308,7 +336,10 @@ function runQuestion(question) {
308
336
  assert: (description, passed) => Effect.sync(() => {
309
337
  assertions.push({ description, passed });
310
338
  }),
311
- }), Effect.exit);
339
+ }),
340
+ // A proof must see the same logging whatever host runs it: a Story
341
+ // that captures its own logs cannot depend on the host's log level.
342
+ Effect.provideService(References.MinimumLogLevel, 'Info'), Effect.provide(Logger.layer([])), Effect.exit);
312
343
  const slug = slugifyQuestion(question.question);
313
344
  if (Exit.isFailure(exit)) {
314
345
  return {
@@ -1,4 +1,5 @@
1
- import type { ChangeSet, DiffHunk } from '../../change-set-schema/index.js';
1
+ import type { Branch, ChangeSet, DiffHunk } from '../../change-set-schema/index.js';
2
2
  export declare function readChangeSet(baseDir: string, baseRef: string): Promise<ChangeSet>;
3
3
  export declare function readFileDiff(baseDir: string, baseRef: string, path: string): Promise<readonly DiffHunk[]>;
4
+ export declare function listBranches(baseDir: string): Promise<Branch[]>;
4
5
  //# sourceMappingURL=changed-paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"changed-paths.d.ts","sourceRoot":"","sources":["../../../src/services/git/changed-paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EAET,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAY1C,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CA+BpB;AA8CD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CAiB9B"}
1
+ {"version":3,"file":"changed-paths.d.ts","sourceRoot":"","sources":["../../../src/services/git/changed-paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EAEN,SAAS,EAET,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAY1C,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CA+BpB;AA8CD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CAiB9B;AAYD,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBrE"}
@@ -1,5 +1,5 @@
1
1
  import { parsePatch } from './parse-patch.js';
2
- import { requireGit, splitNul } from './run-git.js';
2
+ import { requireGit, runGit, splitNul } from './run-git.js';
3
3
  const wholeFileContext = 1000000;
4
4
  export async function readChangeSet(baseDir, baseRef) {
5
5
  await requireGit(baseDir, ['rev-parse', '--show-toplevel'], 'not-a-repo');
@@ -71,6 +71,21 @@ async function resolveBase(baseDir, baseRef) {
71
71
  const mergeBase = await requireGit(baseDir, ['merge-base', baseRef, 'HEAD'], 'unknown-ref');
72
72
  return mergeBase.trim();
73
73
  }
74
+ export async function listBranches(baseDir) {
75
+ await requireGit(baseDir, ['rev-parse', '--show-toplevel'], 'not-a-repo');
76
+ const current = (await runGit(baseDir, ['symbolic-ref', '--short', 'HEAD'])).stdout.trim();
77
+ const local = splitLines(await requireGit(baseDir, ['for-each-ref', '--format=%(refname:short)', 'refs/heads'], 'command-failed')).map((name) => ({ name, remote: false, current: name === current }));
78
+ const remote = splitLines(await requireGit(baseDir, ['for-each-ref', '--format=%(refname:short)', 'refs/remotes'], 'command-failed'))
79
+ .filter((name) => !name.endsWith('/HEAD'))
80
+ .map((name) => ({ name, remote: true, current: false }));
81
+ return [...local, ...remote];
82
+ }
83
+ function splitLines(stdout) {
84
+ return stdout
85
+ .split('\n')
86
+ .map((line) => line.trim())
87
+ .filter((line) => line !== '');
88
+ }
74
89
  function trackedStatus(code) {
75
90
  switch (code.charAt(0)) {
76
91
  case 'A':
@@ -1,9 +1,10 @@
1
1
  import { Context, Effect, Layer } from 'effect';
2
- import type { ChangeSet, FileDiff } from '../../change-set-schema/index.js';
2
+ import type { Branch, ChangeSet, FileDiff } from '../../change-set-schema/index.js';
3
3
  import { GitError } from './errors.js';
4
4
  declare const Git_base: Context.ServiceClass<Git, "Git", {
5
5
  readonly changeSet: (baseDir: string, baseRef: string) => Effect.Effect<ChangeSet, GitError>;
6
6
  readonly fileDiff: (baseDir: string, baseRef: string, path: string) => Effect.Effect<FileDiff, GitError>;
7
+ readonly branches: (baseDir: string) => Effect.Effect<readonly Branch[], GitError>;
7
8
  }>;
8
9
  export declare class Git extends Git_base {
9
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../../src/services/git/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEhD,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;;wBAKf,CAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC;uBACpB,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC;;AAX1C,qBAAa,GAAI,SAAQ,QAaf;CAAG;AAEb,eAAO,MAAM,OAAO,gCAclB,CAAC"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../../src/services/git/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEhD,OAAO,KAAK,EACV,MAAM,EACN,SAAS,EACT,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;;wBAKf,CAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC;uBACpB,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC;uBACnB,CACjB,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,QAAQ,CAAC;;AAdnD,qBAAa,GAAI,SAAQ,QAgBf;CAAG;AAEb,eAAO,MAAM,OAAO,gCAmBlB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { Context, Effect, Layer } from 'effect';
2
- import { readChangeSet, readFileDiff } from './changed-paths.js';
2
+ import { listBranches, readChangeSet, readFileDiff } from './changed-paths.js';
3
3
  import { GitError } from './errors.js';
4
4
  export class Git extends Context.Service()('Git') {
5
5
  }
@@ -15,6 +15,10 @@ export const GitLive = Layer.succeed(Git)({
15
15
  }),
16
16
  catch: (cause) => asGitError(cause, baseDir),
17
17
  }),
18
+ branches: (baseDir) => Effect.tryPromise({
19
+ try: () => listBranches(baseDir),
20
+ catch: (cause) => asGitError(cause, baseDir),
21
+ }),
18
22
  });
19
23
  function asGitError(cause, baseDir) {
20
24
  return cause instanceof GitError
@@ -120,16 +120,6 @@ export declare const QuestionSectionSchema: Schema.Union<readonly [Schema.Struct
120
120
  readonly destination: Schema.String;
121
121
  readonly messageId: Schema.String;
122
122
  readonly replyTo: Schema.optional<Schema.String>;
123
- }>, Schema.Struct<{
124
- readonly id: Schema.String;
125
- readonly participantName: Schema.String;
126
- readonly name: Schema.String;
127
- readonly timestamp: Schema.Number;
128
- readonly attributes: Schema.optional<Schema.$Record<Schema.String, Schema.Codec<import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, never, never>>>;
129
- readonly kind: Schema.Literal<"state">;
130
- readonly severity: Schema.Literals<readonly ["debug", "error", "info", "warning"]>;
131
- readonly state: Schema.$Record<Schema.String, Schema.Codec<import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, never, never>>;
132
- readonly merged: Schema.$Record<Schema.String, Schema.Codec<import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, never, never>>;
133
123
  }>]>>;
134
124
  readonly activations: Schema.$Array<Schema.Struct<{
135
125
  readonly participantName: Schema.String;
@@ -243,16 +233,6 @@ export declare const QuestionReportSchema: Schema.Struct<{
243
233
  readonly destination: Schema.String;
244
234
  readonly messageId: Schema.String;
245
235
  readonly replyTo: Schema.optional<Schema.String>;
246
- }>, Schema.Struct<{
247
- readonly id: Schema.String;
248
- readonly participantName: Schema.String;
249
- readonly name: Schema.String;
250
- readonly timestamp: Schema.Number;
251
- readonly attributes: Schema.optional<Schema.$Record<Schema.String, Schema.Codec<import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, never, never>>>;
252
- readonly kind: Schema.Literal<"state">;
253
- readonly severity: Schema.Literals<readonly ["debug", "error", "info", "warning"]>;
254
- readonly state: Schema.$Record<Schema.String, Schema.Codec<import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, never, never>>;
255
- readonly merged: Schema.$Record<Schema.String, Schema.Codec<import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, never, never>>;
256
236
  }>]>>;
257
237
  readonly activations: Schema.$Array<Schema.Struct<{
258
238
  readonly participantName: Schema.String;
@@ -369,16 +349,6 @@ export declare const StoryReportSchema: Schema.Struct<{
369
349
  readonly destination: Schema.String;
370
350
  readonly messageId: Schema.String;
371
351
  readonly replyTo: Schema.optional<Schema.String>;
372
- }>, Schema.Struct<{
373
- readonly id: Schema.String;
374
- readonly participantName: Schema.String;
375
- readonly name: Schema.String;
376
- readonly timestamp: Schema.Number;
377
- readonly attributes: Schema.optional<Schema.$Record<Schema.String, Schema.Codec<import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, never, never>>>;
378
- readonly kind: Schema.Literal<"state">;
379
- readonly severity: Schema.Literals<readonly ["debug", "error", "info", "warning"]>;
380
- readonly state: Schema.$Record<Schema.String, Schema.Codec<import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, never, never>>;
381
- readonly merged: Schema.$Record<Schema.String, Schema.Codec<import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, import("@pkishorez/effect-tracer/flow").RecordedFlowAttributeValue, never, never>>;
382
352
  }>]>>;
383
353
  readonly activations: Schema.$Array<Schema.Struct<{
384
354
  readonly participantName: Schema.String;
@@ -1 +1 @@
1
- {"version":3,"file":"story-report-schema.d.ts","sourceRoot":"","sources":["../../../src/story/schema/story-report-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAc9B,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,SAAS,EAAE,GACpB;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAqC1C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;EAQ9B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;EAO/B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAahC,CAAC;AAEH,eAAO,MAAM,kBAAkB,2DAI7B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW/B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQ5B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAC;AAC5D,MAAM,MAAM,YAAY,GAAG,OAAO,kBAAkB,CAAC,IAAI,CAAC;AAC1D,MAAM,MAAM,cAAc,GAAG,OAAO,oBAAoB,CAAC,IAAI,CAAC;AAC9D,MAAM,MAAM,eAAe,GAAG,OAAO,qBAAqB,CAAC,IAAI,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,OAAO,oBAAoB,CAAC,IAAI,CAAC;AAC9D,MAAM,MAAM,YAAY,GAAG,OAAO,kBAAkB,CAAC,IAAI,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC"}
1
+ {"version":3,"file":"story-report-schema.d.ts","sourceRoot":"","sources":["../../../src/story/schema/story-report-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAc9B,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,SAAS,EAAE,GACpB;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAqC1C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;EAQ9B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;EAO/B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAahC,CAAC;AAEH,eAAO,MAAM,kBAAkB,2DAI7B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW/B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQ5B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAC;AAC5D,MAAM,MAAM,YAAY,GAAG,OAAO,kBAAkB,CAAC,IAAI,CAAC;AAC1D,MAAM,MAAM,cAAc,GAAG,OAAO,oBAAoB,CAAC,IAAI,CAAC;AAC9D,MAAM,MAAM,eAAe,GAAG,OAAO,qBAAqB,CAAC,IAAI,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,OAAO,oBAAoB,CAAC,IAAI,CAAC;AAC9D,MAAM,MAAM,YAAY,GAAG,OAAO,kBAAkB,CAAC,IAAI,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC"}
@@ -1,4 +1,4 @@
1
- import { Context, Effect } from 'effect';
1
+ import { Context, Duration, Effect } from 'effect';
2
2
  import type { QuestionSection } from './schema/index.js';
3
3
  declare const StoryContext_base: Context.ServiceClass<StoryContext, "StoryContext", {
4
4
  readonly beginSection: (section: QuestionSection) => Effect.Effect<void>;
@@ -17,6 +17,8 @@ export interface Story {
17
17
  readonly spine: boolean;
18
18
  readonly sourceUrl: string;
19
19
  readonly questions: readonly StoryQuestion[];
20
+ /** How long this Story may run before it is failed; overrides the config-wide Story timeout. */
21
+ readonly timeout?: Duration.Input;
20
22
  }
21
23
  export interface StoryGroup {
22
24
  readonly title: string;
@@ -1 +1 @@
1
- {"version":3,"file":"story.d.ts","sourceRoot":"","sources":["../../src/story/story.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;;2BAK9B,CAAC,OAAO,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;qBACvD,CACf,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;AAP5B,qBAAa,YAAa,SAAQ,iBASf;CAAG;AAEtB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;CACzC;AAED,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,UAAU,CAAC;AAE3C,eAAO,MAAM,KAAK;IAChB,IAAI,QAAQ,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,KAAK;IAIvE,QAAQ,WACI,MAAM,WACP;QACP,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;KAC/D,GACA,aAAa;IAIhB,KAAK,QACI,MAAM,WACJ;QAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;KAAE,YAC/B,SAAS,SAAS,EAAE,GAC7B,UAAU;IAIb,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UACH,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC;IAcxC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UACF,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC;IAgBxC,MAAM,cACS,MAAM,UACX,OAAO,GACd,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC;CAK5C,CAAC;AAEF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAgBtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAWhE"}
1
+ {"version":3,"file":"story.d.ts","sourceRoot":"","sources":["../../src/story/story.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;;2BAK9B,CAAC,OAAO,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;qBACvD,CACf,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;AAP5B,qBAAa,YAAa,SAAQ,iBASf;CAAG;AAEtB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,gGAAgG;IAChG,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;CACnC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;CACzC;AAED,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,UAAU,CAAC;AAE3C,eAAO,MAAM,KAAK;IAChB,IAAI,QAAQ,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,KAAK;IAIvE,QAAQ,WACI,MAAM,WACP;QACP,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;KAC/D,GACA,aAAa;IAIhB,KAAK,QACI,MAAM,WACJ;QAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;KAAE,YAC/B,SAAS,SAAS,EAAE,GAC7B,UAAU;IAIb,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UACH,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC;IAcxC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UACF,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC;IAgBxC,MAAM,cACS,MAAM,UACX,OAAO,GACd,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC;CAK5C,CAAC;AAEF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAgBtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAWhE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "laymos",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "private": false,
5
5
  "description": "Enforces architectural dependency rules and explores source dependencies.",
6
6
  "repository": {
@@ -53,7 +53,7 @@
53
53
  "oxc-resolver": "11.24.2",
54
54
  "tsx": "4.23.12",
55
55
  "yoctocolors": "2.2.0",
56
- "@pkishorez/effect-tracer": "0.0.7"
56
+ "@pkishorez/effect-tracer": "0.0.8"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@types/node": "26.2.0",
package/schema.json CHANGED
@@ -43,6 +43,17 @@
43
43
  ],
44
44
  "description": "Canonical project-relative folder holding every Story file and the index.ts entry point exposing the Story Collection. Implicitly an Ignored path."
45
45
  },
46
+ "storyTimeout": {
47
+ "anyOf": [
48
+ {
49
+ "type": "string"
50
+ },
51
+ {
52
+ "type": "null"
53
+ }
54
+ ],
55
+ "description": "How long one Story may run before it is failed as timed out, as an Effect Duration string (e.g. \"10 seconds\"). Defaults to 10 seconds; a Story may override it with its own timeout."
56
+ },
46
57
  "layers": {
47
58
  "type": "object",
48
59
  "additionalProperties": {
@@ -71,6 +82,9 @@
71
82
  ],
72
83
  "description": "Human-readable summary of this Layer."
73
84
  },
85
+ "docsPath": {
86
+ "$ref": "#/definitions/Union_"
87
+ },
74
88
  "modules": {
75
89
  "type": "object",
76
90
  "additionalProperties": {
@@ -98,6 +112,9 @@
98
112
  "type": "string",
99
113
  "description": "Canonical project-relative directory rooting this Module Graph. Every member lives below it and every file below it must belong to a member."
100
114
  },
115
+ "docsPath": {
116
+ "$ref": "#/definitions/Union_"
117
+ },
101
118
  "modules": {
102
119
  "type": "object",
103
120
  "additionalProperties": {
@@ -162,6 +179,9 @@
162
179
  ],
163
180
  "description": "Human-readable summary of this LayerGraph."
164
181
  },
182
+ "docsPath": {
183
+ "$ref": "#/definitions/Union_"
184
+ },
165
185
  "rules": {
166
186
  "type": "object",
167
187
  "additionalProperties": {
@@ -192,6 +212,17 @@
192
212
  "title": "Laymos Config",
193
213
  "description": "Declares a project's Layers, their Modules and Module Graphs, and its LayerGraphs.",
194
214
  "definitions": {
215
+ "Union_": {
216
+ "anyOf": [
217
+ {
218
+ "type": "string"
219
+ },
220
+ {
221
+ "type": "null"
222
+ }
223
+ ],
224
+ "description": "Canonical project-relative path to a markdown file documenting this entity. Read-only: Laymos never writes to it."
225
+ },
195
226
  "Objects_": {
196
227
  "type": "object",
197
228
  "properties": {