@clemrig/factory 0.3.0 → 0.4.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.
Files changed (90) hide show
  1. package/README.md +111 -21
  2. package/dist/app/board.d.ts +7 -0
  3. package/dist/app/board.js +47 -0
  4. package/dist/app/board.js.map +1 -0
  5. package/dist/app/define.d.ts +27 -0
  6. package/dist/app/define.js +68 -0
  7. package/dist/app/define.js.map +1 -0
  8. package/dist/app/doctor.js +5 -4
  9. package/dist/app/doctor.js.map +1 -1
  10. package/dist/app/factory.js +10 -2
  11. package/dist/app/factory.js.map +1 -1
  12. package/dist/app/run.js +1 -1
  13. package/dist/app/run.js.map +1 -1
  14. package/dist/app/workflows/implement.d.ts +8 -0
  15. package/dist/app/workflows/implement.js +268 -0
  16. package/dist/app/workflows/implement.js.map +1 -0
  17. package/dist/app/workflows/issue-save.d.ts +2 -0
  18. package/dist/app/workflows/issue-save.js +35 -0
  19. package/dist/app/workflows/issue-save.js.map +1 -0
  20. package/dist/cli/application.js +1 -1
  21. package/dist/cli/application.js.map +1 -1
  22. package/dist/cli/help.d.ts +1 -1
  23. package/dist/cli/help.js +5 -3
  24. package/dist/cli/help.js.map +1 -1
  25. package/dist/cli/init.d.ts +2 -2
  26. package/dist/cli/init.js +4 -4
  27. package/dist/cli/init.js.map +1 -1
  28. package/dist/cli/ui.d.ts +5 -2
  29. package/dist/cli/ui.js +20 -7
  30. package/dist/cli/ui.js.map +1 -1
  31. package/dist/domain/board.d.ts +65 -0
  32. package/dist/domain/board.js +95 -0
  33. package/dist/domain/board.js.map +1 -0
  34. package/dist/domain/definition.d.ts +15 -0
  35. package/dist/domain/definition.js +28 -0
  36. package/dist/domain/definition.js.map +1 -0
  37. package/dist/domain/delivery.d.ts +9 -0
  38. package/dist/domain/delivery.js +10 -0
  39. package/dist/domain/delivery.js.map +1 -0
  40. package/dist/domain/issue.d.ts +11 -0
  41. package/dist/domain/issue.js +22 -0
  42. package/dist/domain/issue.js.map +1 -0
  43. package/dist/domain/parsed.d.ts +8 -0
  44. package/dist/domain/parsed.js +2 -0
  45. package/dist/domain/parsed.js.map +1 -0
  46. package/dist/domain/plan.d.ts +24 -0
  47. package/dist/domain/plan.js +49 -0
  48. package/dist/domain/plan.js.map +1 -0
  49. package/dist/domain/pull-request.d.ts +17 -0
  50. package/dist/domain/pull-request.js +32 -0
  51. package/dist/domain/pull-request.js.map +1 -0
  52. package/dist/domain/review.d.ts +36 -0
  53. package/dist/domain/review.js +45 -0
  54. package/dist/domain/review.js.map +1 -0
  55. package/dist/domain/spec.d.ts +18 -0
  56. package/dist/domain/spec.js +118 -0
  57. package/dist/domain/spec.js.map +1 -0
  58. package/dist/domain/verification.d.ts +16 -0
  59. package/dist/domain/verification.js +11 -0
  60. package/dist/domain/verification.js.map +1 -0
  61. package/dist/index.d.ts +8 -4
  62. package/dist/index.js +5 -3
  63. package/dist/index.js.map +1 -1
  64. package/dist/system/checks.d.ts +32 -0
  65. package/dist/system/checks.js +49 -0
  66. package/dist/system/checks.js.map +1 -0
  67. package/dist/system/factory.d.ts +7 -5
  68. package/dist/system/factory.js +19 -19
  69. package/dist/system/factory.js.map +1 -1
  70. package/dist/system/git.d.ts +25 -0
  71. package/dist/system/git.js +73 -0
  72. package/dist/system/git.js.map +1 -0
  73. package/dist/system/github.d.ts +8 -0
  74. package/dist/system/github.js +52 -0
  75. package/dist/system/github.js.map +1 -0
  76. package/dist/system/issues.d.ts +24 -0
  77. package/dist/system/issues.js +66 -0
  78. package/dist/system/issues.js.map +1 -0
  79. package/dist/system/lock.d.ts +8 -0
  80. package/dist/system/lock.js +35 -0
  81. package/dist/system/lock.js.map +1 -0
  82. package/dist/system/templates.d.ts +2 -1
  83. package/dist/system/templates.js +69 -3
  84. package/dist/system/templates.js.map +1 -1
  85. package/package.json +6 -4
  86. package/prompts/implement/implement.md +21 -0
  87. package/prompts/implement/plan.md +20 -0
  88. package/prompts/implement/review.md +17 -0
  89. package/templates/init/factory.ts +37 -2
  90. package/templates/skills/issue/SKILL.md +82 -0
@@ -1,13 +1,70 @@
1
- import { cp, mkdir, readFile, rename, writeFile } from "node:fs/promises";
2
- import { join } from "node:path";
1
+ import { cp, lstat, mkdir, readFile, readlink, rename, symlink, writeFile, } from "node:fs/promises";
2
+ import { basename, dirname, join, relative, resolve } from "node:path";
3
3
  /** Both `src/system/` and `dist/system/` sit two levels below the package root. */
4
4
  const root = new URL("../../", import.meta.url);
5
+ /** The `issue` skill: read by Pi and Codex there, by Claude Code through a folder link. */
6
+ const skillDir = join(".agents", "skills", "issue");
7
+ async function exists(path) {
8
+ return lstat(path).then(() => true, (error) => {
9
+ if (error.code === "ENOENT")
10
+ return false;
11
+ throw error;
12
+ });
13
+ }
14
+ /**
15
+ * Where a path really leads: through every link on the way, dangling ones
16
+ * included, and through what does not exist yet.
17
+ */
18
+ async function location(path, links = 0) {
19
+ if (links > 40)
20
+ throw new Error(`Too many links on the way to ${path}`);
21
+ const parent = dirname(path);
22
+ const here = parent === path
23
+ ? path
24
+ : join(await location(parent, links), basename(path));
25
+ const stats = await lstat(here).catch((error) => {
26
+ if (error.code === "ENOENT")
27
+ return undefined;
28
+ throw error;
29
+ });
30
+ if (!stats?.isSymbolicLink())
31
+ return here;
32
+ return location(resolve(dirname(here), await readlink(here)), links + 1);
33
+ }
34
+ /**
35
+ * Where the skill goes, and Claude Code's link to it, both where the paths
36
+ * really lead: `.agents`, `.claude` and their `skills` may be links, even to
37
+ * folders that do not exist yet. No link when `.claude/skills` leads to
38
+ * `.agents/skills`, which then holds the skill. The link's target is relative
39
+ * to the folder it lands in.
40
+ */
41
+ async function skillPlaces(cwd) {
42
+ const agents = await location(join(resolve(cwd), ".agents", "skills"));
43
+ const claude = await location(join(resolve(cwd), ".claude", "skills"));
44
+ const skill = { path: join(agents, "issue"), shown: join(cwd, skillDir) };
45
+ if (claude === agents)
46
+ return { skill };
47
+ return {
48
+ skill,
49
+ link: {
50
+ path: join(claude, "issue"),
51
+ target: relative(claude, skill.path),
52
+ shown: join(cwd, ".claude", "skills", "issue"),
53
+ },
54
+ };
55
+ }
5
56
  /**
6
57
  * Creates `.factory/` in `cwd` from the package's templates, its `package.json`
7
- * pinned to this factory version. An existing `.factory/` is refused untouched.
58
+ * pinned to this factory version, and the `issue` skill. An existing
59
+ * `.factory/` or skill is refused, with nothing written.
8
60
  */
9
61
  export async function createFromTemplates(cwd) {
10
62
  const factoryDir = join(cwd, ".factory");
63
+ // Everything is decided before anything is written.
64
+ const { skill, link } = await skillPlaces(cwd);
65
+ for (const { path, shown } of [skill, ...(link ? [link] : [])])
66
+ if (await exists(path))
67
+ throw new Error(`${shown} already exists`);
11
68
  try {
12
69
  await mkdir(factoryDir);
13
70
  }
@@ -25,6 +82,15 @@ export async function createFromTemplates(cwd) {
25
82
  type: "module",
26
83
  dependencies: { "@clemrig/factory": version },
27
84
  }, null, 2)}\n`);
85
+ await mkdir(dirname(skill.path), { recursive: true });
86
+ await cp(new URL("templates/skills/issue/", root), skill.path, {
87
+ recursive: true,
88
+ });
89
+ if (link) {
90
+ await mkdir(dirname(link.path), { recursive: true });
91
+ // Codex ignores a SKILL.md that is itself a link: the link is the folder's.
92
+ await symlink(link.target, link.path);
93
+ }
28
94
  return { factoryDir, version };
29
95
  }
30
96
  //# sourceMappingURL=templates.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/system/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,mFAAmF;AACnF,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAEhD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAW;IAEX,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YACpD,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,iBAAiB,CAAC,CAAC;QAClD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAC5B,MAAM,QAAQ,CAAC,IAAI,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAC/B,CAAC;IACzB,MAAM,EAAE,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,kEAAkE;IAClE,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5E,MAAM,SAAS,CACb,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,EAChC,GAAG,IAAI,CAAC,SAAS,CACf;QACE,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,EAAE,kBAAkB,EAAE,OAAO,EAAE;KAC9C,EACD,IAAI,EACJ,CAAC,CACF,IAAI,CACN,CAAC;IACF,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/system/templates.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@clemrig/factory",
3
- "version": "0.3.0",
4
- "description": "Write agent workflows in TypeScript inside any repository, run them in the terminal and watch them in a local dashboard",
3
+ "version": "0.4.0",
4
+ "description": "Take a repository's issues from spec to pull request with agents, watch them on a local Kanban, and run the repository's own workflows",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -22,6 +22,7 @@
22
22
  },
23
23
  "files": [
24
24
  "dist",
25
+ "prompts",
25
26
  "templates"
26
27
  ],
27
28
  "engines": {
@@ -38,7 +39,8 @@
38
39
  "prepack": "npm run build"
39
40
  },
40
41
  "dependencies": {
41
- "@clemrig/flow": "0.3.0",
42
- "@clemrig/flow-ui": "0.1.2"
42
+ "@clemrig/factory-ui": "0.1.0",
43
+ "@clemrig/flow": "0.4.0",
44
+ "@clemrig/flow-ui": "0.2.0"
43
45
  }
44
46
  }
@@ -0,0 +1,21 @@
1
+ You implement an approved plan in this repository.
2
+
3
+ First read the repository's agent instructions: `AGENTS.md` at the root and in each directory you touch.
4
+ Follow their conventions and validation guidance. Ignore `.factory/` and never change it.
5
+
6
+ The request gives the spec, approved and unchanging, and the plan. Implement the plan, tests included, and run
7
+ the relevant checks yourself before answering.
8
+
9
+ Never commit, switch branches or push: the run commits, pushes and opens the pull request itself, and it stops
10
+ if you commit or switch branches.
11
+
12
+ When the request contains `feedback`, it reports what failed after your previous answer, a check or the
13
+ review: fix that, then answer again.
14
+
15
+ Answer with:
16
+
17
+ - `summary`: what you changed, in a few sentences.
18
+ - `criteria`: each acceptance criterion once, with the evidence that it is met (tests, files).
19
+ - `deviations`: where you departed from the plan and why; empty if nowhere.
20
+
21
+ Write in English.
@@ -0,0 +1,20 @@
1
+ You plan the implementation of an approved spec in this repository. You change nothing.
2
+
3
+ Before planning, read the repository's agent instructions: `AGENTS.md` at the root and in each directory the
4
+ change will touch, and follow them. Ignore `.factory/`: the other issues there are history, not the current
5
+ truth, and `.factory/runs/` holds agents' outputs.
6
+
7
+ The request gives the issue's slug and its spec. The spec is approved and does not change: plan what it asks,
8
+ nothing more. When something is unclear, choose the interpretation most consistent with the code and record it
9
+ in `risks`.
10
+
11
+ Answer with a plan of verifiable steps:
12
+
13
+ - `summary`: the approach, in a few sentences.
14
+ - `steps`: each names the acceptance criteria it serves (`AC1`…), the files it creates or changes, and the
15
+ tests that prove it. Every acceptance criterion is served by at least one step.
16
+ - `commit`: the conventional commit subject of the whole change, for example
17
+ `feat(api): export watchlists as CSV`, at most 72 characters.
18
+ - `risks`: what could go wrong and what you assumed; empty if nothing.
19
+
20
+ Write in English.
@@ -0,0 +1,17 @@
1
+ You review a change against its approved spec, independently. You change nothing.
2
+
3
+ Read the repository's agent instructions: `AGENTS.md` at the root and in the directories the change touches.
4
+ Ignore `.factory/`: it holds other issues' history and agents' outputs, which you must not rely on.
5
+
6
+ The request gives the spec, the diff of the change, and the repository's checks, which all passed. Do not take
7
+ anything on trust: verify each acceptance criterion in the code and the tests, reading files beyond the diff
8
+ when needed. Look for unmet criteria, defects, regressions, missing or weak tests, security problems and
9
+ departures from the repository's conventions.
10
+
11
+ Answer with:
12
+
13
+ - `criteria`: each acceptance criterion once, `met` or `not_met`, with its evidence (file, test, behavior).
14
+ - `findings`: `blocking` for an unmet criterion, a defect or a regression; `minor` for an improvement that is
15
+ not required. Give the file when relevant.
16
+
17
+ The change is approved only when every criterion is met and no finding is blocking. Write in English.
@@ -1,4 +1,39 @@
1
+ import { type AgentProfile, defineFactory } from "@clemrig/factory";
1
2
  import ask from "./workflows/ask/index.ts";
2
3
 
3
- /** The workflows of this repository, run with `factory run <name>`. */
4
- export default [ask];
4
+ const minutes = 60_000;
5
+ const opus = {
6
+ runtime: "claude-code",
7
+ model: "claude-opus-5-5",
8
+ thinking: "high",
9
+ } as const;
10
+ const reader = {
11
+ ...opus,
12
+ tools: ["Read", "Grep", "Glob"],
13
+ timeoutMs: 20 * minutes,
14
+ } satisfies AgentProfile;
15
+
16
+ /**
17
+ * This repository's factory: `factory run issue-save` and `factory run
18
+ * implement --issue <slug>` take an issue from its spec to a pull request.
19
+ */
20
+ export default defineFactory({
21
+ // The repository's checks, run in order, without a shell: before the run on
22
+ // the main branch, then after each implementation. Replace this example.
23
+ verify: [{ name: "test", command: ["npm", "test"], timeoutMs: 10 * minutes }],
24
+ // The budget of an implement run, in USD; --max-cost-usd changes it for one run.
25
+ maxCostUsd: 25,
26
+ profiles: {
27
+ plan: reader,
28
+ implement: {
29
+ ...opus,
30
+ tools: ["Read", "Grep", "Glob", "Edit", "Write", "Bash"],
31
+ // The listed tools run; anything else is refused instead of waiting for a prompt.
32
+ permissionMode: "dontAsk",
33
+ timeoutMs: 60 * minutes,
34
+ },
35
+ review: reader,
36
+ },
37
+ // This repository's own workflows, run with `factory run <name>`.
38
+ workflows: [ask],
39
+ });
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: issue
3
+ description: "Create or specify a factory issue in .factory/issues/<slug>/: capture an idea as issue.md, then clarify it with the operator into a spec.md ready for factory run implement. Use when the operator wants to add an issue, write or refine a spec, or prepare work for the factory."
4
+ ---
5
+
6
+ # Issue
7
+
8
+ You move an issue through the first two columns of the factory's Kanban: **Backlog** (its `issue.md` exists)
9
+ and **Specifying** (its `spec.md` exists). You never write these files yourself: `factory run issue-save` checks
10
+ a draft and writes it at the right place. Talk with the operator in their language.
11
+
12
+ ## Find or create the issue
13
+
14
+ Issues live in `.factory/issues/<slug>/`; read them to find the one the operator means. For a new issue,
15
+ propose a slug (lowercase words separated by hyphens; it also names the issue's branch), a title and a short
16
+ description of the need. Once the operator agrees, save the issue (see Save).
17
+
18
+ ## Specify
19
+
20
+ 1. Read the repository's agent instructions (`AGENTS.md` at the root and in the directories concerned) and the
21
+ relevant code. Change nothing.
22
+ 2. Ask the operator questions, a few at a time, until you can fill every section without inventing anything.
23
+ Do not ask what the code or the docs already answer. For each question, give its practical consequence
24
+ and your recommendation.
25
+ 3. Describe what and why, never how: the run that implements the spec plans the technical work itself.
26
+ 4. Propose the complete spec and wait for the operator's agreement, then save it (see Save).
27
+
28
+ Other issues in `.factory/issues/` are history, not the current truth: rely on the code and the docs.
29
+
30
+ ## Format
31
+
32
+ `issue.md`:
33
+
34
+ ```markdown
35
+ # <Title>
36
+
37
+ <Description of the need>
38
+ ```
39
+
40
+ `spec.md`:
41
+
42
+ ```markdown
43
+ # <Title>
44
+
45
+ ## Objective
46
+ <The problem and why it matters>
47
+
48
+ ## Scope
49
+ <What the change includes>
50
+
51
+ ## Out of scope
52
+ <What it explicitly excludes>
53
+
54
+ ## Acceptance criteria
55
+ - AC1: <A fact observable from outside>
56
+ - AC2: <…>
57
+
58
+ ## Constraints
59
+ <Limits imposed on the solution>
60
+ ```
61
+
62
+ - Exactly these five sections, in this order, with nothing between the title and the first one.
63
+ - No section is empty: write `None.` when there is nothing to say.
64
+ - Acceptance criteria contains only `- AC<n>: <criterion>` items, numbered from AC1 without gaps; an indented
65
+ line continues the criterion above it. Each criterion is a fact that a user, an API client or an operator
66
+ can check, not an implementation detail.
67
+ - Headings stay in English; the content may be in any language.
68
+
69
+ ## Save
70
+
71
+ 1. Write the draft to a new file outside the repository, for example in a directory created by `mktemp -d`.
72
+ 2. From the repository, run
73
+ `factory run issue-save --issue <slug> --kind issue --file <absolute path>` for `issue.md`, or
74
+ `--kind spec` for `spec.md`.
75
+ 3. `Saved .factory/issues/<slug>/<kind>.md` means it is done. Otherwise the command lists every problem: fix
76
+ the draft and run it again. It refuses a spec whose issue does not exist yet.
77
+
78
+ ## Boundaries
79
+
80
+ Never write in `.factory/issues/` directly, never commit, and never run `factory run implement`. When the spec
81
+ is saved, tell the operator the next steps: review it, commit it and push it on the main branch, then run
82
+ `factory run implement --issue <slug>`.