laymos 0.0.8 → 0.0.10
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/README.md +259 -142
- package/dist/architecture-analysis-schema/module-source-schema.d.ts +4 -0
- package/dist/architecture-analysis-schema/module-source-schema.d.ts.map +1 -1
- package/dist/architecture-analysis-schema/module-source-schema.js +4 -0
- package/dist/change-set-schema/change-set-schema.js +2 -2
- package/dist/cli/run.d.ts +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +2 -0
- package/dist/cli/skills.d.ts +6 -0
- package/dist/cli/skills.d.ts.map +1 -0
- package/dist/cli/skills.js +9 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/orchestrator/load-changes/index.d.ts +1 -1
- package/dist/orchestrator/load-changes/index.d.ts.map +1 -1
- package/dist/orchestrator/load-changes/index.js +1 -1
- package/dist/orchestrator/load-changes/load-changes.d.ts +4 -3
- package/dist/orchestrator/load-changes/load-changes.d.ts.map +1 -1
- package/dist/orchestrator/load-changes/load-changes.js +14 -9
- package/dist/orchestrator/load-source-files/index.d.ts +1 -1
- package/dist/orchestrator/load-source-files/index.d.ts.map +1 -1
- package/dist/orchestrator/load-source-files/index.js +1 -1
- package/dist/orchestrator/load-source-files/load-source-files.d.ts +20 -4
- package/dist/orchestrator/load-source-files/load-source-files.d.ts.map +1 -1
- package/dist/orchestrator/load-source-files/load-source-files.js +46 -7
- package/dist/services/git/changed-paths.d.ts +1 -0
- package/dist/services/git/changed-paths.d.ts.map +1 -1
- package/dist/services/git/changed-paths.js +8 -0
- package/dist/services/git/git.d.ts +1 -0
- package/dist/services/git/git.d.ts.map +1 -1
- package/dist/services/git/git.js +5 -1
- package/dist/skills-command/index.d.ts +2 -0
- package/dist/skills-command/index.d.ts.map +1 -0
- package/dist/skills-command/index.js +1 -0
- package/dist/skills-command/skills-command.d.ts +21 -0
- package/dist/skills-command/skills-command.d.ts.map +1 -0
- package/dist/skills-command/skills-command.js +64 -0
- package/dist/story/schema/index.d.ts +2 -2
- package/dist/story/schema/index.d.ts.map +1 -1
- package/dist/story/schema/index.js +1 -1
- package/dist/story/schema/story-report-schema.d.ts +264 -132
- package/dist/story/schema/story-report-schema.d.ts.map +1 -1
- package/dist/story/schema/story-report-schema.js +4 -4
- package/dist/story/story.d.ts +3 -1
- package/dist/story/story.d.ts.map +1 -1
- package/dist/story/story.js +4 -5
- package/package.json +18 -11
- package/schema.json +60 -55
- package/skills/deep-module/SKILL.md +55 -0
- package/skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/skills/domain-modeling/SKILL.md +74 -0
- package/skills/domain-modeling/agents/openai.yaml +3 -0
- package/skills/laymos/SKILL.md +130 -0
- package/skills/laymos/references/config.md +96 -0
- package/skills/laymos/references/design.md +166 -0
- package/skills/laymos/references/graphs.md +85 -0
- package/skills/laymos/references/visibility.md +60 -0
- package/skills/to-laymos/SKILL.md +60 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-changes.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-changes/load-changes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EACV,MAAM,EACN,SAAS,EACT,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"load-changes.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-changes/load-changes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EACV,MAAM,EACN,SAAS,EACT,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAI1E,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,OAAO,SAAS,GACf,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAKpC;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,SAAS,GACf,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAKnC;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,QAAQ,CAAC,CAK5C;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,QAAQ,CAAC,CAK5C"}
|
|
@@ -1,24 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
2
|
import { Effect } from 'effect';
|
|
3
3
|
import { Git, GitLive } from '../../services/git/index.js';
|
|
4
|
-
|
|
4
|
+
// Each loader works on any folder inside a git repository; paths are relative
|
|
5
|
+
// to that folder.
|
|
6
|
+
export function loadChangeSet(folder, baseRef = 'HEAD') {
|
|
5
7
|
return Effect.gen(function* () {
|
|
6
8
|
const git = yield* Git;
|
|
7
|
-
return yield* git.changeSet(
|
|
9
|
+
return yield* git.changeSet(resolve(folder), baseRef);
|
|
8
10
|
}).pipe(Effect.provide(GitLive));
|
|
9
11
|
}
|
|
10
|
-
export function loadFileDiff(
|
|
12
|
+
export function loadFileDiff(folder, path, baseRef = 'HEAD') {
|
|
11
13
|
return Effect.gen(function* () {
|
|
12
14
|
const git = yield* Git;
|
|
13
|
-
return yield* git.fileDiff(
|
|
15
|
+
return yield* git.fileDiff(resolve(folder), baseRef, path);
|
|
14
16
|
}).pipe(Effect.provide(GitLive));
|
|
15
17
|
}
|
|
16
|
-
export function loadBranches(
|
|
18
|
+
export function loadBranches(folder) {
|
|
17
19
|
return Effect.gen(function* () {
|
|
18
20
|
const git = yield* Git;
|
|
19
|
-
return yield* git.branches(
|
|
21
|
+
return yield* git.branches(resolve(folder));
|
|
20
22
|
}).pipe(Effect.provide(GitLive));
|
|
21
23
|
}
|
|
22
|
-
function
|
|
23
|
-
return
|
|
24
|
+
export function loadKnownFiles(folder) {
|
|
25
|
+
return Effect.gen(function* () {
|
|
26
|
+
const git = yield* Git;
|
|
27
|
+
return yield* git.knownFiles(resolve(folder));
|
|
28
|
+
}).pipe(Effect.provide(GitLive));
|
|
24
29
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { loadSourceFiles, SourceFileReadError } from './load-source-files.js';
|
|
1
|
+
export { loadFolderFiles, loadSourceFiles, SourceFileReadError, } from './load-source-files.js';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-source-files/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-source-files/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,eAAe,EACf,mBAAmB,GACpB,MAAM,wBAAwB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { loadSourceFiles, SourceFileReadError } from './load-source-files.js';
|
|
1
|
+
export { loadFolderFiles, loadSourceFiles, SourceFileReadError, } from './load-source-files.js';
|
|
@@ -2,15 +2,31 @@ import { Effect } from 'effect';
|
|
|
2
2
|
import { SourceFileReadError } from './errors.js';
|
|
3
3
|
export { SourceFileReadError } from './errors.js';
|
|
4
4
|
/**
|
|
5
|
-
* Reads every
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Reads every file at or below one of the given project-relative path
|
|
6
|
+
* prefixes — a Configured Module's, Module Graph's, or Layer scope's own root.
|
|
7
|
+
* Files git knows beside the analyzed ones are read too, marked as Unanalyzed
|
|
8
|
+
* files; without git, only analyzed files are read. Only paths inside the Project are ever listed, so a caller can never
|
|
9
|
+
* use this to read a file outside it.
|
|
9
10
|
*/
|
|
10
11
|
export declare function loadSourceFiles(configPath: string, pathPrefixes: readonly string[]): Effect.Effect<{
|
|
11
12
|
files: {
|
|
12
13
|
readonly path: string;
|
|
13
14
|
readonly content: string;
|
|
15
|
+
readonly binary?: boolean | undefined;
|
|
16
|
+
readonly unanalyzed?: boolean | undefined;
|
|
14
17
|
}[];
|
|
15
18
|
}, import("../../services/config/errors.js").ConfigError | import("../../services/file-cruiser/errors.js").CruiseError | SourceFileReadError, never>;
|
|
19
|
+
/**
|
|
20
|
+
* Reads every file git knows at or below one of the given paths of a folder,
|
|
21
|
+
* such as a Package's files within its Monorepo. Paths are relative to the
|
|
22
|
+
* folder, and only paths inside it are ever listed.
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadFolderFiles(folder: string, pathPrefixes: readonly string[]): Effect.Effect<{
|
|
25
|
+
files: {
|
|
26
|
+
readonly path: string;
|
|
27
|
+
readonly content: string;
|
|
28
|
+
readonly binary?: boolean | undefined;
|
|
29
|
+
readonly unanalyzed?: boolean | undefined;
|
|
30
|
+
}[];
|
|
31
|
+
}, import("../../services/git/errors.js").GitError | SourceFileReadError, never>;
|
|
16
32
|
//# sourceMappingURL=load-source-files.d.ts.map
|
|
@@ -1 +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;
|
|
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;AAO5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAKlD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,SAAS,MAAM,EAAE;;;;;;;qJAuBhC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,SAAS,MAAM,EAAE;;;;;;;iFAUhC"}
|
|
@@ -3,28 +3,67 @@ import { NodeServices } from '@effect/platform-node';
|
|
|
3
3
|
import { Effect, FileSystem } from 'effect';
|
|
4
4
|
import { ConfigServiceLive } from '../../services/config/index.js';
|
|
5
5
|
import { CruiserLive } from '../../services/file-cruiser/index.js';
|
|
6
|
+
import { Git, GitLive } from '../../services/git/index.js';
|
|
6
7
|
import { loadProject } from '../load-project/index.js';
|
|
7
8
|
import { SourceFileReadError } from './errors.js';
|
|
8
9
|
export { SourceFileReadError } from './errors.js';
|
|
10
|
+
// Git's own test for binary content: a NUL byte near the start.
|
|
11
|
+
const binarySniffLength = 8000;
|
|
9
12
|
/**
|
|
10
|
-
* Reads every
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* Reads every file at or below one of the given project-relative path
|
|
14
|
+
* prefixes — a Configured Module's, Module Graph's, or Layer scope's own root.
|
|
15
|
+
* Files git knows beside the analyzed ones are read too, marked as Unanalyzed
|
|
16
|
+
* files; without git, only analyzed files are read. Only paths inside the Project are ever listed, so a caller can never
|
|
17
|
+
* use this to read a file outside it.
|
|
14
18
|
*/
|
|
15
19
|
export function loadSourceFiles(configPath, pathPrefixes) {
|
|
16
20
|
const absoluteConfigPath = resolve(configPath);
|
|
17
21
|
const baseDir = dirname(absoluteConfigPath);
|
|
18
22
|
return Effect.gen(function* () {
|
|
19
23
|
const { fileGraph } = yield* loadProject(absoluteConfigPath);
|
|
20
|
-
const
|
|
24
|
+
const known = yield* knownFiles(baseDir).pipe(Effect.orElseSucceed(() => []));
|
|
25
|
+
const paths = [...new Set([...fileGraph.keys(), ...known])]
|
|
21
26
|
.filter((path) => underAnyPrefix(path, pathPrefixes))
|
|
22
27
|
.sort((left, right) => left.localeCompare(right));
|
|
23
|
-
const
|
|
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 }))));
|
|
28
|
+
const files = yield* readFiles(baseDir, paths, (path) => fileGraph.has(path));
|
|
25
29
|
return { files };
|
|
26
30
|
}).pipe(Effect.provide(ConfigServiceLive), Effect.provide(CruiserLive), Effect.provide(NodeServices.layer));
|
|
27
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Reads every file git knows at or below one of the given paths of a folder,
|
|
34
|
+
* such as a Package's files within its Monorepo. Paths are relative to the
|
|
35
|
+
* folder, and only paths inside it are ever listed.
|
|
36
|
+
*/
|
|
37
|
+
export function loadFolderFiles(folder, pathPrefixes) {
|
|
38
|
+
const baseDir = resolve(folder);
|
|
39
|
+
return Effect.gen(function* () {
|
|
40
|
+
const paths = (yield* knownFiles(baseDir)).filter((path) => underAnyPrefix(path, pathPrefixes));
|
|
41
|
+
const files = yield* readFiles(baseDir, paths, () => true);
|
|
42
|
+
return { files };
|
|
43
|
+
}).pipe(Effect.provide(NodeServices.layer));
|
|
44
|
+
}
|
|
45
|
+
function knownFiles(baseDir) {
|
|
46
|
+
return Effect.gen(function* () {
|
|
47
|
+
const git = yield* Git;
|
|
48
|
+
return yield* git.knownFiles(baseDir);
|
|
49
|
+
}).pipe(Effect.provide(GitLive));
|
|
50
|
+
}
|
|
51
|
+
function readFiles(baseDir, paths, isAnalyzed) {
|
|
52
|
+
return Effect.gen(function* () {
|
|
53
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
54
|
+
const files = yield* Effect.forEach(paths, (path) => fileSystem.readFile(resolve(baseDir, path)).pipe(Effect.map((bytes) => sourceFile(path, bytes, isAnalyzed(path))), Effect.mapError((cause) => new SourceFileReadError({ filePath: path, cause }))));
|
|
55
|
+
return files;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function sourceFile(path, bytes, analyzed) {
|
|
59
|
+
const binary = bytes.subarray(0, binarySniffLength).includes(0);
|
|
60
|
+
return {
|
|
61
|
+
path,
|
|
62
|
+
content: binary ? '' : new TextDecoder().decode(bytes),
|
|
63
|
+
...(binary ? { binary } : {}),
|
|
64
|
+
...(analyzed ? {} : { unanalyzed: true }),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
28
67
|
function underAnyPrefix(path, pathPrefixes) {
|
|
29
68
|
return pathPrefixes.some((prefix) => prefix === '.' || path === prefix || path.startsWith(`${prefix}/`));
|
|
30
69
|
}
|
|
@@ -2,4 +2,5 @@ import type { Branch, ChangeSet, DiffHunk } from '../../change-set-schema/index.
|
|
|
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
4
|
export declare function listBranches(baseDir: string): Promise<Branch[]>;
|
|
5
|
+
export declare function listKnownFiles(baseDir: string): Promise<string[]>;
|
|
5
6
|
//# 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,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
|
+
{"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;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBvE"}
|
|
@@ -80,6 +80,14 @@ export async function listBranches(baseDir) {
|
|
|
80
80
|
.map((name) => ({ name, remote: true, current: false }));
|
|
81
81
|
return [...local, ...remote];
|
|
82
82
|
}
|
|
83
|
+
export async function listKnownFiles(baseDir) {
|
|
84
|
+
await requireGit(baseDir, ['rev-parse', '--show-toplevel'], 'not-a-repo');
|
|
85
|
+
const known = splitNul(await requireGit(baseDir, ['ls-files', '--cached', '--others', '--exclude-standard', '-z'], 'command-failed'));
|
|
86
|
+
const deleted = new Set(splitNul(await requireGit(baseDir, ['ls-files', '--deleted', '-z'], 'command-failed')));
|
|
87
|
+
return [...new Set(known)]
|
|
88
|
+
.filter((path) => !deleted.has(path))
|
|
89
|
+
.sort((left, right) => left.localeCompare(right));
|
|
90
|
+
}
|
|
83
91
|
function splitLines(stdout) {
|
|
84
92
|
return stdout
|
|
85
93
|
.split('\n')
|
|
@@ -5,6 +5,7 @@ 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
7
|
readonly branches: (baseDir: string) => Effect.Effect<readonly Branch[], GitError>;
|
|
8
|
+
readonly knownFiles: (baseDir: string) => Effect.Effect<readonly string[], GitError>;
|
|
8
9
|
}>;
|
|
9
10
|
export declare class Git extends Git_base {
|
|
10
11
|
}
|
|
@@ -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,EACV,MAAM,EACN,SAAS,EACT,QAAQ,EACT,MAAM,kCAAkC,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;AAO1C,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;yBAG1B,CACnB,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,QAAQ,CAAC;;AAnBnD,qBAAa,GAAI,SAAQ,QAqBf;CAAG;AAEb,eAAO,MAAM,OAAO,gCAwBlB,CAAC"}
|
package/dist/services/git/git.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from 'effect';
|
|
2
|
-
import { listBranches, readChangeSet, readFileDiff } from './changed-paths.js';
|
|
2
|
+
import { listBranches, listKnownFiles, readChangeSet, readFileDiff, } from './changed-paths.js';
|
|
3
3
|
import { GitError } from './errors.js';
|
|
4
4
|
export class Git extends Context.Service()('Git') {
|
|
5
5
|
}
|
|
@@ -19,6 +19,10 @@ export const GitLive = Layer.succeed(Git)({
|
|
|
19
19
|
try: () => listBranches(baseDir),
|
|
20
20
|
catch: (cause) => asGitError(cause, baseDir),
|
|
21
21
|
}),
|
|
22
|
+
knownFiles: (baseDir) => Effect.tryPromise({
|
|
23
|
+
try: () => listKnownFiles(baseDir),
|
|
24
|
+
catch: (cause) => asGitError(cause, baseDir),
|
|
25
|
+
}),
|
|
22
26
|
});
|
|
23
27
|
function asGitError(cause, baseDir) {
|
|
24
28
|
return cause instanceof GitError
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/skills-command/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { makeSkillsCommand, } from './skills-command.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { FileSystem } from 'effect';
|
|
2
|
+
import { Command } from 'effect/unstable/cli';
|
|
3
|
+
export type SkillsCommandOptions = {
|
|
4
|
+
/** Folder holding one sub-folder per skill, each with a `SKILL.md`. */
|
|
5
|
+
readonly skillsRoot: string;
|
|
6
|
+
/** Skill folder names in listing order. */
|
|
7
|
+
readonly names: ReadonlyArray<string>;
|
|
8
|
+
/** The CLI's own name, used in help text. */
|
|
9
|
+
readonly cliName: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Builds a `skills` subcommand: `skills` lists, `skills <name>` prints one
|
|
13
|
+
* SKILL.md, and `--install <dir>` copies one or every skill folder into
|
|
14
|
+
* `<dir>/<name>/`, overwriting what is there.
|
|
15
|
+
*/
|
|
16
|
+
export declare const makeSkillsCommand: ({ skillsRoot, names, cliName, }: SkillsCommandOptions) => Command.Command<"skills", {
|
|
17
|
+
readonly name: import("effect/Option").Option<string>;
|
|
18
|
+
readonly install: import("effect/Option").Option<string>;
|
|
19
|
+
readonly format: "json" | "text";
|
|
20
|
+
}, {}, import("effect/PlatformError").PlatformError, FileSystem.FileSystem>;
|
|
21
|
+
//# sourceMappingURL=skills-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-command.d.ts","sourceRoot":"","sources":["../../src/skills-command/skills-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,UAAU,EAAE,MAAM,QAAQ,CAAC;AACrD,OAAO,EAAY,OAAO,EAAQ,MAAM,qBAAqB,CAAC;AAE9D,MAAM,MAAM,oBAAoB,GAAG;IACjC,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAoCF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,oCAI3B,oBAAoB;;;;2EAwEtB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { Console, Effect, FileSystem } from 'effect';
|
|
3
|
+
import { Argument, Command, Flag } from 'effect/unstable/cli';
|
|
4
|
+
const descriptionOf = (markdown) => /^description:\s*(.+)$/m.exec(markdown)?.[1]?.trim() ?? '';
|
|
5
|
+
const renderList = (skills) => skills.map((skill) => `${skill.name} ${skill.description}`).join('\n');
|
|
6
|
+
const fail = (message) => Console.error(message).pipe(Effect.andThen(Effect.sync(() => {
|
|
7
|
+
process.exitCode = 1;
|
|
8
|
+
})));
|
|
9
|
+
const nameArgument = Argument.string('name').pipe(Argument.withDescription('Skill to print or install; omit for all skills'), Argument.optional);
|
|
10
|
+
const installFlag = Flag.directory('install', { mustExist: false }).pipe(Flag.withDescription('Copy the skill folder(s) into <dir>/<name>/ instead of printing'), Flag.optional);
|
|
11
|
+
const formatFlag = Flag.choice('format', ['json', 'text']).pipe(Flag.withDescription('List skills as readable text or JSON'), Flag.withDefault('text'));
|
|
12
|
+
/**
|
|
13
|
+
* Builds a `skills` subcommand: `skills` lists, `skills <name>` prints one
|
|
14
|
+
* SKILL.md, and `--install <dir>` copies one or every skill folder into
|
|
15
|
+
* `<dir>/<name>/`, overwriting what is there.
|
|
16
|
+
*/
|
|
17
|
+
export const makeSkillsCommand = ({ skillsRoot, names, cliName, }) => {
|
|
18
|
+
const skillDir = (name) => path.join(skillsRoot, name);
|
|
19
|
+
const summarize = (name) => Effect.gen(function* () {
|
|
20
|
+
const fs = yield* FileSystem.FileSystem;
|
|
21
|
+
const markdown = yield* fs.readFileString(path.join(skillDir(name), 'SKILL.md'));
|
|
22
|
+
return { name, description: descriptionOf(markdown), markdown };
|
|
23
|
+
});
|
|
24
|
+
const printSkill = (name) => Effect.gen(function* () {
|
|
25
|
+
const fs = yield* FileSystem.FileSystem;
|
|
26
|
+
const { markdown } = yield* summarize(name);
|
|
27
|
+
yield* Console.log(markdown.trimEnd());
|
|
28
|
+
const files = yield* fs.readDirectory(skillDir(name), {
|
|
29
|
+
recursive: true,
|
|
30
|
+
});
|
|
31
|
+
const extra = files.filter((file) => file !== 'SKILL.md').length;
|
|
32
|
+
if (extra > 0) {
|
|
33
|
+
yield* Console.error(`Note: ${name} ships ${extra} more file(s). Use --install <dir> to get all of them.`);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const installSkills = (selected, directory) => Effect.gen(function* () {
|
|
37
|
+
const fs = yield* FileSystem.FileSystem;
|
|
38
|
+
const root = path.resolve(directory);
|
|
39
|
+
yield* fs.makeDirectory(root, { recursive: true });
|
|
40
|
+
for (const name of selected) {
|
|
41
|
+
const target = path.join(root, name);
|
|
42
|
+
yield* fs.copy(skillDir(name), target, { overwrite: true });
|
|
43
|
+
yield* Console.log(`Installed skill ${name} at ${target}`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return Command.make('skills', { name: nameArgument, install: installFlag, format: formatFlag }, ({ name, install, format }) => Effect.gen(function* () {
|
|
47
|
+
if (name._tag === 'Some' && !names.includes(name.value)) {
|
|
48
|
+
return yield* fail(`Unknown skill: ${name.value}. Available: ${names.join(', ')}`);
|
|
49
|
+
}
|
|
50
|
+
const selected = name._tag === 'Some' ? [name.value] : names;
|
|
51
|
+
if (install._tag === 'Some') {
|
|
52
|
+
return yield* installSkills(selected, install.value);
|
|
53
|
+
}
|
|
54
|
+
if (name._tag === 'Some')
|
|
55
|
+
return yield* printSkill(name.value);
|
|
56
|
+
const skills = yield* Effect.forEach(names, (skill) => Effect.map(summarize(skill), ({ name, description }) => ({
|
|
57
|
+
name,
|
|
58
|
+
description,
|
|
59
|
+
})));
|
|
60
|
+
yield* Console.log(format === 'json'
|
|
61
|
+
? JSON.stringify(skills, null, 2)
|
|
62
|
+
: renderList(skills));
|
|
63
|
+
})).pipe(Command.withDescription(`List the agent skills shipped with ${cliName}, print one, or install them into a skills folder`));
|
|
64
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { CapturedTraceSchema, QuestionReportSchema, QuestionSectionSchema,
|
|
2
|
-
export type { CapturedTrace, JsonValue, QuestionReport, QuestionSection,
|
|
1
|
+
export { CapturedTraceSchema, QuestionReportSchema, QuestionSectionSchema, JournalSchema, StoryAssertionSchema, StoryReportSchema, StoryVerdictSchema, } from './story-report-schema.js';
|
|
2
|
+
export type { CapturedTrace, JsonValue, QuestionReport, QuestionSection, Journal, StoryAssertion, StoryReport, StoryVerdict, } from './story-report-schema.js';
|
|
3
3
|
export { slugifyQuestion } from './slug.js';
|
|
4
4
|
export { QuestionLeafSchema, StoryLeafSchema, StoryPageSchema, StorySourceSchema, StoryTreeGroupSchema, StoryTreeSchema, } from './story-tree-schema.js';
|
|
5
5
|
export type { QuestionLeaf, StoryLeaf, StoryPage, StorySource, StoryTree, StoryTreeGroup, } from './story-tree-schema.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/story/schema/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/story/schema/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,aAAa,EACb,SAAS,EACT,cAAc,EACd,eAAe,EACf,OAAO,EACP,cAAc,EACd,WAAW,EACX,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,cAAc,GACf,MAAM,wBAAwB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// RPC transports and renderers use this browser-safe Story report contract.
|
|
2
|
-
export { CapturedTraceSchema, QuestionReportSchema, QuestionSectionSchema,
|
|
2
|
+
export { CapturedTraceSchema, QuestionReportSchema, QuestionSectionSchema, JournalSchema, StoryAssertionSchema, StoryReportSchema, StoryVerdictSchema, } from './story-report-schema.js';
|
|
3
3
|
export { slugifyQuestion } from './slug.js';
|
|
4
4
|
export { QuestionLeafSchema, StoryLeafSchema, StoryPageSchema, StorySourceSchema, StoryTreeGroupSchema, StoryTreeSchema, } from './story-tree-schema.js';
|