@clemrig/factory 0.6.0 → 0.7.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 (68) hide show
  1. package/README.md +61 -23
  2. package/dist/app/define.js +1 -1
  3. package/dist/app/define.js.map +1 -1
  4. package/dist/app/init.d.ts +1 -0
  5. package/dist/app/init.js +1 -0
  6. package/dist/app/init.js.map +1 -1
  7. package/dist/app/run.d.ts +2 -1
  8. package/dist/app/run.js +16 -4
  9. package/dist/app/run.js.map +1 -1
  10. package/dist/app/workflows/implement.d.ts +1 -1
  11. package/dist/app/workflows/implement.js +332 -132
  12. package/dist/app/workflows/implement.js.map +1 -1
  13. package/dist/app/workflows/issue-save.js +16 -14
  14. package/dist/app/workflows/issue-save.js.map +1 -1
  15. package/dist/cli/help.d.ts +1 -1
  16. package/dist/cli/help.js +4 -2
  17. package/dist/cli/help.js.map +1 -1
  18. package/dist/cli/init.d.ts +3 -2
  19. package/dist/cli/init.js +10 -3
  20. package/dist/cli/init.js.map +1 -1
  21. package/dist/cli/run.js +1 -1
  22. package/dist/cli/run.js.map +1 -1
  23. package/dist/domain/definition.d.ts +2 -0
  24. package/dist/domain/definition.js +1 -0
  25. package/dist/domain/definition.js.map +1 -1
  26. package/dist/domain/description.d.ts +51 -0
  27. package/dist/domain/description.js +78 -0
  28. package/dist/domain/description.js.map +1 -0
  29. package/dist/domain/plan.d.ts +2 -0
  30. package/dist/domain/plan.js +15 -0
  31. package/dist/domain/plan.js.map +1 -1
  32. package/dist/domain/pull-request.d.ts +42 -8
  33. package/dist/domain/pull-request.js +287 -24
  34. package/dist/domain/pull-request.js.map +1 -1
  35. package/dist/domain/review.d.ts +19 -11
  36. package/dist/domain/review.js +42 -21
  37. package/dist/domain/review.js.map +1 -1
  38. package/dist/domain/spec.js +12 -4
  39. package/dist/domain/spec.js.map +1 -1
  40. package/dist/domain/verification.d.ts +0 -2
  41. package/dist/domain/verification.js.map +1 -1
  42. package/dist/system/browser.d.ts +29 -0
  43. package/dist/system/browser.js +84 -0
  44. package/dist/system/browser.js.map +1 -0
  45. package/dist/system/checks.d.ts +5 -6
  46. package/dist/system/checks.js +3 -3
  47. package/dist/system/checks.js.map +1 -1
  48. package/dist/system/git.d.ts +9 -15
  49. package/dist/system/git.js +92 -100
  50. package/dist/system/git.js.map +1 -1
  51. package/dist/system/github.d.ts +15 -0
  52. package/dist/system/github.js +36 -2
  53. package/dist/system/github.js.map +1 -1
  54. package/dist/system/issues.d.ts +5 -2
  55. package/dist/system/issues.js +5 -3
  56. package/dist/system/issues.js.map +1 -1
  57. package/dist/system/run-files.d.ts +22 -2
  58. package/dist/system/run-files.js +78 -4
  59. package/dist/system/run-files.js.map +1 -1
  60. package/dist/system/templates.d.ts +3 -2
  61. package/dist/system/templates.js +8 -3
  62. package/dist/system/templates.js.map +1 -1
  63. package/package.json +3 -3
  64. package/prompts/implement/describe.md +74 -0
  65. package/prompts/implement/implement.md +25 -8
  66. package/prompts/implement/plan.md +35 -7
  67. package/prompts/implement/review.md +43 -16
  68. package/templates/init/factory.ts +23 -5
@@ -1 +1 @@
1
- {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/system/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,gGAAgG;AAChG,KAAK,UAAU,EAAE,CACf,GAAW,EACX,IAAc,EACd,KAAc;IAEd,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,EACf,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,CACN,CAAC;IACF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CACnE,CAAC;IACJ,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW;IAC/C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACvE,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,WAAwE;IAExE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CACrB,MAAM,EAAE,CAAC,GAAG,EAAE;QACZ,IAAI;QACJ,MAAM;QACN,QAAQ;QACR,IAAI;QACJ,SAAS;QACT,MAAM;QACN,QAAQ;QACR,YAAY;KACb,CAAC,CACkC,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,EAAE,CACN,GAAG,EACH;YACE,IAAI;YACJ,MAAM;YACN,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YACvB,SAAS;YACT,KAAK;YACL,aAAa;YACb,GAAG;SACJ,EACD,IAAI,CACL,CAAC;QACF,OAAO,QAAQ,CAAC,GAAG,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,CACP,GAAG,EACH;QACE,IAAI;QACJ,QAAQ;QACR,QAAQ;QACR,IAAI;QACJ,QAAQ;QACR,IAAI;QACJ,SAAS;QACT,KAAK;QACL,aAAa;QACb,GAAG;KACJ,EACD,IAAI,CACL,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/system/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,gGAAgG;AAChG,KAAK,UAAU,EAAE,CACf,GAAW,EACX,IAAc,EACd,KAAc,EACd,SAAS,GAAG,MAAM;IAElB,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,EACf,GAAG,EACH,SAAS,EACT,SAAS,EACT,KAAK,CACN,CAAC;IACF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CACnE,CAAC;IACJ,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW;IAC/C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACvE,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,4CAA4C;AAC5C,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW;IACvC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9D,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,MAAM,EAAE,CAAC,CAAC;IAC1E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAW;IAEX,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,KAAK,CACpC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CACrB,CAAC;IACzC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,KAAK,QAAQ,EAAE,CAAC;AAClD,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,WAAwE;IAExE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CACrB,MAAM,EAAE,CAAC,GAAG,EAAE;QACZ,IAAI;QACJ,MAAM;QACN,QAAQ;QACR,IAAI;QACJ,SAAS;QACT,MAAM;QACN,QAAQ;QACR,YAAY;KACb,CAAC,CACkC,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,EAAE,CACN,GAAG,EACH;YACE,IAAI;YACJ,MAAM;YACN,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YACvB,SAAS;YACT,KAAK;YACL,aAAa;YACb,GAAG;SACJ,EACD,IAAI,CACL,CAAC;QACF,OAAO,QAAQ,CAAC,GAAG,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,CACP,GAAG,EACH;QACE,IAAI;QACJ,QAAQ;QACR,QAAQ;QACR,IAAI;QACJ,QAAQ;QACR,IAAI;QACJ,SAAS;QACT,KAAK;QACL,aAAa;QACb,GAAG;KACJ,EACD,IAAI,CACL,CAAC;AACJ,CAAC;AAED,wCAAwC;AACxC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,GAAW,EACX,WAAmB,EACnB,IAAY;IAEZ,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAc,EACd,WAAmB,EACnB,IAAY,EACZ,MAAgB;IAEhB,MAAM,EAAE,CACN,MAAM,EACN;QACE,IAAI;QACJ,MAAM;QACN,WAAW;QACX,aAAa;QACb,GAAG;QACH,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;KAClD,EACD,IAAI;IACJ,4CAA4C;IAC5C,OAAO,CACR,CAAC;AACJ,CAAC"}
@@ -1,4 +1,6 @@
1
- export type ArtifactKind = "issue" | "spec" | "plan";
1
+ /** An issue's files: a folder with none of them is not an issue. */
2
+ declare const artifactKinds: readonly ["issue", "spec", "plan"];
3
+ export type ArtifactKind = (typeof artifactKinds)[number];
2
4
  /** Where the issues are, relative to the repository. */
3
5
  export declare const issuesPath: string;
4
6
  /** `.factory/issues/<slug>/<kind>.md`, relative to the repository: the only place that names these paths. */
@@ -18,9 +20,10 @@ export interface IssueFolder {
18
20
  export declare function listIssueFolders(repository: string): Promise<IssueFolder[]>;
19
21
  export declare function writeArtifact(repository: string, slug: string, kind: ArtifactKind, text: string): Promise<string>;
20
22
  export declare function hasArtifact(repository: string, slug: string, kind: ArtifactKind): Promise<boolean>;
21
- /** Whether `slug` names an issue: a folder with its issue.md, spec.md or plan.md. */
23
+ /** Whether `slug` names an issue: a folder with one of its files. */
22
24
  export declare function isIssue(repository: string, slug: string): Promise<boolean>;
23
25
  /** The artifact's text, or nothing when the issue has none. */
24
26
  export declare function readArtifact(repository: string, slug: string, kind: ArtifactKind): Promise<string | undefined>;
25
27
  /** A draft handed over by an agent, wherever it wrote it. */
26
28
  export declare function readDraft(path: string): Promise<string>;
29
+ export {};
@@ -1,5 +1,7 @@
1
1
  import { access, mkdir, readdir, readFile, stat, writeFile, } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
+ /** An issue's files: a folder with none of them is not an issue. */
4
+ const artifactKinds = ["issue", "spec", "plan"];
3
5
  /** Where the issues are, relative to the repository. */
4
6
  export const issuesPath = join(".factory", "issues");
5
7
  /** `.factory/issues/<slug>/<kind>.md`, relative to the repository: the only place that names these paths. */
@@ -20,7 +22,7 @@ export async function listIssueFolders(repository) {
20
22
  continue;
21
23
  const files = await readdir(join(root, entry.name));
22
24
  // A folder without its files is not an issue (an abandoned one, say).
23
- if (!["issue.md", "spec.md", "plan.md"].some((file) => files.includes(file)))
25
+ if (!artifactKinds.some((kind) => files.includes(`${kind}.md`)))
24
26
  continue;
25
27
  const changes = await Promise.all([".", ...files].map((file) => stat(join(root, entry.name, file)).then(({ mtimeMs }) => mtimeMs,
26
28
  // An editor's temporary file may go between the listing and now.
@@ -53,9 +55,9 @@ export async function writeArtifact(repository, slug, kind, text) {
53
55
  export async function hasArtifact(repository, slug, kind) {
54
56
  return access(join(repository, artifactPath(slug, kind))).then(() => true, () => false);
55
57
  }
56
- /** Whether `slug` names an issue: a folder with its issue.md, spec.md or plan.md. */
58
+ /** Whether `slug` names an issue: a folder with one of its files. */
57
59
  export async function isIssue(repository, slug) {
58
- for (const kind of ["issue", "spec", "plan"])
60
+ for (const kind of artifactKinds)
59
61
  if (await hasArtifact(repository, slug, kind))
60
62
  return true;
61
63
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"issues.js","sourceRoot":"","sources":["../../src/system/issues.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,KAAK,EACL,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAI1C,wDAAwD;AACxD,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAErD,6GAA6G;AAC7G,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,IAAkB;IAC3D,OAAO,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;AAC9C,CAAC;AAcD,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAAkB;IAElB,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAChE,CAAC,KAA4B,EAAE,EAAE;QAC/B,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACvC,MAAM,KAAK,CAAC;IACd,CAAC,CACF,CAAC;IACF,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YAAE,SAAS;QACnC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACpD,sEAAsE;QACtE,IACE,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAExE,SAAS;QACX,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CACrC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO;QACxB,iEAAiE;QACjE,CAAC,KAA4B,EAAE,EAAE;YAC/B,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,CAAC,CAAC;YACtC,MAAM,KAAK,CAAC;QACd,CAAC,CACF,CACF,CACF,CAAC;QACF,4DAA4D;QAC5D,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CACpE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EACpB,CAAC,KAAc,EAAE,EAAE,CAAC,CAAC;YACnB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CACH,CAAC;QACF,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,CAAC,MAAM,IAAI,KAAK;gBACjB,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE;gBACvB,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YAChC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;YAClC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE;SACxD,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,UAAkB,EAClB,IAAY,EACZ,IAAkB,EAClB,IAAY;IAEZ,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,MAAM,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAAkB,EAClB,IAAY,EACZ,IAAkB;IAElB,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAC5D,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACZ,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,UAAkB,EAClB,IAAY;IAEZ,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAU;QACnD,IAAI,MAAM,WAAW,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IAC7D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAkB,EAClB,IAAY,EACZ,IAAkB;IAElB,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACnE,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACtE,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"issues.js","sourceRoot":"","sources":["../../src/system/issues.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,24 @@
1
+ import type { CheckResult } from "../domain/verification.js";
2
+ import type { PassedCheck } from "./checks.js";
3
+ /** A check that passed, and where the run kept what it wrote, for the review. */
4
+ export type KeptCheck = CheckResult & {
5
+ outputFile: string;
6
+ };
1
7
  /** Keeps `text` in the run's directory, at `path` within it; returns where, absolute. */
2
8
  export declare function keepInRun(runDir: string, path: string, text: string): Promise<string>;
3
- /** A check's name as part of a file name. */
4
- export declare function fileName(name: string): string;
9
+ /** Keeps what each check wrote in `checks/<n>-<name>.log` of the run's directory. */
10
+ export declare function keepCheckOutputs(runDir: string, passed: PassedCheck[]): Promise<KeptCheck[]>;
11
+ /**
12
+ * Keeps what a failed check wrote in `checks/failed-<n>-<name>.log`, `n`
13
+ * counting the run's failures, resumptions included; returns where, absolute.
14
+ */
15
+ export declare function keepFailedCheck(runDir: string, name: string, output: string): Promise<string>;
16
+ /** The run's folder where the describing agent puts its screenshots, created empty. */
17
+ export declare function screenshotsFolder(runDir: string): Promise<string>;
18
+ /**
19
+ * What is wrong with the screenshots `files` of `folder`: a folder or a file
20
+ * that is a link (which could lead anywhere on the machine), a file missing,
21
+ * not an image, too large, or already named, under another name or another
22
+ * case of it, which `gh` refuses.
23
+ */
24
+ export declare function screenshotProblems(folder: string, files: string[], maxBytes: number): Promise<string[]>;
@@ -1,5 +1,5 @@
1
- import { mkdir, writeFile } from "node:fs/promises";
2
- import { dirname, join } from "node:path";
1
+ import { lstat, mkdir, open, readdir, realpath, writeFile, } from "node:fs/promises";
2
+ import { basename, dirname, join } from "node:path";
3
3
  /** Keeps `text` in the run's directory, at `path` within it; returns where, absolute. */
4
4
  export async function keepInRun(runDir, path, text) {
5
5
  const file = join(runDir, path);
@@ -7,8 +7,82 @@ export async function keepInRun(runDir, path, text) {
7
7
  await writeFile(file, text);
8
8
  return file;
9
9
  }
10
- /** A check's name as part of a file name. */
11
- export function fileName(name) {
10
+ /** Keeps what each check wrote in `checks/<n>-<name>.log` of the run's directory. */
11
+ export function keepCheckOutputs(runDir, passed) {
12
+ return Promise.all(passed.map(async ({ output, ...check }, index) => ({
13
+ ...check,
14
+ outputFile: await keepInRun(runDir, `checks/${index + 1}-${safeName(check.name)}.log`, output),
15
+ })));
16
+ }
17
+ /**
18
+ * Keeps what a failed check wrote in `checks/failed-<n>-<name>.log`, `n`
19
+ * counting the run's failures, resumptions included; returns where, absolute.
20
+ */
21
+ export async function keepFailedCheck(runDir, name, output) {
22
+ const kept = await readdir(join(runDir, "checks")).catch(() => []);
23
+ const failures = kept.filter((file) => file.startsWith("failed-")).length;
24
+ return keepInRun(runDir, `checks/failed-${failures + 1}-${safeName(name)}.log`, output);
25
+ }
26
+ /** A name with only the characters a file name may safely hold. */
27
+ function safeName(name) {
12
28
  return name.replace(/[^A-Za-z0-9._-]+/g, "-");
13
29
  }
30
+ /** The run's folder where the describing agent puts its screenshots, created empty. */
31
+ export async function screenshotsFolder(runDir) {
32
+ const folder = join(runDir, "screenshots");
33
+ await mkdir(folder, { recursive: true });
34
+ return folder;
35
+ }
36
+ /** The first bytes of a PNG, JPEG, GIF or WebP image. */
37
+ function isImage(start) {
38
+ const ascii = (from, to) => start.subarray(from, to).toString("latin1");
39
+ return (ascii(0, 8) === "\x89PNG\r\n\x1a\n" ||
40
+ ascii(0, 3) === "\xff\xd8\xff" ||
41
+ ascii(0, 4) === "GIF8" ||
42
+ (ascii(0, 4) === "RIFF" && ascii(8, 12) === "WEBP"));
43
+ }
44
+ /**
45
+ * What is wrong with the screenshots `files` of `folder`: a folder or a file
46
+ * that is a link (which could lead anywhere on the machine), a file missing,
47
+ * not an image, too large, or already named, under another name or another
48
+ * case of it, which `gh` refuses.
49
+ */
50
+ export async function screenshotProblems(folder, files, maxBytes) {
51
+ const real = await realpath(folder).catch(() => undefined);
52
+ if (real !== join(await realpath(dirname(folder)), basename(folder)))
53
+ return [`screenshots: ${folder} must be the run's folder, not a link`];
54
+ const problems = [];
55
+ const named = new Map();
56
+ // A name given twice is the description's problem.
57
+ for (const file of new Set(files)) {
58
+ const path = join(folder, file);
59
+ const found = await lstat(path).catch(() => undefined);
60
+ if (!found?.isFile()) {
61
+ problems.push(`screenshots: ${file} is not a file of ${folder}`);
62
+ continue;
63
+ }
64
+ const identity = `${found.dev}:${found.ino}`;
65
+ const first = named.get(identity);
66
+ if (first !== undefined) {
67
+ problems.push(`screenshots: ${file} and ${first} are the same file`);
68
+ continue;
69
+ }
70
+ named.set(identity, file);
71
+ if (found.size > maxBytes) {
72
+ problems.push(`screenshots: ${file} has ${found.size} bytes, over ${maxBytes}`);
73
+ continue;
74
+ }
75
+ const handle = await open(path);
76
+ const start = Buffer.alloc(12);
77
+ try {
78
+ await handle.read(start, 0, 12, 0);
79
+ }
80
+ finally {
81
+ await handle.close();
82
+ }
83
+ if (!isImage(start))
84
+ problems.push(`screenshots: ${file} is not a PNG, JPEG, GIF or WebP image`);
85
+ }
86
+ return problems;
87
+ }
14
88
  //# sourceMappingURL=run-files.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-files.js","sourceRoot":"","sources":["../../src/system/run-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAc,EACd,IAAY,EACZ,IAAY;IAEZ,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"run-files.js","sourceRoot":"","sources":["../../src/system/run-files.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Creates `.factory/` in `cwd` from the package's templates, its `package.json`
3
- * pinned to this factory version, and the `issue` skill. An existing
4
- * `.factory/` or skill is refused, with nothing written.
3
+ * pinned to this factory version and to the agents' browser command line, and
4
+ * the `issue` skill. An existing `.factory/` or skill is refused, with nothing
5
+ * written.
5
6
  */
6
7
  export declare function createFromTemplates(cwd: string): Promise<{
7
8
  factoryDir: string;
@@ -1,5 +1,6 @@
1
1
  import { cp, lstat, mkdir, readFile, readlink, rename, symlink, writeFile, } from "node:fs/promises";
2
2
  import { basename, dirname, join, relative, resolve } from "node:path";
3
+ import { browserPackage } from "./browser.js";
3
4
  /** Both `src/system/` and `dist/system/` sit two levels below the package root. */
4
5
  const root = new URL("../../", import.meta.url);
5
6
  /** The `issue` skill: read by Pi and Codex there, by Claude Code through a folder link. */
@@ -55,8 +56,9 @@ async function skillPlaces(cwd) {
55
56
  }
56
57
  /**
57
58
  * Creates `.factory/` in `cwd` from the package's templates, its `package.json`
58
- * pinned to this factory version, and the `issue` skill. An existing
59
- * `.factory/` or skill is refused, with nothing written.
59
+ * pinned to this factory version and to the agents' browser command line, and
60
+ * the `issue` skill. An existing `.factory/` or skill is refused, with nothing
61
+ * written.
60
62
  */
61
63
  export async function createFromTemplates(cwd) {
62
64
  const factoryDir = join(cwd, ".factory");
@@ -80,7 +82,10 @@ export async function createFromTemplates(cwd) {
80
82
  await writeFile(join(factoryDir, "package.json"), `${JSON.stringify({
81
83
  private: true,
82
84
  type: "module",
83
- dependencies: { "@clemrig/factory": version },
85
+ dependencies: {
86
+ "@clemrig/factory": version,
87
+ [browserPackage.name]: browserPackage.version,
88
+ },
84
89
  }, null, 2)}\n`);
85
90
  await mkdir(dirname(skill.path), { recursive: true });
86
91
  await cp(new URL("templates/skills/issue/", root), skill.path, {
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/system/templates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/system/templates.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clemrig/factory",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
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": {
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@clemrig/factory-ui": "0.1.0",
43
- "@clemrig/flow": "0.6.0",
44
- "@clemrig/flow-ui": "0.4.1"
43
+ "@clemrig/flow": "0.7.0",
44
+ "@clemrig/flow-ui": "0.5.0"
45
45
  }
46
46
  }
@@ -0,0 +1,74 @@
1
+ You describe an approved change for its pull request. Its reader reviews it days later and remembers nothing of
2
+ the issue: from the pull request alone, they must understand what the change does, how it works, how dangerous it
3
+ is to merge, and see it when it shows. You never change the repository. Write every text of your answer in the
4
+ language of the spec's content, even when the request, the code or these instructions use another; keep code,
5
+ paths and identifiers as they are.
6
+
7
+ Read the repository's agent instructions: `AGENTS.md` at the root and in the directories the change touches.
8
+ Ignore `.factory/`, except the files this request names.
9
+
10
+ The request gives the spec, the plan, the change, the checks that passed, the review that approved it and
11
+ `deviations`, where the implementation departed from the plan:
12
+
13
+ - `changes` lists the changed files with their added and removed lines. A small change comes with its whole diff in
14
+ `diff`; a large one (`large` is true) with `diffFile`, the path of its diff.
15
+ - `checks` gives each check's command and `outputFile`, where the run kept what it wrote.
16
+
17
+ Read the code: describe what the change does, not what anyone said it does. The pull request already shows, from
18
+ the run, the spec's objective, each acceptance criterion with the review's evidence, the checks, the review's
19
+ findings, the deviations and the plan's risks: do not repeat them. When the review still asks for changes, the
20
+ operator delivers the change anyway and the pull request lists them as open: weigh them in `danger`, without
21
+ listing them again.
22
+
23
+ Write for that reader: name things by what they do, an identifier only beside its meaning, and say what each item
24
+ means for the merge. Be brief: a sentence or two per item, the details a reviewer finds in the code left there.
25
+ Size everything to the change. Give as many items as it has, no more: if removing one loses nothing, remove it. A
26
+ one-line fix may have a single change, no visual and a single group of files.
27
+
28
+ Answer with:
29
+
30
+ - `changes`: each change of behavior, as a user, an API client or an operator observes it, one item each, starting
31
+ with a few words that name it. A change to what already existed, beyond what the spec adds, is an item of its
32
+ own that says so: a reviewer must not miss it.
33
+ - `visuals`: the views a reviewer needs to understand how it works; none when the text suffices. Each has a
34
+ `caption`, what it shows in a sentence, and its `content`, without code fences:
35
+ - `mermaid`: how components interact, or how control or data flows, as a `sequenceDiagram` or a `flowchart`
36
+ (`flowchart TD` beyond six nodes, which stays readable). Keep the syntax simple and quote labels that hold
37
+ punctuation: GitHub draws an invalid diagram as an error.
38
+ - `diff`: what changes in a shape that already exists, such as a call tree, a component tree, a file tree or a
39
+ state machine; unchanged lines start with a space, added ones with `+`, removed ones with `-`.
40
+ - `text`: pseudocode, a call tree or a file tree.
41
+
42
+ Pick the smallest view that makes its point, with only the calls, files, states and boundaries that matter.
43
+ - `danger`, what merging risks, a sentence or two per field:
44
+ - `door`: `two_way` when reverting the merge walks the change back; `one_way` when it does not, for instance a
45
+ migration that transforms or deletes data, a published contract or format that others rely on, a message
46
+ sent or an external system changed. `reason`: why.
47
+ - `blastRadius`: one word for how far a defect of this change would reach; `ramifications`: what would break,
48
+ and for whom.
49
+ - `rollback`: how to undo the change once merged: a revert, a data restore, manual steps.
50
+ - `afterMerge`: what the operator must do once it is merged, such as a migration to run, a setting to change or
51
+ a package to publish; empty if nothing.
52
+ - `guide`: `start`, the changed file to read first and why; `groups`, the changed files in the order to read them,
53
+ each group with a short `title` such as "Core logic", "Wiring", "Tests" or "Docs". Give each file once, with its
54
+ path as `changes` gives it; the pull request lists the files you leave out under "Other files".
55
+ - `screenshots`, or, without any, `noScreenshots` with the reason; leave `noScreenshots` out when there are some.
56
+
57
+ Only `visuals` hold code fences' content: write no code fence, of backticks or tildes, or HTML comment anywhere
58
+ else. The pull request's body must stay under 60,000 characters.
59
+
60
+ ## Screenshots
61
+
62
+ When the change shows in a web interface, take screenshots of its new state: the screens and states a reviewer
63
+ must see. Start the application as the repository's instructions say. Use the request's `browser` when it gives
64
+ one, a command line (run it with `--help` first), or else the browser tools you have. Do not change data you did
65
+ not create: to show a state, use what the repository's instructions provide for tests, or create your own data.
66
+ Save each image in the folder `screenshots` names, then give its file name, starting with a letter or a digit and
67
+ made of letters, digits, `.`, `-` and `_`, and its caption, in a sentence: PNG, JPEG, GIF or WebP, 10 MB at most,
68
+ 50 at most, each a file of its own. Stop everything you started, servers and browsers, before you answer.
69
+
70
+ When `repository.public` is true, anyone can see these images: show only test or seed data, never a secret, a
71
+ token or a person's data; when you cannot, take none and say why.
72
+
73
+ Take none when nothing visible changed, when the application does not start or when you have no browser, and give
74
+ the reason in `noScreenshots`.
@@ -1,21 +1,38 @@
1
- You implement an approved plan in this repository.
1
+ You implement an approved plan in this repository. Write every text of your answer in the language of the spec's
2
+ content, even when the request, the code or these instructions use another; keep code, paths and identifiers as
3
+ they are.
2
4
 
3
5
  First read the repository's agent instructions: `AGENTS.md` at the root and in each directory you touch.
4
6
  Follow their conventions and validation guidance. Ignore `.factory/` and never change it.
5
7
 
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
+ The request gives the spec, approved and unchanging, and the plan. The plan is your guide, not a script: its
9
+ `existing` says what the code already does and must keep doing, and each step's `cases` the situations it must
10
+ handle and test besides its main path. When the code shows a better way than a step describes, take it and say so
11
+ in `deviations`. Implement the spec through the plan, tests included, and run the relevant checks yourself before
12
+ answering.
13
+
14
+ When the change shows in a web interface, check it in a browser before answering. Start the application as the
15
+ repository's instructions say. Use the request's `browser` when it gives one, a command line (run it with `--help`
16
+ first), or else the browser tools you have. Do not change data you did not create: when the application needs
17
+ data, use what the repository's instructions provide for tests, or create your own. Stop everything you started,
18
+ servers and browsers, before you answer.
8
19
 
9
20
  Never commit, switch branches or push: the run commits, pushes and opens the pull request itself, and it stops
10
21
  if you commit or switch branches.
11
22
 
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.
23
+ When the request contains `feedback`, it reports what failed after your previous answer, a check or the review.
24
+ First find why the change let each defect happen. When defects come from the same mechanism, such as a state
25
+ machine, the order locks are taken in or the way texts are built, or when a fix would add a special case for one
26
+ situation, change the mechanism instead, reworking that part of your change if needed: prefer the fix that leaves
27
+ less code and fewer special cases, a guard per case is the sign of a wrong mechanism. Fix each defect wherever the
28
+ change has it, not only where the feedback points, then test each place. The review
29
+ may add findings that do not block: fix them too when that is safe and stays within the spec, and say in your
30
+ summary which you left and why. Then answer again.
14
31
 
15
32
  Answer with:
16
33
 
17
34
  - `summary`: what you changed, in a few sentences.
18
35
  - `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.
36
+ - `deviations`: every place where the change departs from the plan, since the plan and not only in your last
37
+ answer, and why; empty if nowhere. The pull request shows them to a reader who knows neither the plan nor the
38
+ code: a sentence or two each, naming things by what they do, an identifier only beside its meaning.
@@ -1,4 +1,6 @@
1
- You plan the implementation of an approved spec in this repository. You change nothing.
1
+ You plan the implementation of an approved spec in this repository. You change nothing. Write every text of your
2
+ answer in the language of the spec's content, except `commit`, in English, even when the request, the code or
3
+ these instructions use another; keep code, paths and identifiers as they are.
2
4
 
3
5
  Before planning, read the repository's agent instructions: `AGENTS.md` at the root and in each directory the
4
6
  change will touch, and follow them. Ignore `.factory/`: the other issues there are history, not the current
@@ -8,13 +10,39 @@ The request gives the issue's slug and its spec. The spec is approved and does n
8
10
  nothing more. When something is unclear, choose the interpretation most consistent with the code and record it
9
11
  in `risks`.
10
12
 
11
- Answer with a plan of verifiable steps:
13
+ ## Explore first
14
+
15
+ Before writing a step, find out how the code works where the spec changes it. For each area the spec touches,
16
+ such as an application, a layer or a feature, establish from the code itself, not only its documentation:
17
+
18
+ - the mechanisms involved and their states and transitions: a job's life, a queue, a cache, a shared resource;
19
+ - their invariants: transactions, locks and the order they are taken in, idempotence, what must stay consistent;
20
+ - the conventions the change must follow: texts and their plural forms, errors, API shapes, migrations;
21
+ - the tests and tools that prove such behavior in this repository.
22
+
23
+ When the spec touches several areas and you can launch sub-agents, give each, five at most, one area: the spec,
24
+ the questions above for that area, and the instruction to report facts with the file and symbol they come from,
25
+ to change nothing and to launch no agent itself. Check against the code the facts the plan depends on.
26
+
27
+ ## The plan
28
+
29
+ The plan guides the implementation; it does not write it. Say what must be true and where, precisely enough that
30
+ nothing is forgotten: name a function, a file or an approach only when the code or the spec settles it, and leave
31
+ the other choices to the implementing agent, who reads the code as it goes and may find a better way.
32
+
33
+ Answer with:
12
34
 
13
35
  - `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.
36
+ - `existing`: what the code already does that the change builds on or must keep, as the exploration found it:
37
+ each mechanism, invariant, convention or test tool with where it lives; empty when the change depends on
38
+ nothing of the kind.
39
+ - `steps`: each names the acceptance criteria it serves (`AC1`…), the files you expect it to create or change,
40
+ `cases` and the tests that prove it. Every acceptance criterion is served by at least one step.
41
+ - `cases`: the situations the step must handle besides its main path, each with what must happen: failures,
42
+ interruptions and recoveries, concurrent requests, a resource that changes or disappears meanwhile, none, one
43
+ or many items, permissions. Only those the step meets; empty when there are none.
16
44
  - `commit`: the conventional commit subject of the whole change, for example
17
45
  `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.
46
+ - `risks`: what could go wrong and what you assumed; empty if nothing. The pull request shows them to a reader
47
+ who knows neither the spec nor the code: a sentence or two each, naming things by what they do, an identifier
48
+ only beside its meaning, and what each means for the change.
@@ -1,4 +1,6 @@
1
- You review a change against its approved spec, independently. You never change the repository.
1
+ You review a change against its approved spec, independently. You never change the repository. Write every text
2
+ of your answer in the language of the spec's content, even when the request, the code or these instructions use
3
+ another; keep code, paths and identifiers as they are.
2
4
 
3
5
  Read the repository's agent instructions: `AGENTS.md` at the root and in the directories the change touches.
4
6
  Ignore `.factory/`, except the files this request names: it holds other issues' history and agents' outputs, which
@@ -12,32 +14,57 @@ The request gives the spec, the change and the repository's checks, which all pa
12
14
 
13
15
  Do not take anything on trust: verify each acceptance criterion in the code and the tests, reading files beyond the
14
16
  diff when needed. Look for unmet criteria, defects, regressions, missing or weak tests, security problems and
15
- departures from the repository's conventions. Follow every path the change must handle, failures, interruptions
16
- and recoveries included, not only the one that succeeds.
17
+ departures from the repository's conventions. Follow every path the change must handle, failures, interruptions,
18
+ concurrent requests and recoveries included, not only the one that succeeds: for each mechanism the change touches,
19
+ such as a state machine, a queue, a lock or a cache, go through each of its states and transitions.
20
+
21
+ When you find a defect, look for the same defect everywhere in the change: every text that shows a count, every
22
+ path that takes the same locks, every transition of the same mechanism. Report it once, naming each place, so that
23
+ it is fixed everywhere at once; when several defects come from one mechanism, report the mechanism, with the
24
+ defects as its occurrences: the fix belongs there, not in a guard per case.
17
25
 
18
26
  If you can run commands, run what helps you judge: targeted tests, the scripts the change adds, small
19
- reproductions. Write temporary files only in the system's temporary directory. Never modify, stage, commit or
20
- delete anything in the repository: the run compares it before and after your review, restores what changed and
21
- starts the review again.
27
+ reproductions. When the change shows in a web interface, check it in a browser: start the application as the
28
+ repository's instructions say, and use the request's `browser` when it gives one, a command line (run it with
29
+ `--help` first), or else the browser tools you have. Do not change data you did not create: when the application
30
+ needs data, use what the repository's instructions provide for tests, or create your own. Write temporary files
31
+ only in the system's temporary directory, and stop everything you started, servers and browsers, before you
32
+ answer. Never modify, stage, commit or delete anything in the repository: the run compares it before and after
33
+ your review, restores what changed and starts the review again.
22
34
 
23
- When the change is large and you can launch sub-agents, you may give a few of them, five at most, one angle each
24
- that this change calls for: for instance its conformance to the spec, its failure and recovery paths, its data and
25
- migrations, its security or its tests. Give each the spec, its angle, the files concerned and where to read the
26
- diff, and tell it to report its findings with their evidence, to change nothing and to launch no agent itself.
27
- Their reports come back to you: check them, then give one answer for the whole change.
35
+ When the change is large (`large` is true), or spans several applications or layers, and you can launch
36
+ sub-agents, split the review between them, five at most: each takes one part of the change, such as an
37
+ application, a layer or a feature, and one more takes the paths that cross the parts: failures, interruptions,
38
+ concurrent requests and recoveries. Give each the spec, its part, the files concerned and where to read the diff,
39
+ and tell it to report its findings with their evidence, to look for each defect's other occurrences, to change
40
+ nothing and to launch no agent itself. Check their reports, then give one answer for the whole change.
28
41
 
29
42
  Answer with:
30
43
 
31
- - `criteria`: each acceptance criterion once, `met` or `not_met`, with its evidence (file, test, behavior).
44
+ - `criteria`: each acceptance criterion once, `met` or `not_met`, with its evidence: the decisive proof (file,
45
+ test, behavior), without narrating how you found it. The pull request shows it to its reader.
32
46
  - `findings`: each with its `nature`, its `file` when relevant and a `summary` that states the trigger, then the
33
- consequence. The nature alone decides whether the finding blocks the change:
47
+ consequence, for a reader who has not read the code: name things by what they do, an identifier only beside its
48
+ meaning. The nature alone decides whether the finding blocks the change:
34
49
  - blocking: `incorrect_behavior` (the change does the wrong thing in a situation it must handle), `data_loss`,
35
50
  `outage`, `security`, `regression` (something that worked no longer does), `spec_violation` (the change
36
51
  contradicts the spec's scope or constraints);
37
52
  - not blocking: `weak_test`, `maintainability`, `documentation`.
38
53
 
39
54
  A defect whose trigger is a situation the change must handle, as the spec and the change's own paths (a
40
- recovery, say) define them, is `incorrect_behavior` however rare that situation is. Choose the nature that
41
- describes the defect, not the severity you would like it to have.
55
+ recovery, say) define them, is `incorrect_behavior` however rare that situation is; so is a text the user reads
56
+ that is wrong, such as a missing plural. Choose the nature that describes the defect, not the severity you would
57
+ like it to have.
58
+
59
+ ## The previous review
60
+
61
+ From the second round on, once you have answered, a request in this conversation gives `previous`, the review of
62
+ the change's previous version. Check each unmet criterion and finding it gave against the code as it is now: when
63
+ the change fixes it, put it in `resolved`, with its `summary` and the `evidence` of the fix; when it still holds,
64
+ keep it in `findings`, with the same nature unless the code shows that nature was wrong, which its summary then
65
+ says. Look at how each was fixed: a fix that adds a special case where the mechanism should change, or that makes
66
+ the change harder to follow without need, is a finding, `maintainability`, or the defect's own nature when the
67
+ mechanism still fails elsewhere. Then answer your whole review again: every criterion, and your findings with the
68
+ previous ones that still hold, each once.
42
69
 
43
- The change is approved only when every criterion is met and no finding is blocking. Write in English.
70
+ The change is approved only when every criterion is met and no finding is blocking.
@@ -7,10 +7,21 @@ const opus = {
7
7
  model: "claude-opus-5-5",
8
8
  thinking: "high",
9
9
  } as const;
10
- const reader = {
10
+ // Explores the code the spec changes, handing areas of a large one to
11
+ // sub-agents (Agent), then plans.
12
+ const planner = {
11
13
  ...opus,
12
- tools: ["Read", "Grep", "Glob"],
13
- timeoutMs: 20 * minutes,
14
+ tools: ["Read", "Grep", "Glob", "Agent"],
15
+ timeoutMs: 30 * minutes,
16
+ } satisfies AgentProfile;
17
+ // Reads the change and runs what checks it: tests, the application in a
18
+ // browser (Playwright CLI, installed in .factory/). The run puts back what it
19
+ // changes in the repository.
20
+ const checker = {
21
+ ...opus,
22
+ tools: ["Read", "Grep", "Glob", "Bash"],
23
+ permissionMode: "dontAsk",
24
+ timeoutMs: 30 * minutes,
14
25
  } satisfies AgentProfile;
15
26
 
16
27
  /**
@@ -24,7 +35,7 @@ export default defineFactory({
24
35
  // The budget of an implement run, in USD; --max-cost-usd changes it for one run.
25
36
  maxCostUsd: 25,
26
37
  profiles: {
27
- plan: reader,
38
+ plan: planner,
28
39
  implement: {
29
40
  ...opus,
30
41
  tools: ["Read", "Grep", "Glob", "Edit", "Write", "Bash"],
@@ -32,7 +43,14 @@ export default defineFactory({
32
43
  permissionMode: "dontAsk",
33
44
  timeoutMs: 60 * minutes,
34
45
  },
35
- review: reader,
46
+ // Splits the review of a large change between sub-agents (Agent).
47
+ review: {
48
+ ...checker,
49
+ tools: [...checker.tools, "Agent"],
50
+ timeoutMs: 60 * minutes,
51
+ },
52
+ // Writes the pull request and takes its screenshots.
53
+ describe: checker,
36
54
  },
37
55
  // This repository's own workflows, run with `factory run <name>`.
38
56
  workflows: [ask],