yet-another-agentic-workflow 0.2.0
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 +125 -0
- package/dist/adapters.d.ts +43 -0
- package/dist/adapters.js +191 -0
- package/dist/adapters.js.map +1 -0
- package/dist/architect.d.ts +38 -0
- package/dist/architect.js +275 -0
- package/dist/architect.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +580 -0
- package/dist/cli.js.map +1 -0
- package/dist/feature.d.ts +30 -0
- package/dist/feature.js +344 -0
- package/dist/feature.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +26 -0
- package/dist/init.js +255 -0
- package/dist/init.js.map +1 -0
- package/dist/installer.d.ts +64 -0
- package/dist/installer.js +365 -0
- package/dist/installer.js.map +1 -0
- package/dist/observability.d.ts +37 -0
- package/dist/observability.js +200 -0
- package/dist/observability.js.map +1 -0
- package/dist/parser.d.ts +6 -0
- package/dist/parser.js +166 -0
- package/dist/parser.js.map +1 -0
- package/dist/persistence.d.ts +83 -0
- package/dist/persistence.js +279 -0
- package/dist/persistence.js.map +1 -0
- package/dist/providers.d.ts +14 -0
- package/dist/providers.js +27 -0
- package/dist/providers.js.map +1 -0
- package/dist/review.d.ts +29 -0
- package/dist/review.js +66 -0
- package/dist/review.js.map +1 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.js +44 -0
- package/dist/schema.js.map +1 -0
- package/dist/skills.d.ts +24 -0
- package/dist/skills.js +210 -0
- package/dist/skills.js.map +1 -0
- package/dist/types.d.ts +86 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +48 -0
- package/schemas/agent.schema.json +37 -0
- package/schemas/context.schema.json +13 -0
- package/schemas/eval.schema.json +26 -0
- package/schemas/hook.schema.json +29 -0
- package/schemas/skill.schema.json +23 -0
- package/schemas/state.schema.json +14 -0
- package/schemas/workflow.schema.json +34 -0
- package/schemas/yaaw.schema.json +58 -0
- package/skills/clarify/SKILL.md +14 -0
- package/skills/code-review/SKILL.md +29 -0
- package/skills/slice-work/SKILL.md +15 -0
- package/skills/spec/SKILL.md +21 -0
- package/skills/tdd/SKILL.md +25 -0
- package/templates/instructions/managed-block.md +17 -0
package/dist/review.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export class ReviewError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "ReviewError";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
/** Validate one axis-scoped report without consulting the other reviewer. */
|
|
11
|
+
export function createReviewRecord(axis, value, recordedAt = new Date().toISOString()) {
|
|
12
|
+
if (!isRecord(value))
|
|
13
|
+
throw new ReviewError(`${axis} review must be a JSON object`);
|
|
14
|
+
if (value.axis !== undefined && value.axis !== axis) {
|
|
15
|
+
throw new ReviewError(`${axis} reviewer cannot submit a '${String(value.axis)}' axis report`);
|
|
16
|
+
}
|
|
17
|
+
if (value.verdict !== "PASS" && value.verdict !== "FAIL") {
|
|
18
|
+
throw new ReviewError(`${axis} review verdict must be PASS or FAIL`);
|
|
19
|
+
}
|
|
20
|
+
if (typeof value.summary !== "string" || !value.summary.trim()) {
|
|
21
|
+
throw new ReviewError(`${axis} review summary must be a non-empty string`);
|
|
22
|
+
}
|
|
23
|
+
if (!Array.isArray(value.findings)) {
|
|
24
|
+
throw new ReviewError(`${axis} review findings must be an array`);
|
|
25
|
+
}
|
|
26
|
+
const findings = value.findings.map((finding, index) => {
|
|
27
|
+
if (!isRecord(finding))
|
|
28
|
+
throw new ReviewError(`${axis} review finding ${index + 1} must be an object`);
|
|
29
|
+
for (const field of ["code", "message", "evidence"]) {
|
|
30
|
+
if (typeof finding[field] !== "string" || !finding[field].trim()) {
|
|
31
|
+
throw new ReviewError(`${axis} review finding ${index + 1}.${field} must be a non-empty string`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return { code: finding.code, message: finding.message, evidence: finding.evidence };
|
|
35
|
+
});
|
|
36
|
+
if (value.verdict === "PASS" && findings.length > 0) {
|
|
37
|
+
throw new ReviewError(`${axis} review cannot PASS with findings`);
|
|
38
|
+
}
|
|
39
|
+
if (value.verdict === "FAIL" && findings.length === 0) {
|
|
40
|
+
throw new ReviewError(`${axis} review cannot FAIL without a finding`);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
axis,
|
|
44
|
+
reviewer: axis === "spec" ? "spec-reviewer" : "standards-reviewer",
|
|
45
|
+
verdict: value.verdict,
|
|
46
|
+
summary: value.summary.trim(),
|
|
47
|
+
findings,
|
|
48
|
+
recordedAt
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** Enforce the join gate and preserve axis-specific failure reasons. */
|
|
52
|
+
export function assertIndependentReviewGate(reviews) {
|
|
53
|
+
if (!reviews.spec)
|
|
54
|
+
throw new ReviewError("completion blocked: spec review is missing");
|
|
55
|
+
if (!reviews.standards)
|
|
56
|
+
throw new ReviewError("completion blocked: standards review is missing");
|
|
57
|
+
if (reviews.spec.verdict === "FAIL") {
|
|
58
|
+
const codes = reviews.spec.findings.map(({ code }) => code).join(", ");
|
|
59
|
+
throw new ReviewError(`completion blocked: spec review failed (${codes})`);
|
|
60
|
+
}
|
|
61
|
+
if (reviews.standards.verdict === "FAIL") {
|
|
62
|
+
const codes = reviews.standards.findings.map(({ code }) => code).join(", ");
|
|
63
|
+
throw new ReviewError(`completion blocked: standards review failed (${codes})`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
ADDED
package/dist/schema.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
5
|
+
const schemaDirectory = fileURLToPath(new URL("../schemas/", import.meta.url));
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const addFormats = require("ajv-formats");
|
|
8
|
+
const schemaFiles = [
|
|
9
|
+
"skill.schema.json",
|
|
10
|
+
"agent.schema.json",
|
|
11
|
+
"hook.schema.json",
|
|
12
|
+
"eval.schema.json",
|
|
13
|
+
"workflow.schema.json",
|
|
14
|
+
"context.schema.json",
|
|
15
|
+
"state.schema.json",
|
|
16
|
+
"yaaw.schema.json"
|
|
17
|
+
];
|
|
18
|
+
function readSchema(fileName) {
|
|
19
|
+
return JSON.parse(readFileSync(`${schemaDirectory}${fileName}`, "utf8"));
|
|
20
|
+
}
|
|
21
|
+
const ajv = new Ajv2020({ allErrors: true, strict: true });
|
|
22
|
+
addFormats(ajv);
|
|
23
|
+
for (const fileName of schemaFiles) {
|
|
24
|
+
ajv.addSchema(readSchema(fileName));
|
|
25
|
+
}
|
|
26
|
+
const registeredSchema = ajv.getSchema("https://yaaw.dev/schemas/yaaw.schema.json");
|
|
27
|
+
if (!registeredSchema) {
|
|
28
|
+
throw new Error("The root YAAW schema was not registered.");
|
|
29
|
+
}
|
|
30
|
+
const validateSchema = registeredSchema;
|
|
31
|
+
function schemaPath(error) {
|
|
32
|
+
return error.instancePath === "" ? "$" : `$${error.instancePath}`;
|
|
33
|
+
}
|
|
34
|
+
export function validateAgainstSchema(value) {
|
|
35
|
+
if (validateSchema(value)) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return (validateSchema.errors ?? []).map((error) => ({
|
|
39
|
+
path: schemaPath(error),
|
|
40
|
+
message: error.message ?? "failed schema validation",
|
|
41
|
+
keyword: "schema"
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAoB,MAAM,kBAAkB,CAAC;AAK7D,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/E,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAkB,CAAC;AAE3D,MAAM,WAAW,GAAG;IAClB,mBAAmB;IACnB,mBAAmB;IACnB,kBAAkB;IAClB,kBAAkB;IAClB,sBAAsB;IACtB,qBAAqB;IACrB,mBAAmB;IACnB,kBAAkB;CACV,CAAC;AAEX,SAAS,UAAU,CAAC,QAAsC;IACxD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,eAAe,GAAG,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAW,CAAC;AACrF,CAAC;AAED,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3D,UAAU,CAAC,GAAG,CAAC,CAAC;AAEhB,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;IACnC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,gBAAgB,GAAG,GAAG,CAAC,SAAS,CACpC,2CAA2C,CAC5C,CAAC;AAEF,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACtB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAExC,SAAS,UAAU,CAAC,KAAkB;IACpC,OAAO,KAAK,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,CAAC,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAkB,EAAE,EAAE,CAAC,CAAC;QAChE,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC;QACvB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,0BAA0B;QACpD,OAAO,EAAE,QAAQ;KAClB,CAAC,CAAC,CAAC;AACN,CAAC"}
|
package/dist/skills.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface SkillSummary {
|
|
2
|
+
name: string;
|
|
3
|
+
purpose: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
dependencies: string[];
|
|
6
|
+
path: string;
|
|
7
|
+
}
|
|
8
|
+
export interface LoadedSkill extends SkillSummary {
|
|
9
|
+
instructions: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SkillInvocation {
|
|
12
|
+
requested: string;
|
|
13
|
+
order: string[];
|
|
14
|
+
skills: LoadedSkill[];
|
|
15
|
+
prompt: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class SkillSystemError extends Error {
|
|
18
|
+
constructor(message: string);
|
|
19
|
+
}
|
|
20
|
+
/** Discover skill metadata without retaining or returning instruction bodies. */
|
|
21
|
+
export declare function discoverSkills(projectDirectory?: string): Promise<SkillSummary[]>;
|
|
22
|
+
/** Load one skill and its dependencies in dependency-first order. */
|
|
23
|
+
export declare function invokeSkill(name: string, projectDirectory?: string): Promise<SkillInvocation>;
|
|
24
|
+
export declare function displaySkillPath(summary: SkillSummary, projectDirectory?: string): string;
|
package/dist/skills.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { createReadStream } from "node:fs";
|
|
2
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
3
|
+
import { basename, join, resolve } from "node:path";
|
|
4
|
+
import { createInterface } from "node:readline";
|
|
5
|
+
import { parse as parseYaml } from "yaml";
|
|
6
|
+
const SKILL_NAME = /^[a-z][a-z0-9-]*$/;
|
|
7
|
+
export class SkillSystemError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "SkillSystemError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function parseMetadata(source, path) {
|
|
14
|
+
let value;
|
|
15
|
+
try {
|
|
16
|
+
value = parseYaml(source);
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
throw new SkillSystemError(`${path}: invalid YAML frontmatter: ${error instanceof Error ? error.message : String(error)}`);
|
|
20
|
+
}
|
|
21
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
22
|
+
throw new SkillSystemError(`${path}: skill frontmatter must be an object`);
|
|
23
|
+
}
|
|
24
|
+
const metadata = value;
|
|
25
|
+
const allowed = new Set(["name", "purpose", "description", "dependencies"]);
|
|
26
|
+
const extra = Object.keys(metadata).find((key) => !allowed.has(key));
|
|
27
|
+
if (extra)
|
|
28
|
+
throw new SkillSystemError(`${path}: unknown skill metadata field '${extra}'`);
|
|
29
|
+
if (typeof metadata.name !== "string" || !SKILL_NAME.test(metadata.name)) {
|
|
30
|
+
throw new SkillSystemError(`${path}: skill name must match ${SKILL_NAME.source}`);
|
|
31
|
+
}
|
|
32
|
+
if (typeof metadata.purpose !== "string" || metadata.purpose.trim().length === 0) {
|
|
33
|
+
throw new SkillSystemError(`${path}: skill purpose must be a non-empty string`);
|
|
34
|
+
}
|
|
35
|
+
if (metadata.description !== undefined &&
|
|
36
|
+
(typeof metadata.description !== "string" || metadata.description.trim().length === 0)) {
|
|
37
|
+
throw new SkillSystemError(`${path}: skill description must be a non-empty string`);
|
|
38
|
+
}
|
|
39
|
+
const rawDependencies = metadata.dependencies ?? [];
|
|
40
|
+
if (!Array.isArray(rawDependencies) ||
|
|
41
|
+
rawDependencies.some((dependency) => typeof dependency !== "string" || !SKILL_NAME.test(dependency))) {
|
|
42
|
+
throw new SkillSystemError(`${path}: skill dependencies must be unique valid skill names`);
|
|
43
|
+
}
|
|
44
|
+
const dependencies = rawDependencies;
|
|
45
|
+
if (new Set(dependencies).size !== dependencies.length) {
|
|
46
|
+
throw new SkillSystemError(`${path}: skill dependencies must be unique valid skill names`);
|
|
47
|
+
}
|
|
48
|
+
const result = {
|
|
49
|
+
name: metadata.name,
|
|
50
|
+
purpose: metadata.purpose.trim(),
|
|
51
|
+
dependencies
|
|
52
|
+
};
|
|
53
|
+
if (typeof metadata.description === "string")
|
|
54
|
+
result.description = metadata.description.trim();
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
async function readMetadataOnly(path) {
|
|
58
|
+
const stream = createReadStream(path, { encoding: "utf8" });
|
|
59
|
+
const lines = createInterface({ input: stream, crlfDelay: Infinity });
|
|
60
|
+
const frontmatter = [];
|
|
61
|
+
let lineNumber = 0;
|
|
62
|
+
let closed = false;
|
|
63
|
+
try {
|
|
64
|
+
for await (const line of lines) {
|
|
65
|
+
lineNumber += 1;
|
|
66
|
+
if (lineNumber === 1) {
|
|
67
|
+
if (line !== "---")
|
|
68
|
+
throw new SkillSystemError(`${path}: SKILL.md must start with ---`);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (line === "---") {
|
|
72
|
+
closed = true;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
frontmatter.push(line);
|
|
76
|
+
if (lineNumber > 200) {
|
|
77
|
+
throw new SkillSystemError(`${path}: skill frontmatter exceeds 200 lines`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
lines.close();
|
|
83
|
+
stream.destroy();
|
|
84
|
+
}
|
|
85
|
+
if (!closed)
|
|
86
|
+
throw new SkillSystemError(`${path}: skill frontmatter is not closed with ---`);
|
|
87
|
+
return parseMetadata(frontmatter.join("\n"), path);
|
|
88
|
+
}
|
|
89
|
+
function splitSkillDocument(source, path) {
|
|
90
|
+
const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
91
|
+
if (!match)
|
|
92
|
+
throw new SkillSystemError(`${path}: invalid or unclosed skill frontmatter`);
|
|
93
|
+
const metadata = parseMetadata(match[1] ?? "", path);
|
|
94
|
+
const body = (match[2] ?? "").trim();
|
|
95
|
+
if (!body)
|
|
96
|
+
throw new SkillSystemError(`${path}: skill instructions must not be empty`);
|
|
97
|
+
return { metadata, body };
|
|
98
|
+
}
|
|
99
|
+
async function skillDocumentPaths(directory) {
|
|
100
|
+
let entries;
|
|
101
|
+
try {
|
|
102
|
+
entries = await readdir(directory, { withFileTypes: true });
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const code = error.code;
|
|
106
|
+
if (code === "ENOENT")
|
|
107
|
+
return [];
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
const paths = [];
|
|
111
|
+
for (const entry of entries) {
|
|
112
|
+
if (entry.isDirectory()) {
|
|
113
|
+
paths.push(join(directory, entry.name, "SKILL.md"));
|
|
114
|
+
}
|
|
115
|
+
else if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
|
|
116
|
+
paths.push(join(directory, entry.name));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return paths.sort((left, right) => left.localeCompare(right));
|
|
120
|
+
}
|
|
121
|
+
/** Discover skill metadata without retaining or returning instruction bodies. */
|
|
122
|
+
export async function discoverSkills(projectDirectory = ".") {
|
|
123
|
+
const directory = join(resolve(projectDirectory), ".yaaw", "skills");
|
|
124
|
+
const summaries = [];
|
|
125
|
+
const names = new Map();
|
|
126
|
+
for (const path of await skillDocumentPaths(directory)) {
|
|
127
|
+
let metadata;
|
|
128
|
+
try {
|
|
129
|
+
metadata = await readMetadataOnly(path);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
const code = error.code;
|
|
133
|
+
if (code === "ENOENT")
|
|
134
|
+
continue;
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
const existing = names.get(metadata.name);
|
|
138
|
+
if (existing) {
|
|
139
|
+
throw new SkillSystemError(`duplicate discovered skill '${metadata.name}' in ${existing} and ${path}`);
|
|
140
|
+
}
|
|
141
|
+
names.set(metadata.name, path);
|
|
142
|
+
const summary = {
|
|
143
|
+
name: metadata.name,
|
|
144
|
+
purpose: metadata.purpose,
|
|
145
|
+
dependencies: metadata.dependencies,
|
|
146
|
+
path
|
|
147
|
+
};
|
|
148
|
+
if (metadata.description)
|
|
149
|
+
summary.description = metadata.description;
|
|
150
|
+
summaries.push(summary);
|
|
151
|
+
}
|
|
152
|
+
return summaries.sort((left, right) => left.name.localeCompare(right.name));
|
|
153
|
+
}
|
|
154
|
+
async function loadDiscoveredSkill(summary) {
|
|
155
|
+
const source = await readFile(summary.path, "utf8");
|
|
156
|
+
const { metadata, body } = splitSkillDocument(source, summary.path);
|
|
157
|
+
if (metadata.name !== summary.name) {
|
|
158
|
+
throw new SkillSystemError(`${summary.path}: skill metadata changed during loading`);
|
|
159
|
+
}
|
|
160
|
+
const loaded = { ...summary, instructions: body };
|
|
161
|
+
return loaded;
|
|
162
|
+
}
|
|
163
|
+
/** Load one skill and its dependencies in dependency-first order. */
|
|
164
|
+
export async function invokeSkill(name, projectDirectory = ".") {
|
|
165
|
+
const summaries = await discoverSkills(projectDirectory);
|
|
166
|
+
const catalog = new Map(summaries.map((summary) => [summary.name, summary]));
|
|
167
|
+
if (!catalog.has(name)) {
|
|
168
|
+
const available = summaries.map((summary) => summary.name).join(", ") || "none";
|
|
169
|
+
throw new SkillSystemError(`unknown skill '${name}' (available: ${available})`);
|
|
170
|
+
}
|
|
171
|
+
const order = [];
|
|
172
|
+
const visiting = [];
|
|
173
|
+
const visited = new Set();
|
|
174
|
+
const visit = (skillName) => {
|
|
175
|
+
if (visited.has(skillName))
|
|
176
|
+
return;
|
|
177
|
+
const cycleIndex = visiting.indexOf(skillName);
|
|
178
|
+
if (cycleIndex >= 0) {
|
|
179
|
+
const cycle = [...visiting.slice(cycleIndex), skillName].join(" -> ");
|
|
180
|
+
throw new SkillSystemError(`cyclic skill dependency: ${cycle}`);
|
|
181
|
+
}
|
|
182
|
+
const summary = catalog.get(skillName);
|
|
183
|
+
if (!summary) {
|
|
184
|
+
const owner = visiting.at(-1) ?? name;
|
|
185
|
+
throw new SkillSystemError(`skill '${owner}' depends on unknown skill '${skillName}'`);
|
|
186
|
+
}
|
|
187
|
+
visiting.push(skillName);
|
|
188
|
+
for (const dependency of summary.dependencies)
|
|
189
|
+
visit(dependency);
|
|
190
|
+
visiting.pop();
|
|
191
|
+
visited.add(skillName);
|
|
192
|
+
order.push(summary);
|
|
193
|
+
};
|
|
194
|
+
visit(name);
|
|
195
|
+
const skills = [];
|
|
196
|
+
for (const summary of order)
|
|
197
|
+
skills.push(await loadDiscoveredSkill(summary));
|
|
198
|
+
const prompt = [
|
|
199
|
+
`# Skill invocation: ${name}`,
|
|
200
|
+
"",
|
|
201
|
+
"Apply these skills in dependency order.",
|
|
202
|
+
...skills.flatMap((skill) => ["", `## Skill: ${skill.name}`, "", skill.instructions])
|
|
203
|
+
].join("\n");
|
|
204
|
+
return { requested: name, order: skills.map((skill) => skill.name), skills, prompt };
|
|
205
|
+
}
|
|
206
|
+
export function displaySkillPath(summary, projectDirectory = ".") {
|
|
207
|
+
const root = resolve(projectDirectory);
|
|
208
|
+
return summary.path.startsWith(root) ? summary.path.slice(root.length + 1).replaceAll("\\", "/") : basename(summary.path);
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export type PrimitiveKind = "skill" | "agent" | "hook" | "eval" | "workflow" | "context" | "state";
|
|
2
|
+
export interface SkillDefinition {
|
|
3
|
+
name: string;
|
|
4
|
+
purpose: string;
|
|
5
|
+
steps: string[];
|
|
6
|
+
description?: string;
|
|
7
|
+
dependencies?: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface AgentPermissions {
|
|
10
|
+
filesystem: "none" | "read" | "read-write";
|
|
11
|
+
shell: "none" | "read-only" | "execute";
|
|
12
|
+
network?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface AgentDefinition {
|
|
15
|
+
name: string;
|
|
16
|
+
objective: string;
|
|
17
|
+
permissions: AgentPermissions;
|
|
18
|
+
context?: string[];
|
|
19
|
+
skills?: string[];
|
|
20
|
+
tools?: string[];
|
|
21
|
+
}
|
|
22
|
+
export type HookEvent = "after_edit" | "before_verify" | "after_verify_failure" | "before_complete";
|
|
23
|
+
export interface HookDefinition {
|
|
24
|
+
name: string;
|
|
25
|
+
event: HookEvent;
|
|
26
|
+
run: string[];
|
|
27
|
+
match?: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface EvalDefinition {
|
|
30
|
+
name: string;
|
|
31
|
+
run: string[];
|
|
32
|
+
success: {
|
|
33
|
+
exit_code: number;
|
|
34
|
+
stdout_contains?: string;
|
|
35
|
+
stderr_excludes?: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export interface WorkflowStepDefinition {
|
|
39
|
+
id: string;
|
|
40
|
+
uses: `${PrimitiveKind}:${string}`;
|
|
41
|
+
needs?: string[];
|
|
42
|
+
with?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
export interface WorkflowDefinition {
|
|
45
|
+
name: string;
|
|
46
|
+
description?: string;
|
|
47
|
+
steps: WorkflowStepDefinition[];
|
|
48
|
+
}
|
|
49
|
+
export interface ContextDefinition {
|
|
50
|
+
name: string;
|
|
51
|
+
path: string;
|
|
52
|
+
description?: string;
|
|
53
|
+
}
|
|
54
|
+
export interface StateDefinition {
|
|
55
|
+
name: string;
|
|
56
|
+
path: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
durable?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface ProjectDefinition {
|
|
61
|
+
version: 1;
|
|
62
|
+
project: {
|
|
63
|
+
name: string;
|
|
64
|
+
description?: string;
|
|
65
|
+
};
|
|
66
|
+
skills: SkillDefinition[];
|
|
67
|
+
agents: AgentDefinition[];
|
|
68
|
+
hooks: HookDefinition[];
|
|
69
|
+
evals: EvalDefinition[];
|
|
70
|
+
workflows: WorkflowDefinition[];
|
|
71
|
+
context: ContextDefinition[];
|
|
72
|
+
state: StateDefinition[];
|
|
73
|
+
}
|
|
74
|
+
export interface ValidationIssue {
|
|
75
|
+
path: string;
|
|
76
|
+
message: string;
|
|
77
|
+
keyword: "parse" | "schema" | "semantic";
|
|
78
|
+
}
|
|
79
|
+
export type ValidationResult = {
|
|
80
|
+
ok: true;
|
|
81
|
+
value: ProjectDefinition;
|
|
82
|
+
issues: [];
|
|
83
|
+
} | {
|
|
84
|
+
ok: false;
|
|
85
|
+
issues: ValidationIssue[];
|
|
86
|
+
};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "yet-another-agentic-workflow",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Better engineering defaults for Claude Code, Codex, and other coding agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"yaaw": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"skills",
|
|
12
|
+
"templates",
|
|
13
|
+
"schemas"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -p tsconfig.json",
|
|
17
|
+
"prepack": "npm run build",
|
|
18
|
+
"prepublishOnly": "npm test && npm run test:package",
|
|
19
|
+
"test:package": "node --test tests/package.test.mjs",
|
|
20
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
21
|
+
"test": "npm run build && node --test tests",
|
|
22
|
+
"validate:example": "npm run build && node dist/cli.js validate .yaaw/yaaw.yaml"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/QuackyPROG/yet-another-agentic-workflow.git"
|
|
33
|
+
},
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/QuackyPROG/yet-another-agentic-workflow/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/QuackyPROG/yet-another-agentic-workflow#readme",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"ajv": "^8.20.0",
|
|
41
|
+
"ajv-formats": "^3.0.1",
|
|
42
|
+
"yaml": "^2.9.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^24.13.3",
|
|
46
|
+
"typescript": "^5.9.3"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://yaaw.dev/schemas/agent.schema.json",
|
|
4
|
+
"title": "YAAW agent",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["name", "objective", "permissions"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
|
|
10
|
+
"objective": { "type": "string", "minLength": 1 },
|
|
11
|
+
"permissions": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"additionalProperties": false,
|
|
14
|
+
"required": ["filesystem", "shell"],
|
|
15
|
+
"properties": {
|
|
16
|
+
"filesystem": { "enum": ["none", "read", "read-write"] },
|
|
17
|
+
"shell": { "enum": ["none", "read-only", "execute"] },
|
|
18
|
+
"network": { "type": "boolean" }
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"context": {
|
|
22
|
+
"type": "array",
|
|
23
|
+
"uniqueItems": true,
|
|
24
|
+
"items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
|
|
25
|
+
},
|
|
26
|
+
"skills": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"uniqueItems": true,
|
|
29
|
+
"items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
|
|
30
|
+
},
|
|
31
|
+
"tools": {
|
|
32
|
+
"type": "array",
|
|
33
|
+
"uniqueItems": true,
|
|
34
|
+
"items": { "type": "string", "minLength": 1 }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://yaaw.dev/schemas/context.schema.json",
|
|
4
|
+
"title": "YAAW context",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["name", "path"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
|
|
10
|
+
"path": { "type": "string", "minLength": 1 },
|
|
11
|
+
"description": { "type": "string", "minLength": 1 }
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://yaaw.dev/schemas/eval.schema.json",
|
|
4
|
+
"title": "YAAW eval",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["name", "run", "success"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
|
|
10
|
+
"run": {
|
|
11
|
+
"type": "array",
|
|
12
|
+
"minItems": 1,
|
|
13
|
+
"items": { "type": "string", "minLength": 1 }
|
|
14
|
+
},
|
|
15
|
+
"success": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"additionalProperties": false,
|
|
18
|
+
"required": ["exit_code"],
|
|
19
|
+
"properties": {
|
|
20
|
+
"exit_code": { "type": "integer", "minimum": 0, "maximum": 255 },
|
|
21
|
+
"stdout_contains": { "type": "string" },
|
|
22
|
+
"stderr_excludes": { "type": "string" }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://yaaw.dev/schemas/hook.schema.json",
|
|
4
|
+
"title": "YAAW hook",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["name", "event", "run"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
|
|
10
|
+
"event": {
|
|
11
|
+
"enum": [
|
|
12
|
+
"after_edit",
|
|
13
|
+
"before_verify",
|
|
14
|
+
"after_verify_failure",
|
|
15
|
+
"before_complete"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"match": {
|
|
19
|
+
"type": "array",
|
|
20
|
+
"minItems": 1,
|
|
21
|
+
"items": { "type": "string", "minLength": 1 }
|
|
22
|
+
},
|
|
23
|
+
"run": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"minItems": 1,
|
|
26
|
+
"items": { "type": "string", "minLength": 1 }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://yaaw.dev/schemas/skill.schema.json",
|
|
4
|
+
"title": "YAAW skill",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["name", "purpose", "steps"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
|
|
10
|
+
"purpose": { "type": "string", "minLength": 1 },
|
|
11
|
+
"description": { "type": "string", "minLength": 1 },
|
|
12
|
+
"steps": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"minItems": 1,
|
|
15
|
+
"items": { "type": "string", "minLength": 1 }
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"type": "array",
|
|
19
|
+
"uniqueItems": true,
|
|
20
|
+
"items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|