@farmslot/skills 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@farmslot/skills` are tracked here.
4
+
5
+ ## Unreleased
6
+
7
+ - Add the generic recipe-first skills package and migrate the former top-level recipe cooking kit into `skills/recipe-cook`.
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # @farmslot/skills
2
+
3
+ Generic Farmslot recipe skills for Claude, Codex, Cursor, and repo-local agent skill folders.
4
+
5
+ Public guide: https://farmslot.io/docs/guides/recipe-skills-adoption
6
+
7
+ ## What This Package Is
8
+
9
+ `@farmslot/skills` is the recipe-first adoption kit. It teaches an agent how to write, review, diagnose, and adopt validation recipes before a team installs the full Farmslot OS.
10
+
11
+ It does not require Gateway, Command Center, a pool file, slots, or Companion for first use.
12
+
13
+ ## Install
14
+
15
+ Install all skills into a repo-local generic agent folder:
16
+
17
+ ```bash
18
+ npx @farmslot/skills install --target . --layout agents
19
+ ```
20
+
21
+ Install a subset:
22
+
23
+ ```bash
24
+ npx @farmslot/skills install --target . --layout agents --include recipe-cook,recipe-doctor
25
+ ```
26
+
27
+ Supported layouts:
28
+
29
+ | Layout | Destination under `--target` |
30
+ | -------- | ---------------------------- |
31
+ | `agents` | `.agents/skills/` |
32
+ | `codex` | `.codex/skills/` |
33
+ | `claude` | `.claude/skills/` |
34
+ | `cursor` | `.cursor/skills/` |
35
+
36
+ ## Skills
37
+
38
+ | Skill | Purpose |
39
+ | ---------------- | ----------------------------------------------------------------------------------------------- |
40
+ | `recipe-cook` | Turn acceptance criteria, PR intent, or investigation findings into a validation recipe. |
41
+ | `recipe-quality` | Critique recipe and evidence quality; flag fake proof, hidden state injection, and weak claims. |
42
+ | `recipe-doctor` | Check local readiness for recipe authoring or execution. |
43
+ | `recipe-harness` | Help install or run the local recipe runtime when the project has one. |
44
+ | `project-adopt` | Recommend the smallest useful Farmslot integration level for the project. |
45
+
46
+ ## Adoption Ladder
47
+
48
+ 1. Skills only: author and review recipes without a runner.
49
+ 2. Recipe runner: add a local command that can execute one recipe and emit artifacts.
50
+ 3. Project recipe layer: add recipes, runner manifests, project actions, and artifact conventions.
51
+ 4. Farmslot project integration: add `project.json` hooks for Command Center and slots.
52
+ 5. Full OS: adopt multi-slot dispatch, live steering, Companion supervision, and retrospectives.
53
+
54
+ ## Source layout
55
+
56
+ - `src/`: TypeScript CLI and install-library entry points.
57
+ - `skills/`: Packaged skill directories copied into consumer repos.
58
+ - `scripts/`: CommonJS recipe-cook runner utilities exposed through package bin scripts.
59
+ - `templates/`: Scenario fixtures and task templates used by the recipe-cook workflow.
60
+ - `test/`: Node TAP-style smoke and behavior tests for installers and runner scripts.
61
+
62
+ ## Maintenance rules
63
+
64
+ - Keep package payloads self-contained; consumers should not need the Farmslot monorepo.
65
+ - Update `CHANGELOG.md` before packaging or publishing.
66
+ - Run the package readiness guard when files move, bins change, or exports are added.
67
+
68
+ ## Local quality
69
+
70
+ ```bash
71
+ yarn workspace @farmslot/skills build
72
+ yarn workspace @farmslot/skills test
73
+ node scripts/quality/check-farmslot-package-readiness.mjs --packages @farmslot/skills
74
+ ```
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
7
+ const skillsRoot = path.join(packageRoot, 'skills');
8
+ const knownSkills = readdirSync(skillsRoot)
9
+ .filter((entry) => existsSync(path.join(skillsRoot, entry, 'SKILL.md')))
10
+ .sort();
11
+
12
+ const layoutDirs = {
13
+ agents: '.agents/skills',
14
+ claude: '.claude/skills',
15
+ codex: '.codex/skills',
16
+ cursor: '.cursor/skills',
17
+ };
18
+
19
+ function parseArgs(argv) {
20
+ const parsed = {
21
+ command: argv[0] || 'help',
22
+ target: '.',
23
+ layout: 'agents',
24
+ include: [],
25
+ force: false,
26
+ };
27
+ for (let index = 1; index < argv.length; index += 1) {
28
+ const arg = argv[index];
29
+ if (arg === '--target') parsed.target = argv[++index] || '.';
30
+ else if (arg.startsWith('--target=')) parsed.target = arg.slice('--target='.length);
31
+ else if (arg === '--layout') parsed.layout = argv[++index] || 'agents';
32
+ else if (arg.startsWith('--layout=')) parsed.layout = arg.slice('--layout='.length);
33
+ else if (arg === '--include') parsed.include = splitCsv(argv[++index] || '');
34
+ else if (arg.startsWith('--include='))
35
+ parsed.include = splitCsv(arg.slice('--include='.length));
36
+ else if (arg === '--force') parsed.force = true;
37
+ }
38
+ return parsed;
39
+ }
40
+
41
+ function splitCsv(value) {
42
+ return String(value)
43
+ .split(',')
44
+ .map((item) => item.trim())
45
+ .filter(Boolean);
46
+ }
47
+
48
+ function usage() {
49
+ return [
50
+ 'Usage: farmslot-skills <command> [options]',
51
+ '',
52
+ 'Commands:',
53
+ ' list List bundled skills',
54
+ ' install Install skills into a target layout',
55
+ ' init Alias for install',
56
+ ' doctor Print target install destination',
57
+ '',
58
+ 'Options:',
59
+ ' --target <dir> Target root, default .',
60
+ ' --layout <agents|claude|codex|cursor>',
61
+ ' --include <a,b> Skill names to install, default all',
62
+ ' --force Replace existing installed skill directories',
63
+ ].join('\n');
64
+ }
65
+
66
+ function selectedSkills(include) {
67
+ const selected = include.length > 0 ? include : knownSkills;
68
+ const unknown = selected.filter((skill) => !knownSkills.includes(skill));
69
+ if (unknown.length > 0) {
70
+ throw new Error(
71
+ `Unknown skill(s): ${unknown.join(', ')}. Known skills: ${knownSkills.join(', ')}`,
72
+ );
73
+ }
74
+ return selected;
75
+ }
76
+
77
+ function install(args) {
78
+ const relativeDest = layoutDirs[args.layout];
79
+ if (!relativeDest) {
80
+ throw new Error(
81
+ `Unknown layout: ${args.layout}. Expected one of: ${Object.keys(layoutDirs).join(', ')}`,
82
+ );
83
+ }
84
+ const targetRoot = path.resolve(args.target);
85
+ const destRoot = path.join(targetRoot, relativeDest);
86
+ mkdirSync(destRoot, { recursive: true });
87
+
88
+ for (const skill of selectedSkills(args.include)) {
89
+ const source = path.join(skillsRoot, skill);
90
+ const dest = path.join(destRoot, skill);
91
+ if (existsSync(dest)) {
92
+ if (!args.force) {
93
+ throw new Error(`Refusing to overwrite existing skill without --force: ${dest}`);
94
+ }
95
+ rmSync(dest, { recursive: true, force: true });
96
+ }
97
+ cpSync(source, dest, { recursive: true });
98
+ console.log(`${skill} -> ${dest}`);
99
+ }
100
+ }
101
+
102
+ function doctor(args) {
103
+ const relativeDest = layoutDirs[args.layout];
104
+ if (!relativeDest) {
105
+ throw new Error(
106
+ `Unknown layout: ${args.layout}. Expected one of: ${Object.keys(layoutDirs).join(', ')}`,
107
+ );
108
+ }
109
+ const targetRoot = path.resolve(args.target);
110
+ const destRoot = path.join(targetRoot, relativeDest);
111
+ console.log(
112
+ `package: ${JSON.parse(readFileSync(path.join(packageRoot, 'package.json'), 'utf8')).name}`,
113
+ );
114
+ console.log(`layout: ${args.layout}`);
115
+ console.log(`destination: ${destRoot}`);
116
+ console.log(`skills: ${knownSkills.join(', ')}`);
117
+ }
118
+
119
+ function main() {
120
+ const args = parseArgs(process.argv.slice(2));
121
+ if (args.command === 'list') console.log(knownSkills.join('\n'));
122
+ else if (args.command === 'install' || args.command === 'init') install(args);
123
+ else if (args.command === 'doctor') doctor(args);
124
+ else {
125
+ console.log(usage());
126
+ if (args.command !== 'help' && args.command !== '--help' && args.command !== '-h')
127
+ process.exitCode = 1;
128
+ }
129
+ }
130
+
131
+ main();
@@ -0,0 +1,6 @@
1
+ export declare const FARMSLOT_SKILLS_PACKAGE = "@farmslot/skills";
2
+ export declare const FARMSLOT_SKILL_NAMES: readonly ["recipe-cook", "recipe-quality", "recipe-doctor", "recipe-harness", "project-adopt"];
3
+ export type FarmslotSkillName = (typeof FARMSLOT_SKILL_NAMES)[number];
4
+ export declare const FARMSLOT_SKILL_INSTALL_LAYOUTS: readonly ["agents", "claude", "codex", "cursor"];
5
+ export type FarmslotSkillInstallLayout = (typeof FARMSLOT_SKILL_INSTALL_LAYOUTS)[number];
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAE1D,eAAO,MAAM,oBAAoB,gGAMvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,eAAO,MAAM,8BAA8B,kDAAmD,CAAC;AAE/F,MAAM,MAAM,0BAA0B,GAAG,CAAC,OAAO,8BAA8B,CAAC,CAAC,MAAM,CAAC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export const FARMSLOT_SKILLS_PACKAGE = '@farmslot/skills';
2
+ export const FARMSLOT_SKILL_NAMES = [
3
+ 'recipe-cook',
4
+ 'recipe-quality',
5
+ 'recipe-doctor',
6
+ 'recipe-harness',
7
+ 'project-adopt',
8
+ ];
9
+ export const FARMSLOT_SKILL_INSTALL_LAYOUTS = ['agents', 'claude', 'codex', 'cursor'];
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,kBAAkB,CAAC;AAE1D,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,aAAa;IACb,gBAAgB;IAChB,eAAe;IACf,gBAAgB;IAChB,eAAe;CACP,CAAC;AAIX,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAU,CAAC"}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@farmslot/skills",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "farmslot-skills": "./bin/farmslot-skills.mjs"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./skills/*": "./skills/*/SKILL.md",
17
+ "./schemas/*": "./schemas/*"
18
+ },
19
+ "scripts": {
20
+ "typecheck": "tsc --noEmit --project tsconfig.json",
21
+ "test": "node test/prepare-cooking-run.test.cjs && node test/run-cooking-lane.test.cjs && node test/validator-loop.test.cjs && node test/package-exports.test.cjs",
22
+ "format": "prettier --write --ignore-path ../../.prettierignore .",
23
+ "format:check": "prettier --check --ignore-path ../../.prettierignore .",
24
+ "lint": "eslint \"src/**/*.ts\"",
25
+ "lint:fix": "eslint \"src/**/*.ts\" --fix",
26
+ "quality": "prettier --check --ignore-path ../../.prettierignore . && eslint \"src/**/*.ts\" && tsc --noEmit --project tsconfig.json && yarn build && yarn test",
27
+ "build": "rm -rf dist && tsc --project tsconfig.build.json",
28
+ "prepack": "cd ../.. && node scripts/quality/check-farmslot-package-readiness.mjs --require-changelog --packages @farmslot/skills && yarn workspace @farmslot/skills build",
29
+ "prepublishOnly": "node ../../scripts/quality/check-farmslot-package-readiness.mjs --publish --packages @farmslot/skills"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^22.0.0",
33
+ "eslint": "^10.3.0",
34
+ "prettier": "^3.8.3",
35
+ "typescript": "^5.6.0"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/deeeed/farmslot.git",
40
+ "directory": "packages/skills"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/deeeed/farmslot/issues"
44
+ },
45
+ "license": "MIT",
46
+ "homepage": "https://farmslot.io/docs/guides/recipe-skills-adoption",
47
+ "keywords": [
48
+ "farmslot",
49
+ "skills",
50
+ "recipe",
51
+ "validation",
52
+ "agentic-engineering"
53
+ ],
54
+ "files": [
55
+ "README.md",
56
+ "CHANGELOG.md",
57
+ "bin/**/*.mjs",
58
+ "dist/**/*.js",
59
+ "dist/**/*.d.ts",
60
+ "dist/**/*.d.ts.map",
61
+ "dist/**/*.js.map",
62
+ "schemas/**/*.json",
63
+ "scripts/**/*.cjs",
64
+ "skills/**/*.md",
65
+ "templates/**/*.json"
66
+ ],
67
+ "publishConfig": {
68
+ "access": "public"
69
+ }
70
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "recipe-cook-learning.schema.json",
4
+ "type": "object",
5
+ "required": [
6
+ "run_id",
7
+ "scenario_type",
8
+ "target_repo",
9
+ "branch",
10
+ "validation_results",
11
+ "evidence_verdict",
12
+ "artifact_dir",
13
+ "recipe_path",
14
+ "next_delta",
15
+ "touched_files"
16
+ ],
17
+ "properties": {
18
+ "run_id": { "type": "string" },
19
+ "scenario_type": { "type": "string" },
20
+ "target_repo": { "type": "string" },
21
+ "branch": { "type": ["string", "null"] },
22
+ "artifact_dir": { "type": "string" },
23
+ "recipe_path": { "type": "string" },
24
+ "recipe_cook_path": { "type": ["string", "null"] },
25
+ "validation_results": { "type": ["object", "null"] },
26
+ "evidence_verdict": { "type": ["string", "null"] },
27
+ "next_delta": { "type": "string" },
28
+ "touched_files": { "type": "array", "items": { "type": "string" } }
29
+ },
30
+ "additionalProperties": true
31
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "recipe-cook-patch-metadata.schema.json",
4
+ "type": "object",
5
+ "required": [
6
+ "before_version_id",
7
+ "after_version_id",
8
+ "scenario_ids",
9
+ "touched_files",
10
+ "expected_score_impact"
11
+ ],
12
+ "properties": {
13
+ "before_version_id": { "type": "string" },
14
+ "after_version_id": { "type": "string" },
15
+ "scenario_ids": { "type": "array", "items": { "type": "string" } },
16
+ "touched_files": { "type": "array", "items": { "type": "string" } },
17
+ "expected_score_impact": { "type": "string" }
18
+ }
19
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "recipe-cook-run-ledger-entry.schema.json",
4
+ "type": "object",
5
+ "required": [
6
+ "run_id",
7
+ "version_id_under_test",
8
+ "task_artifact_dir",
9
+ "learning_artifact_path",
10
+ "recipe_path",
11
+ "recipe_cook_path",
12
+ "validator_manifest_path",
13
+ "scenario_lane",
14
+ "result_summary",
15
+ "quality_semantic",
16
+ "quality",
17
+ "pass_rate",
18
+ "inference_cost_usd",
19
+ "source_run_id"
20
+ ],
21
+ "properties": {
22
+ "run_id": { "type": "string" },
23
+ "version_id_under_test": { "type": "string" },
24
+ "task_artifact_dir": { "type": "string" },
25
+ "learning_artifact_path": { "type": "string" },
26
+ "recipe_path": { "type": "string" },
27
+ "recipe_cook_path": { "type": ["string", "null"] },
28
+ "validator_manifest_path": { "type": "string" },
29
+ "scenario_lane": { "type": "string" },
30
+ "result_summary": { "type": "string" },
31
+ "quality_semantic": { "type": "string", "enum": ["good", "ok", "bad"] },
32
+ "quality": { "type": "number" },
33
+ "pass_rate": { "type": ["number", "null"] },
34
+ "inference_cost_usd": { "type": ["number", "null"] },
35
+ "source_run_id": { "type": "string" }
36
+ }
37
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "recipe-cook-validator-manifest.schema.json",
4
+ "type": "object",
5
+ "required": [
6
+ "run_id",
7
+ "iteration_id",
8
+ "base_version_id",
9
+ "task_artifact_dir",
10
+ "learning_artifact_path",
11
+ "recipe_path",
12
+ "recipe_cook_path",
13
+ "candidate_patch_path",
14
+ "validator_manifest_path",
15
+ "touched_files",
16
+ "scenario_bundle",
17
+ "lane_results",
18
+ "score_vector",
19
+ "decision",
20
+ "decision_reason"
21
+ ],
22
+ "properties": {
23
+ "run_id": { "type": "string" },
24
+ "iteration_id": { "type": "string" },
25
+ "base_version_id": { "type": "string" },
26
+ "task_artifact_dir": { "type": "string" },
27
+ "learning_artifact_path": { "type": "string" },
28
+ "recipe_path": { "type": "string" },
29
+ "recipe_cook_path": { "type": ["string", "null"] },
30
+ "candidate_patch_path": { "type": "string" },
31
+ "validator_manifest_path": { "type": "string" },
32
+ "touched_files": { "type": "array", "items": { "type": "string" } },
33
+ "scenario_bundle": { "type": "array", "items": { "type": "string" } },
34
+ "lane_results": {
35
+ "type": "array",
36
+ "items": {
37
+ "type": "object",
38
+ "required": [
39
+ "lane",
40
+ "scenario_id",
41
+ "task_artifact_dir",
42
+ "learning_artifact_path",
43
+ "recipe_path",
44
+ "recipe_cook_path",
45
+ "quality_semantic",
46
+ "quality_reasoning",
47
+ "live_run_exit",
48
+ "pass_rate_input",
49
+ "inference_cost_usd",
50
+ "source_artifacts"
51
+ ],
52
+ "properties": {
53
+ "lane": { "type": "string" },
54
+ "scenario_id": { "type": "string" },
55
+ "task_artifact_dir": { "type": "string" },
56
+ "learning_artifact_path": { "type": "string" },
57
+ "recipe_path": { "type": "string" },
58
+ "recipe_cook_path": { "type": ["string", "null"] },
59
+ "quality_semantic": { "type": "string", "enum": ["good", "ok", "bad"] },
60
+ "quality_reasoning": { "type": "string" },
61
+ "live_run_exit": { "type": ["integer", "null"] },
62
+ "pass_rate_input": { "type": ["number", "null"] },
63
+ "inference_cost_usd": { "type": ["number", "null"] },
64
+ "source_artifacts": {
65
+ "type": "object",
66
+ "properties": {
67
+ "grade_path": { "type": ["string", "null"] },
68
+ "meta_path": { "type": ["string", "null"] },
69
+ "session_metrics_path": { "type": ["string", "null"] },
70
+ "probe_state_path": { "type": ["string", "null"] }
71
+ },
72
+ "additionalProperties": true
73
+ }
74
+ },
75
+ "additionalProperties": true
76
+ }
77
+ },
78
+ "score_vector": {
79
+ "type": "object",
80
+ "required": ["quality", "pass_rate", "cost_efficiency", "balanced_score"],
81
+ "properties": {
82
+ "quality": { "type": "number" },
83
+ "pass_rate": { "type": ["number", "null"] },
84
+ "cost_efficiency": { "type": ["number", "null"] },
85
+ "balanced_score": { "type": ["number", "null"] }
86
+ }
87
+ },
88
+ "decision": { "type": "string", "enum": ["keep", "reject"] },
89
+ "decision_reason": { "type": "string" }
90
+ },
91
+ "additionalProperties": true
92
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "recipe-cook-version-ledger.schema.json",
4
+ "type": "object",
5
+ "required": ["versions"],
6
+ "properties": {
7
+ "versions": {
8
+ "type": "array",
9
+ "items": {
10
+ "type": "object",
11
+ "required": [
12
+ "version_id",
13
+ "parent_version_id",
14
+ "patch_artifact_path",
15
+ "source_run_id",
16
+ "source_validator_manifest_path",
17
+ "source_task_artifact_dirs",
18
+ "source_learning_artifact_paths",
19
+ "scenarios_covered",
20
+ "aggregate_score_vector",
21
+ "decision",
22
+ "decision_rationale"
23
+ ],
24
+ "properties": {
25
+ "version_id": { "type": "string" },
26
+ "parent_version_id": { "type": "string" },
27
+ "patch_artifact_path": { "type": "string" },
28
+ "source_run_id": { "type": "string" },
29
+ "source_validator_manifest_path": { "type": "string" },
30
+ "source_task_artifact_dirs": { "type": "array", "items": { "type": "string" } },
31
+ "source_learning_artifact_paths": { "type": "array", "items": { "type": "string" } },
32
+ "scenarios_covered": { "type": "array", "items": { "type": "string" } },
33
+ "aggregate_score_vector": {
34
+ "type": "object",
35
+ "required": ["quality", "pass_rate", "cost_efficiency", "balanced_score"],
36
+ "properties": {
37
+ "quality": { "type": "number" },
38
+ "pass_rate": { "type": ["number", "null"] },
39
+ "cost_efficiency": { "type": ["number", "null"] },
40
+ "balanced_score": { "type": ["number", "null"] }
41
+ }
42
+ },
43
+ "decision": { "type": "string", "enum": ["keep", "reject"] },
44
+ "decision_rationale": { "type": "string" }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }