testeiya 0.8.1 β†’ 0.10.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 (63) hide show
  1. package/PIPELINES.md +153 -19
  2. package/README.md +29 -14
  3. package/dist/prompt/pipeline-report.js +23 -0
  4. package/dist/prompt/pipeline-report.js.map +1 -0
  5. package/dist/prompt/report.js +1 -1
  6. package/dist/prompt/testomat.io.js +2 -2
  7. package/dist/prompt/testomat.io.js.map +1 -1
  8. package/dist/src/args.js +19 -1
  9. package/dist/src/args.js.map +1 -1
  10. package/dist/src/cli.js +4 -2
  11. package/dist/src/cli.js.map +1 -1
  12. package/dist/src/doctor.js +8 -10
  13. package/dist/src/doctor.js.map +1 -1
  14. package/dist/src/langfuse-extension.js +2 -0
  15. package/dist/src/langfuse-extension.js.map +1 -1
  16. package/dist/src/mcp.js +20 -90
  17. package/dist/src/mcp.js.map +1 -1
  18. package/dist/src/pipeline/command-stage.js +2 -2
  19. package/dist/src/pipeline/command-stage.js.map +1 -1
  20. package/dist/src/pipeline/log.js +5 -0
  21. package/dist/src/pipeline/log.js.map +1 -1
  22. package/dist/src/pipeline/overlay.js +217 -0
  23. package/dist/src/pipeline/overlay.js.map +1 -0
  24. package/dist/src/pipeline/pipeline-file.js +67 -5
  25. package/dist/src/pipeline/pipeline-file.js.map +1 -1
  26. package/dist/src/pipeline/pipeline.js +48 -29
  27. package/dist/src/pipeline/pipeline.js.map +1 -1
  28. package/dist/src/pipeline/stage.js +49 -13
  29. package/dist/src/pipeline/stage.js.map +1 -1
  30. package/dist/src/pipeline/state.js +3 -1
  31. package/dist/src/pipeline/state.js.map +1 -1
  32. package/dist/src/pipeline/summary-stage.js +99 -0
  33. package/dist/src/pipeline/summary-stage.js.map +1 -0
  34. package/dist/src/pipeline/task-stage.js +25 -10
  35. package/dist/src/pipeline/task-stage.js.map +1 -1
  36. package/dist/src/pipeline/variables.js +34 -2
  37. package/dist/src/pipeline/variables.js.map +1 -1
  38. package/dist/src/session.js +19 -14
  39. package/dist/src/session.js.map +1 -1
  40. package/package.json +6 -9
  41. package/pipelines/api-testing.yml +9 -6
  42. package/pipelines/issue-test-cases.yml +14 -13
  43. package/pipelines/pr-review.yml +13 -9
  44. package/pipelines/regression.yml +6 -3
  45. package/pipelines/web-testing.yml +13 -12
  46. package/prompt/pipeline-report.ts +23 -0
  47. package/prompt/report.ts +1 -1
  48. package/prompt/testomat.io.ts +4 -4
  49. package/skills/codeceptjs/lint-codeceptjs-tests/SKILL.md +104 -0
  50. package/skills/skills.lock.json +5 -2
  51. package/skills/testomatio/qa-process/testing-workflow/SKILL.md +12 -7
  52. package/skills/testomatio/requirements/catalog-features/SKILL.md +132 -0
  53. package/skills/testomatio/requirements/catalog-features/references/layout.md +43 -0
  54. package/skills/testomatio/requirements/detect-product-mismatches/SKILL.md +146 -0
  55. package/skills/testomatio/requirements/detect-product-mismatches/references/features.md +84 -0
  56. package/skills/testomatio/requirements/detect-product-mismatches/references/layout.md +93 -0
  57. package/skills/testomatio/requirements/wiki-from-code/SKILL.md +58 -71
  58. package/skills/testomatio/requirements/wiki-from-code/references/behaviors.md +42 -0
  59. package/skills/testomatio/requirements/wiki-from-code/references/layout.md +70 -71
  60. package/dist/src/mcp-extension.js +0 -9
  61. package/dist/src/mcp-extension.js.map +0 -1
  62. package/dist/vendor/mcp.js +0 -14801
  63. package/mcp-tools.json +0 -1949
@@ -2,11 +2,11 @@ import { existsSync, readFileSync, rmSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { log } from "./log.js";
4
4
  import { Stage } from "./stage.js";
5
- import { SESSIONS_DIR } from "./state.js";
6
- const RETRY_NOTE = "This stage stopped before it finished. Go on from where you stopped. Files you already wrote are in the pipeline folder.";
5
+ import { CHANGES_FILE, LAST_DIR, SESSIONS_DIR } from "./state.js";
6
+ const RETRY_NOTE = "This stage stopped before it finished. Go on from where you stopped. Files you already wrote are in the stage folder.";
7
7
  /**
8
8
  * An agent stage: a `testeiya task` run. It writes its report to `<id>.md`
9
- * and its verdict to `<id>.json`.
9
+ * and its verdict to `<id>.json`, in its folder.
10
10
  */
11
11
  export class TaskStage extends Stage {
12
12
  result = { field: "report", extension: "md" };
@@ -15,8 +15,8 @@ export class TaskStage extends Stage {
15
15
  }
16
16
  async runItem(context, item, vars) {
17
17
  const { dir } = context;
18
- const report = `${this.id}${item.suffix}.md`;
19
- const envelope = `${this.id}${item.suffix}.json`;
18
+ const report = `${this.folder}/${this.id}${item.suffix}.md`;
19
+ const envelope = `${this.folder}/${this.id}${item.suffix}.json`;
20
20
  rmSync(join(dir, report), { force: true });
21
21
  rmSync(join(dir, envelope), { force: true });
22
22
  const task = this.task(context, vars);
@@ -38,8 +38,9 @@ export class TaskStage extends Stage {
38
38
  const { session } = this.spec;
39
39
  const args = [];
40
40
  // Only the reporting stage posts. Every other stage keeps out of the comment thread.
41
+ // Their reports land in the summary, which is signed once.
41
42
  if (!context.report)
42
- args.push("--no-thread");
43
+ args.push("--no-thread", "--no-default-footer");
43
44
  for (const output of outputs)
44
45
  args.push("-o", output);
45
46
  if (context.report)
@@ -56,20 +57,34 @@ export class TaskStage extends Stage {
56
57
  }
57
58
  /** The task, then where its files are, so the model never guesses a path. */
58
59
  task(context, vars) {
59
- const { dir } = context;
60
- const lines = [`Pipeline folder: ${dir}`];
60
+ const dir = this.dir(context);
61
+ const lines = [`Stage folder: ${dir}`];
61
62
  const wanted = this.inputs();
62
63
  const present = wanted.filter((input) => existsSync(join(dir, input)));
63
64
  const absent = wanted.filter((input) => !present.includes(input));
64
65
  if (present.length > 0)
65
- lines.push(`Read these first: ${present.join(", ")}`);
66
- const outputs = this.spec.outputs.map((output) => vars.expand(output));
66
+ lines.push(`Read these first: ${present.map((input) => join(dir, input)).join(", ")}`);
67
+ const outputs = this.spec.outputs.map((output) => join(dir, vars.expand(output)));
67
68
  if (outputs.length > 0)
68
69
  lines.push(`Write these files: ${outputs.join(", ")}`);
69
70
  for (const input of absent)
70
71
  lines.push(`Not available: ${input} (${context.missing(input)})`);
72
+ const last = this.lastRound(context);
73
+ if (last)
74
+ lines.push(last);
71
75
  return `${vars.expand(this.spec.task ?? "").trim()}\n\n${lines.join("\n")}`;
72
76
  }
77
+ /** A new round updates the last one's result instead of starting over. */
78
+ lastRound(context) {
79
+ const last = join(context.dir, LAST_DIR, this.folder);
80
+ if (!existsSync(last))
81
+ return null;
82
+ let line = `Last round: ${last}. Update its result: keep what still holds, redo what the changes touch.`;
83
+ const changes = join(context.dir, CHANGES_FILE);
84
+ if (existsSync(changes))
85
+ line += ` Changed files: ${changes}`;
86
+ return line;
87
+ }
73
88
  readEnvelope(path) {
74
89
  if (!existsSync(path))
75
90
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"task-stage.js","sourceRoot":"","sources":["../../../src/pipeline/task-stage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task-stage.js","sourceRoot":"","sources":["../../../src/pipeline/task-stage.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,42 @@
1
+ import { Liquid } from "liquidjs";
2
+ /** `${NAME}`, `${NAME:-default}` or `${NAME | filter | filter: arg}`. */
3
+ const REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*)|(\s*\|[^}]*))?\}/g;
4
+ /** Liquid's filters, and ours for URLs. Only expressions: Liquid's tags never run. */
5
+ const liquid = new Liquid({ strictFilters: true });
6
+ liquid.registerFilter("host", (value) => url(value)?.host ?? "");
7
+ liquid.registerFilter("path", (value) => url(value)?.pathname ?? "");
1
8
  /** The environment a pipeline runs in, and `${NAME}` expansion over it. */
2
9
  export class Variables {
3
10
  values;
4
11
  constructor(values) {
5
12
  this.values = values;
6
13
  }
14
+ /** Why the filters in `text` cannot run, or null. */
15
+ static problem(text) {
16
+ for (const [, name, , filters] of text.matchAll(REFERENCE)) {
17
+ if (!filters)
18
+ continue;
19
+ try {
20
+ liquid.evalValueSync(`${name}${filters}`, {});
21
+ }
22
+ catch (err) {
23
+ return `\${${name}${filters}}: ${err.message.split("\n")[0]}`;
24
+ }
25
+ }
26
+ return null;
27
+ }
28
+ /** Whether `text` uses a filter. */
29
+ static filtered(text) {
30
+ return [...text.matchAll(REFERENCE)].some((match) => match[3]);
31
+ }
7
32
  get(name) {
8
33
  return this.values[name];
9
34
  }
10
- /** `${NAME}` and `${NAME:-default}`, the shell's rule: unset is empty. */
35
+ /** `${NAME}` and `${NAME:-default}`, the shell's rule: unset is empty. A `|` runs Liquid filters. */
11
36
  expand(text) {
12
- return text.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g, (_, name, fallback) => {
37
+ return text.replace(REFERENCE, (_, name, fallback, filters) => {
38
+ if (filters)
39
+ return String(liquid.evalValueSync(`${name}${filters}`, this.values) ?? "");
13
40
  const value = this.values[name];
14
41
  if (value)
15
42
  return value;
@@ -38,4 +65,9 @@ export class Variables {
38
65
  return { ...this.values };
39
66
  }
40
67
  }
68
+ function url(value) {
69
+ if (typeof value !== "string" || !URL.canParse(value))
70
+ return null;
71
+ return new URL(value);
72
+ }
41
73
  //# sourceMappingURL=variables.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"variables.js","sourceRoot":"","sources":["../../../src/pipeline/variables.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,MAAM,OAAO,SAAS;IACS;IAA7B,YAA6B,MAAW;QAAX,WAAM,GAAN,MAAM,CAAK;IAAG,CAAC;IAE5C,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,0EAA0E;IAC1E,MAAM,CAAC,IAAY;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,+CAA+C,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,QAAiB,EAAE,EAAE;YAC1G,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;YACxB,OAAO,QAAQ,IAAI,EAAE,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,qDAAqD;IACrD,IAAI,CAAC,KAAU;QACb,OAAO,IAAI,SAAS,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,4EAA4E;IAC5E,YAAY,CAAC,KAA6B;QACxC,MAAM,MAAM,GAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpG,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,CAAC,KAAe;QACrB,MAAM,MAAM,GAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvC,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9C,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,2BAA2B;IAC3B,KAAK;QACH,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;CACF"}
1
+ {"version":3,"file":"variables.js","sourceRoot":"","sources":["../../../src/pipeline/variables.ts"],"names":[],"mappings":"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"}
@@ -1,20 +1,22 @@
1
1
  import { existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { createAgentSession, DefaultResourceLoader, ModelRuntime, SettingsManager, } from "@earendil-works/pi-coding-agent";
2
+ import { createRequire } from "node:module";
3
+ import { dirname, join } from "node:path";
4
+ import { createAgentSession, createCodemodeExtension, createMcpExtension, DefaultResourceLoader, ModelRuntime, SettingsManager, } from "@earendil-works/pi-coding-agent";
4
5
  import { buildSystemPrompt } from "../prompt/system-prompt.js";
5
6
  import { pathClis } from "../prompt/clis.js";
6
7
  import { PACKAGE_ROOT, PI_STATE_DIR, TESTEIYA_HOME } from "./env.js";
7
8
  import { langfuseConfig } from "./langfuse.js";
8
- import { hasMcp, tmsAccess } from "./mcp.js";
9
+ import { hasMcp, mcpConfig, tmsAccess } from "./mcp.js";
9
10
  import { applyEnvKeys, resolveModel } from "./model.js";
10
11
  import { createSetResultTool } from "./result.js";
11
12
  import { sessionModel } from "./sessions.js";
12
13
  // From the package root, never this file's own directory: `../skills` would
13
14
  // resolve to dist/skills, and the filter below would silently drop everything.
14
15
  export const BUNDLED_SKILLS_DIR = join(PACKAGE_ROOT, "skills");
15
- const MCP_EXTENSION = extensionPath("mcp-extension");
16
16
  const ATTRIBUTION_EXTENSION = extensionPath("attribution-extension");
17
17
  const LANGFUSE_EXTENSION = extensionPath("langfuse-extension");
18
+ // The package root: pi loads it through its `pi.extensions` manifest.
19
+ const SUBAGENTS_EXTENSION = dirname(createRequire(import.meta.url).resolve("pi-subagents"));
18
20
  /** The one runtime factory, so every command reads the same auth. */
19
21
  export async function createRuntime() {
20
22
  const runtime = await ModelRuntime.create({
@@ -37,6 +39,7 @@ export function createLoader(options) {
37
39
  settingsManager: options.settingsManager,
38
40
  additionalSkillPaths: [BUNDLED_SKILLS_DIR],
39
41
  additionalExtensionPaths: options.extensionPaths,
42
+ extensionFactories: options.extensionFactories,
40
43
  systemPromptOverride: options.systemPrompt,
41
44
  skillsOverride: (current) => ({
42
45
  skills: current.skills.filter((s) => s.baseDir.startsWith(BUNDLED_SKILLS_DIR)),
@@ -47,19 +50,26 @@ export function createLoader(options) {
47
50
  export async function createTesteiyaSession(options) {
48
51
  const runtime = await createRuntime();
49
52
  const model = resolveModel(runtime, options.model, sessionModel(options.sessionManager));
50
- const settingsManager = SettingsManager.inMemory();
51
- const extensionPaths = [ATTRIBUTION_EXTENSION];
53
+ const settingsManager = SettingsManager.inMemory({
54
+ defaultTools: ["+codemode"],
55
+ // A checkout never gets to add agents, settings or MCP servers of its own.
56
+ defaultProjectTrust: "never",
57
+ });
58
+ const extensionPaths = [ATTRIBUTION_EXTENSION, SUBAGENTS_EXTENSION];
52
59
  if (langfuseConfig())
53
60
  extensionPaths.push(LANGFUSE_EXTENSION);
61
+ // pi's CLI loads these as built-ins; SDK sessions only get what is listed here.
62
+ const extensionFactories = [createCodemodeExtension({ models: false })];
54
63
  const connectedMcps = [];
55
64
  if (hasMcp()) {
56
- extensionPaths.push(MCP_EXTENSION);
65
+ extensionFactories.push(createMcpExtension({ loadConfig: mcpConfig, openUrl: () => { } }));
57
66
  connectedMcps.push("Testomat.io");
58
67
  }
59
68
  const loader = createLoader({
60
69
  cwd: options.cwd,
61
70
  settingsManager,
62
71
  extensionPaths,
72
+ extensionFactories,
63
73
  systemPrompt: () => buildSystemPrompt({
64
74
  cwd: options.cwd,
65
75
  tms: tmsAccess(),
@@ -83,15 +93,10 @@ export async function createTesteiyaSession(options) {
83
93
  settingsManager,
84
94
  sessionManager: options.sessionManager,
85
95
  customTools: [createSetResultTool(options.result)],
86
- // Extensions start their runtime on this event. Without it the MCP adapter
87
- // registers its tools but never connects, and every call answers
88
- // "MCP not initialized".
89
96
  sessionStartEvent: { type: "session_start", reason: "startup" },
90
97
  });
91
- // Starts the extension runtime and fires session_start. createAgentSession
92
- // does not do this β€” pi's own modes do β€” and without it an extension is
93
- // constructed but never initialized: the MCP adapter registers its tools and
94
- // then answers "MCP not initialized" for every call.
98
+ // Starts the extension runtime and fires session_start, where MCP connects.
99
+ // createAgentSession does not do this; pi's own modes do.
95
100
  await session.bindExtensions({
96
101
  mode: "print",
97
102
  onError: (err) => {
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,eAAe,GAIhB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAkB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,4EAA4E;AAC5E,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAE/D,MAAM,aAAa,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;AACrD,MAAM,qBAAqB,GAAG,aAAa,CAAC,uBAAuB,CAAC,CAAC;AACrE,MAAM,kBAAkB,GAAG,aAAa,CAAC,oBAAoB,CAAC,CAAC;AAE/D,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC;QACxC,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC;QAC1C,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IACH,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAC5B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,OAAsB;IACjD,OAAO,IAAI,qBAAqB,CAAC;QAC/B,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ,EAAE,YAAY;QACtB,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,oBAAoB,EAAE,CAAC,kBAAkB,CAAC;QAC1C,wBAAwB,EAAE,OAAO,CAAC,cAAc;QAChD,oBAAoB,EAAE,OAAO,CAAC,YAAY;QAC1C,cAAc,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC5B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;YAC9E,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAuB;IACjE,MAAM,OAAO,GAAG,MAAM,aAAa,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;IAEzF,MAAM,eAAe,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC;IAEnD,MAAM,cAAc,GAAa,CAAC,qBAAqB,CAAC,CAAC;IACzD,IAAI,cAAc,EAAE;QAAE,cAAc,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC9D,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,IAAI,MAAM,EAAE,EAAE,CAAC;QACb,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC;QAC1B,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,eAAe;QACf,cAAc;QACd,YAAY,EAAE,GAAG,EAAE,CACjB,iBAAiB,CAAC;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,SAAS,EAAE;YAChB,SAAS,EAAE,OAAO,CAAC,UAAU,EAAE,cAAc;YAC7C,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;YAC7D,aAAa,EAAE,QAAQ,EAAE;YACzB,aAAa;SACd,CAAC;KACL,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;IAEtB,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,kBAAkB,CAAC;QAC3C,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ,EAAE,YAAY;QACtB,KAAK;QACL,YAAY,EAAE,OAAO;QACrB,cAAc,EAAE,MAAM;QACtB,eAAe;QACf,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,WAAW,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClD,2EAA2E;QAC3E,iEAAiE;QACjE,yBAAyB;QACzB,iBAAiB,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE;KAChE,CAAC,CAAC;IAEH,2EAA2E;IAC3E,wEAAwE;IACxE,6EAA6E;IAC7E,qDAAqD;IACrD,MAAM,OAAO,CAAC,cAAc,CAAC;QAC3B,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,GAAG,CAAC,aAAa,MAAM,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC;QACnF,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC;IACzC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;IACtD,IAAI,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;AACjD,CAAC"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testeiya",
3
- "version": "0.8.1",
3
+ "version": "0.10.0",
4
4
  "description": "AI testing agent β€” QA-focused coding agent for manual and automated tests",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -18,7 +18,6 @@
18
18
  "pipelines",
19
19
  "PIPELINES.md",
20
20
  "skills",
21
- "mcp-tools.json",
22
21
  "README.md",
23
22
  "LICENSE"
24
23
  ],
@@ -31,8 +30,7 @@
31
30
  "scripts": {
32
31
  "start": "npm run build && node dist/src/cli.js",
33
32
  "dev": "./testeiya",
34
- "build": "tsc -p tsconfig.json && npm run build:vendor",
35
- "build:vendor": "esbuild scripts/vendor-entry.ts --bundle --format=esm --platform=node --packages=external --outfile=dist/vendor/mcp.js",
33
+ "build": "tsc -p tsconfig.json",
36
34
  "typecheck": "tsc -p tsconfig.json --noEmit",
37
35
  "prepublishOnly": "npm run build",
38
36
  "test": "npm run build && node --test test/*.test.js"
@@ -46,19 +44,18 @@
46
44
  "pi"
47
45
  ],
48
46
  "dependencies": {
49
- "@earendil-works/pi-ai": "^0.84.3",
50
- "@earendil-works/pi-coding-agent": "^0.84.3",
51
- "@earendil-works/pi-tui": "^0.84.3",
47
+ "@earendil-works/pi-ai": "^1.4.0",
48
+ "@earendil-works/pi-coding-agent": "^1.4.0",
52
49
  "@testomatio/mcp": "^3.1.0",
53
50
  "chalk": "^5.6.2",
54
51
  "dedent": "^1.7.2",
55
- "pi-mcp-adapter": "^2.21.1",
52
+ "liquidjs": "^10.30.0",
53
+ "pi-subagents": "^0.81.0",
56
54
  "typebox": "1.3.7",
57
55
  "yaml": "^2.9.0"
58
56
  },
59
57
  "devDependencies": {
60
58
  "@types/node": "^22.19.19",
61
- "esbuild": "^0.28.1",
62
59
  "tsx": "^4.23.12",
63
60
  "typescript": "^5.9.3"
64
61
  }
@@ -10,30 +10,33 @@ gates:
10
10
  message: Explorbot has no AI provider. Set EXPLORBOT_AI_PROVIDER and its key.
11
11
 
12
12
  env:
13
- EXPLORBOT_OUTPUT: ${PIPELINE_DIR}/explorbot
14
13
  EXPLORBOT_NO_BANNER: "1"
15
14
 
16
15
  stages:
17
16
  - id: review
17
+ title: Pull request review
18
+ emoji: πŸ”
18
19
  session: qa
19
20
  task: |
20
21
  Review this pull request as a QA engineer. /qa-review-pr
21
- List every API endpoint it adds or changes in endpoints.txt, one path per line, like /users/{id}.
22
- Leave the file empty when no endpoint changed.
22
+ List the API endpoints it adds or changes in endpoints.txt, one path per line like /users/{id}, empty if none.
23
23
  outputs: [endpoints.txt]
24
24
 
25
25
  - id: explore
26
+ title: API exploration
27
+ emoji: πŸ€–
26
28
  when: [api, explorbot-ai]
27
29
  each_line: endpoints.txt
28
- run: npx -y explorbot api explore "$ITEM" --style psycho
30
+ run: EXPLORBOT_OUTPUT="$STAGE_DIR/explorbot" npx -y explorbot api explore "$ITEM" --style psycho
29
31
  outputs: [explorbot/]
30
32
  timeout: 10m
31
33
 
32
34
  - id: results
35
+ title: Results
36
+ emoji: πŸ“Š
33
37
  session: qa
34
38
  when: [api, explorbot-ai]
35
39
  task: |
36
- Explorbot results are under explorbot/: plans, request logs, and a session report. Read them.
37
- Say which failures are real defects in this change: a broken contract, missing validation, a wrong status.
40
+ Read the Explorbot results in explorbot/ and say which failures are real defects in this change. /explorbot-fundamentals
38
41
  Fail the run if any is a real defect.
39
42
  inputs: [endpoints.txt, explorbot/]
@@ -11,29 +11,30 @@ gates:
11
11
 
12
12
  when: [issue]
13
13
 
14
+ env:
15
+ # https://github.com/org/repo/issues/42 β†’ org-repo-issues-42
16
+ TESTOMATIO_BRANCH: ${ISSUE_URL | path | slugify}
17
+
14
18
  stages:
15
19
  - id: requirements
20
+ title: Requirements
21
+ emoji: πŸ“‹
16
22
  session: analyst
17
- task: |
18
- Read the issue at ${ISSUE_URL}: its body, its comments, and every linked issue.
19
- An epic has sub-issues. Read each one. On GitHub, `gh issue view <url> --comments`
20
- reads an issue and `gh api repos/<owner>/<repo>/issues/<number>/sub_issues` lists sub-issues.
21
- Review the requirements as a QA engineer. /qa-requirement-reviewer
22
- Write the acceptance criteria to criteria.md, one section per sub-issue or feature area.
23
- End it with the open questions and gaps you found.
24
- The code here may not implement the issue yet. Read it only to use the real names of screens and terms.
25
- outputs: [criteria.md]
23
+ task: Review the requirements in ${ISSUE_URL}. /qa-requirement-reviewer
26
24
 
27
25
  - id: test-cases
26
+ title: Test cases
27
+ emoji: πŸ“
28
28
  session: writer
29
29
  task: |
30
- Write test cases from criteria.md. /qa-write-test-cases
31
- Put them in test-cases/, one markdown file per suite, one suite per sub-issue or feature area.
32
- Cover every criterion. A case that depends on an open question says so in its description.
33
- inputs: [criteria.md]
30
+ Write test cases from requirements.md. /qa-write-test-cases
31
+ Put them in test-cases/, one markdown file per suite.
32
+ inputs: [requirements.md]
34
33
  outputs: [test-cases/]
35
34
 
36
35
  - id: sync
36
+ title: Sync to Testomat.io
37
+ emoji: πŸ”„
37
38
  when: [testomatio]
38
39
  each_file: test-cases/*.md
39
40
  task: |
@@ -15,27 +15,31 @@ when: [code-changed]
15
15
 
16
16
  stages:
17
17
  - id: requirements
18
+ title: Requirements
19
+ emoji: πŸ“‹
18
20
  session: reviewer
19
- task: |
20
- Work out what this pull request is meant to do. /qa-pr-requirements-analyzer
21
- Write the acceptance criteria to criteria.md.
22
- outputs: [criteria.md]
21
+ task: Work out what this pull request is meant to do. /qa-pr-requirements-analyzer
23
22
 
24
23
  - id: review
24
+ title: Review
25
+ emoji: πŸ”
25
26
  session: reviewer
26
- task: |
27
- Review this pull request as a QA engineer against criteria.md. /qa-review-pr
28
- inputs: [criteria.md]
27
+ task: Review this pull request as a QA engineer against requirements.md. /qa-review-pr
28
+ inputs: [requirements.md]
29
29
 
30
30
  - id: test-cases
31
+ title: Test cases
32
+ emoji: πŸ“
31
33
  session: writer
32
34
  task: |
33
- Write test cases for this pull request from criteria.md and review.md. /qa-write-test-cases
35
+ Write test cases for this pull request from requirements.md and review.md. /qa-write-test-cases
34
36
  Put them in test-cases/, one markdown file per suite.
35
- inputs: [criteria.md, review.md]
37
+ inputs: [requirements.md, review.md]
36
38
  outputs: [test-cases/]
37
39
 
38
40
  - id: sync
41
+ title: Sync to Testomat.io
42
+ emoji: πŸ”„
39
43
  when: [testomatio]
40
44
  each_file: test-cases/*.md
41
45
  task: |
@@ -22,6 +22,8 @@ env:
22
22
 
23
23
  stages:
24
24
  - id: tests
25
+ title: Tests
26
+ emoji: πŸ§ͺ
25
27
  when: [testomatio]
26
28
  run: |
27
29
  npx -y @testomatio/reporter run --kind detect --warn \
@@ -30,10 +32,11 @@ stages:
30
32
  timeout: 30m
31
33
 
32
34
  - id: failures
35
+ title: Failures
36
+ emoji: 🐞
33
37
  when: [local, test-command]
34
38
  session: triage
35
39
  task: |
36
- Read the test run in tests.log. For each failure, say if this change caused it,
37
- if it is flaky, or if the test is out of date. /debug-fix-failed-flaky-autotests
38
- Do not edit any file. Fail the run if this change caused a failure.
40
+ Triage the failures in tests.log without editing files. /debug-fix-failed-flaky-autotests
41
+ Fail the run if this change caused a failure.
39
42
  inputs: [tests.log]
@@ -13,38 +13,39 @@ gates:
13
13
  message: Explorbot has no AI provider. Set EXPLORBOT_AI_PROVIDER and its key.
14
14
 
15
15
  env:
16
- EXPLORBOT_OUTPUT: ${PIPELINE_DIR}/explorbot
17
16
  EXPLORBOT_NO_BANNER: "1"
18
17
 
19
18
  stages:
20
19
  - id: review
20
+ title: Review
21
+ emoji: πŸ”
21
22
  session: qa
22
- task: |
23
- Review this pull request as a QA engineer. /qa-review-pr
24
- Write the user-facing scenarios worth checking in a browser to scenarios.md.
25
- outputs: [scenarios.md]
23
+ task: Review this pull request as a QA engineer. List the scenarios worth checking in a browser. /qa-review-pr
26
24
 
27
25
  - id: write-plan
26
+ title: Test plan
27
+ emoji: πŸ—ΊοΈ
28
28
  session: qa
29
29
  when: [staging]
30
- task: |
31
- Turn scenarios.md into an Explorbot test plan for ${EXPLORBOT_URL}. /explorbot-plan
32
- Write the plan to plan.md. Keep only scenarios a browser can check.
33
- inputs: [scenarios.md]
30
+ task: Turn the browser scenarios in review.md into an Explorbot test plan for ${EXPLORBOT_URL} in plan.md. /explorbot-plan
31
+ inputs: [review.md]
34
32
  outputs: [plan.md]
35
33
 
36
34
  - id: explore
35
+ title: Browser testing
36
+ emoji: 🌐
37
37
  when: [staging, browser, explorbot-ai]
38
- run: npx -y explorbot test "$PIPELINE_DIR/plan.md" '*'
38
+ run: EXPLORBOT_OUTPUT="$STAGE_DIR/explorbot" npx -y explorbot test "$STAGE_DIR/plan.md" '*'
39
39
  inputs: [plan.md]
40
40
  outputs: [explorbot/]
41
41
  timeout: 30m
42
42
 
43
43
  - id: results
44
+ title: Results
45
+ emoji: πŸ“Š
44
46
  session: qa
45
47
  when: [staging, browser, explorbot-ai]
46
48
  task: |
47
- Explorbot results are under explorbot/. Find its session report and read it.
48
- Say which failed scenarios are real defects in this change and which are test noise.
49
+ Read the Explorbot report in explorbot/ and say which failed scenarios are real defects and which are noise. /explorbot-fundamentals
49
50
  Fail the run if any is a real defect.
50
51
  inputs: [plan.md, explorbot/]
@@ -0,0 +1,23 @@
1
+ import dedent from "dedent";
2
+
3
+ export const pipelineReport = dedent`
4
+ <pipeline-report>
5
+ The draft is the report: every stage's report, word for word, under its own \`### <emoji> <title>\` heading. Your job is to trim it, never to write it. This format overrides <final-report>, its title included.
6
+
7
+ 1. Copy the draft to the report file with the \`write\` tool, word for word.
8
+ 2. Trim it with the \`edit\` tool:
9
+ * Drop a line that repeats what an earlier section already said.
10
+ * When a section is too long, shorten its lines or drop its least important bullets.
11
+ 3. Nothing repeats and nothing is too long: leave the copy as it is.
12
+
13
+ Never:
14
+ * Add, rename, merge, reorder or drop a heading.
15
+ * Add a sentence, a title, an intro, a conclusion or a closing summary.
16
+ * Change a fact, a number, an id or a link. Reword only to shorten.
17
+ * Cut a numbered list, or replace a list with a count like "10 items, see the file".
18
+ * Add findings, assumptions or advice of your own.
19
+
20
+ * A command stage's section links its log. You may add up to three bullets quoting its failures from the log.
21
+ * The verdict is given. Do not call a result tool to set one.
22
+ </pipeline-report>
23
+ `;
package/prompt/report.ts CHANGED
@@ -18,7 +18,7 @@ export function finalReport(path: string): string {
18
18
  <final-report>
19
19
  * Write your complete final report to \`${path}\` with the \`write\` tool. Writing it is required before you finish.
20
20
  * That file is your answer. It is the run's deliverable; nothing else you say is kept.
21
- * A skill's output format overrides every rule in this block, including the title. Follow it strictly.
21
+ * A skill's or the task's output format overrides every rule in this block, including the title. Follow it strictly.
22
22
  * Decide the **severity of your report**. Low severity: a few short bullets, nothing more.
23
23
  * Do not make the reader go through a long report for a minor issue with no effect.
24
24
  * Severity decides how many items you report, not how long each one is. Even a critical finding is: what breaks, for whom, when.
@@ -38,8 +38,8 @@ export function testomatio(options: TestomatioOptions): string {
38
38
  }
39
39
 
40
40
  function dynamicData(tms: TmsAccess): string {
41
- if (tms === "mcp-proxy") {
42
- return "Get them through the Testomat.io tools, one per entity (`tests`, `runs`, `testruns`, `issues`, …); pick the operation with its `command` param. The `mcp` tool searches them when the name is unclear.";
41
+ if (tms === "mcp-tools") {
42
+ return "Get them through the `mcp__testomatio__*` tools, one per entity (`tests`, `runs`, `testruns`, `issues`, …); pick the operation with its `command` param.";
43
43
  }
44
44
  if (tms === "cli-only") {
45
45
  return "There are no Testomat.io tools in this session. Get them from the REST API: `curl` with the `TESTOMATIO` token as the Authorization header against `$TESTOMATIO_URL/api/v2`. Keep to documented endpoints; never invent paths or parameters.";
@@ -48,11 +48,11 @@ function dynamicData(tms: TmsAccess): string {
48
48
  }
49
49
 
50
50
  /**
51
- * `mcp-proxy`: one tool per entity plus the `mcp` search tool. `cli-only`: no
51
+ * `mcp-tools`: one tool per entity, named `mcp__testomatio__<tool>`. `cli-only`: no
52
52
  * tools at all; `check-tests` and REST through the shell. `mcp-direct`: one tool
53
53
  * per entity, prefixed `testomatio-<slug>`; the desktop app's one-shot mode.
54
54
  */
55
- export type TmsAccess = "mcp-direct" | "mcp-proxy" | "cli-only";
55
+ export type TmsAccess = "mcp-direct" | "mcp-tools" | "cli-only";
56
56
 
57
57
  export interface TestomatioOptions {
58
58
  /** How the agent reaches Testomat.io in this run. */