@capagents/forgeqe 0.0.0-stage → 1.0.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 (220) hide show
  1. package/HOW_TO_USE.md +1639 -0
  2. package/README.md +338 -2
  3. package/bin/forgeqe.d.ts +3 -0
  4. package/bin/forgeqe.js +188 -0
  5. package/docs/ARCHITECTURE.md +408 -0
  6. package/docs/security-data-flow.html +1870 -0
  7. package/docs/user-guide.html +2094 -0
  8. package/evals/domain/access-role-change.yaml +37 -0
  9. package/evals/domain/banking-payment-transfer.yaml +41 -0
  10. package/evals/domain/gdpr-account-erasure.yaml +30 -0
  11. package/evals/domain/insurance-claim-fnol.yaml +30 -0
  12. package/evals/domain/insurance-policy-renewal.yaml +37 -0
  13. package/evals/domain/lending-loan-application.yaml +36 -0
  14. package/forgeqe-architecture.html +718 -0
  15. package/forgeqe.example.yaml +203 -0
  16. package/knowledge/README.md +18 -0
  17. package/knowledge/business-rules.md +10 -0
  18. package/knowledge/compliance.md +16 -0
  19. package/knowledge/environments.md +5 -0
  20. package/knowledge/glossary.md +5 -0
  21. package/knowledge/product.md +16 -0
  22. package/knowledge/roles.md +9 -0
  23. package/knowledge/test-data.md +7 -0
  24. package/llms.example.json +51 -0
  25. package/package.json +63 -4
  26. package/prompts/README.md +34 -0
  27. package/prompts/api-scenarios.md +21 -0
  28. package/prompts/api-tests.md +39 -0
  29. package/prompts/brain.md +166 -0
  30. package/prompts/browser-capture.md +7 -0
  31. package/prompts/browser-case-report.md +7 -0
  32. package/prompts/browser-checks.md +14 -0
  33. package/prompts/browser-efficiency.md +7 -0
  34. package/prompts/browser-error-recovery.md +15 -0
  35. package/prompts/browser-extra.md +5 -0
  36. package/prompts/browser-goal-verification.md +13 -0
  37. package/prompts/browser-skill-select.md +6 -0
  38. package/prompts/domain-rule.md +13 -0
  39. package/prompts/eval-judge.md +19 -0
  40. package/prompts/explore-charters.md +27 -0
  41. package/prompts/find-tests.md +28 -0
  42. package/prompts/heal.md +40 -0
  43. package/prompts/pr-review.md +29 -0
  44. package/prompts/skill-rule.md +6 -0
  45. package/prompts/test-agent.md +34 -0
  46. package/prompts/test-reviewer.md +30 -0
  47. package/prompts/test-rules.md +28 -0
  48. package/py/forgeqe_engine/__init__.py +3 -0
  49. package/py/forgeqe_engine/__main__.py +3 -0
  50. package/py/forgeqe_engine/brand.py +453 -0
  51. package/py/forgeqe_engine/brand_assets.py +6 -0
  52. package/py/forgeqe_engine/browser.py +196 -0
  53. package/py/forgeqe_engine/capture.py +538 -0
  54. package/py/forgeqe_engine/checks.py +98 -0
  55. package/py/forgeqe_engine/cli.py +188 -0
  56. package/py/forgeqe_engine/diagnostics.py +609 -0
  57. package/py/forgeqe_engine/llm.py +195 -0
  58. package/py/forgeqe_engine/logins.py +251 -0
  59. package/py/forgeqe_engine/loops.py +224 -0
  60. package/py/forgeqe_engine/memory.py +1004 -0
  61. package/py/forgeqe_engine/network.py +244 -0
  62. package/py/forgeqe_engine/prompts.py +20 -0
  63. package/py/forgeqe_engine/replay.py +240 -0
  64. package/py/forgeqe_engine/report.py +173 -0
  65. package/py/forgeqe_engine/service.py +1335 -0
  66. package/py/forgeqe_engine/settings.py +93 -0
  67. package/py/forgeqe_engine/skills.py +88 -0
  68. package/py/forgeqe_engine/summary.py +239 -0
  69. package/py/forgeqe_engine/urls.py +81 -0
  70. package/py/forgeqe_engine/workflow_yaml.py +689 -0
  71. package/skills/dotnet-nunit-playwright/SKILL.md +34 -0
  72. package/skills/dynamics-365/SKILL.md +21 -0
  73. package/skills/playwright-typescript/SKILL.md +35 -0
  74. package/skills/writing-skills/SKILL.md +30 -0
  75. package/src/api/plan.ts +246 -0
  76. package/src/api/run.ts +204 -0
  77. package/src/api/scenario.ts +502 -0
  78. package/src/api/schema.ts +170 -0
  79. package/src/api/spec.ts +624 -0
  80. package/src/api/store.ts +232 -0
  81. package/src/api/traffic.ts +281 -0
  82. package/src/api/types.ts +163 -0
  83. package/src/api/write.ts +272 -0
  84. package/src/auth/signin.ts +494 -0
  85. package/src/auth/store.ts +170 -0
  86. package/src/brain/index.ts +189 -0
  87. package/src/brain/prompt.ts +19 -0
  88. package/src/capabilities/docs.ts +101 -0
  89. package/src/capabilities/guide.ts +455 -0
  90. package/src/capabilities/registry.ts +343 -0
  91. package/src/capabilities/render.ts +106 -0
  92. package/src/capabilities/status.ts +137 -0
  93. package/src/card.ts +11 -0
  94. package/src/cases/ado.ts +325 -0
  95. package/src/cases/api.ts +117 -0
  96. package/src/cases/bugs.ts +223 -0
  97. package/src/cases/confluence.ts +111 -0
  98. package/src/cases/context.ts +223 -0
  99. package/src/cases/dashboards.ts +137 -0
  100. package/src/cases/failure.ts +97 -0
  101. package/src/cases/files.ts +295 -0
  102. package/src/cases/goal.ts +53 -0
  103. package/src/cases/http.ts +111 -0
  104. package/src/cases/index.ts +131 -0
  105. package/src/cases/jira.ts +122 -0
  106. package/src/cases/qtest.ts +108 -0
  107. package/src/cases/quality.ts +190 -0
  108. package/src/cases/rag.ts +100 -0
  109. package/src/cases/readiness.ts +284 -0
  110. package/src/cases/save.ts +149 -0
  111. package/src/cases/sprints.ts +148 -0
  112. package/src/cases/testrail.ts +176 -0
  113. package/src/cases/types.ts +107 -0
  114. package/src/cases/wiki.ts +105 -0
  115. package/src/cases/xray.ts +206 -0
  116. package/src/cases/zephyr.ts +153 -0
  117. package/src/childEnv.ts +86 -0
  118. package/src/cli/args.ts +114 -0
  119. package/src/cli/help.ts +167 -0
  120. package/src/cli/index.ts +1142 -0
  121. package/src/cli/terminal.ts +187 -0
  122. package/src/code/areas.ts +337 -0
  123. package/src/code/attention.ts +214 -0
  124. package/src/code/find.ts +540 -0
  125. package/src/code/handoff.ts +541 -0
  126. package/src/code/history.ts +170 -0
  127. package/src/code/impact.ts +231 -0
  128. package/src/code/index.ts +34 -0
  129. package/src/code/livebrowser.ts +67 -0
  130. package/src/code/loop.ts +603 -0
  131. package/src/code/notes.ts +75 -0
  132. package/src/code/profile.ts +226 -0
  133. package/src/code/prompt.ts +303 -0
  134. package/src/code/prreview.ts +649 -0
  135. package/src/code/prtests.ts +103 -0
  136. package/src/code/replay.ts +772 -0
  137. package/src/code/review.ts +202 -0
  138. package/src/code/runtime.ts +757 -0
  139. package/src/code/slices.ts +159 -0
  140. package/src/code/testrun.ts +187 -0
  141. package/src/code/traceability.ts +100 -0
  142. package/src/code/worktree.ts +153 -0
  143. package/src/commands.ts +101 -0
  144. package/src/config.ts +970 -0
  145. package/src/detail.ts +65 -0
  146. package/src/domain.ts +19 -0
  147. package/src/engine/bridge.ts +359 -0
  148. package/src/engine/mock.ts +102 -0
  149. package/src/engine/setup.ts +298 -0
  150. package/src/entra.ts +154 -0
  151. package/src/env.ts +24 -0
  152. package/src/evals/domain.ts +338 -0
  153. package/src/explore/charters.ts +151 -0
  154. package/src/explore/run.ts +280 -0
  155. package/src/explore/story.ts +106 -0
  156. package/src/guard.ts +51 -0
  157. package/src/heal/loop.ts +357 -0
  158. package/src/heal/prompt.ts +143 -0
  159. package/src/heal/report.ts +95 -0
  160. package/src/index.ts +12 -0
  161. package/src/init.ts +102 -0
  162. package/src/knowledge.ts +114 -0
  163. package/src/legacyEnv.ts +9 -0
  164. package/src/llm.ts +61 -0
  165. package/src/locale.ts +25 -0
  166. package/src/logins.ts +148 -0
  167. package/src/managed.ts +101 -0
  168. package/src/mcp/apitools.ts +335 -0
  169. package/src/mcp/captools.ts +25 -0
  170. package/src/mcp/casetools.ts +223 -0
  171. package/src/mcp/commands.ts +421 -0
  172. package/src/mcp/exploretools.ts +129 -0
  173. package/src/mcp/external.ts +172 -0
  174. package/src/mcp/git.ts +78 -0
  175. package/src/mcp/notifytools.ts +49 -0
  176. package/src/mcp/prtools.ts +261 -0
  177. package/src/mcp/qualitytools.ts +154 -0
  178. package/src/mcp/repotests.ts +286 -0
  179. package/src/mcp/server.ts +234 -0
  180. package/src/mcp/tools.ts +810 -0
  181. package/src/memory.ts +250 -0
  182. package/src/money.ts +39 -0
  183. package/src/monitor/alerts.ts +94 -0
  184. package/src/monitor/background.ts +68 -0
  185. package/src/monitor/run.ts +263 -0
  186. package/src/monitor/state.ts +105 -0
  187. package/src/notify/events.ts +144 -0
  188. package/src/notify/notice.ts +177 -0
  189. package/src/prices.ts +175 -0
  190. package/src/print.ts +54 -0
  191. package/src/privacy.ts +35 -0
  192. package/src/prompts.ts +165 -0
  193. package/src/quality/budgets.ts +249 -0
  194. package/src/quality/history.ts +149 -0
  195. package/src/quality/visual.ts +201 -0
  196. package/src/report/data.ts +475 -0
  197. package/src/report/html.ts +106 -0
  198. package/src/report/template.html +84 -0
  199. package/src/run.ts +243 -0
  200. package/src/sessionLog.ts +216 -0
  201. package/src/sessionLogins.ts +94 -0
  202. package/src/skills/registry.ts +217 -0
  203. package/src/skills/scaffold.ts +65 -0
  204. package/src/skills/select.ts +37 -0
  205. package/src/skills/view.ts +44 -0
  206. package/src/suite/report.ts +135 -0
  207. package/src/suite/run.ts +303 -0
  208. package/src/summary.ts +188 -0
  209. package/src/tools.ts +130 -0
  210. package/src/tui/App.tsx +983 -0
  211. package/src/tui/clipboard.ts +36 -0
  212. package/src/tui/components.tsx +263 -0
  213. package/src/tui/dialogs.ts +65 -0
  214. package/src/tui/main.tsx +20 -0
  215. package/src/tui/text.ts +28 -0
  216. package/src/tui/theme.ts +104 -0
  217. package/src/tui/transcript.tsx +344 -0
  218. package/src/types.ts +136 -0
  219. package/src/update.ts +311 -0
  220. package/src/usage.ts +158 -0
@@ -0,0 +1,103 @@
1
+ import path from "node:path"
2
+ import { spawnSync } from "node:child_process"
3
+
4
+ import type { CodeEvent } from "../types.ts"
5
+ import type { AppConfig } from "../config.ts"
6
+ import { findTests, type TestSelection, type TestsRun } from "./find.ts"
7
+ import { analyzeImpact, changedBetween, impactSelection, testsForWorkItems, type Impact } from "./impact.ts"
8
+ import { fetchPr, fetchPrBranches, resolvePr, type Platform, type PrInfo } from "./prreview.ts"
9
+ import type { OpencodeSession, openSession } from "./runtime.ts"
10
+ import type { runTestCommand } from "./testrun.ts"
11
+
12
+ /**
13
+ * The tests a pull request (or the commits since a base branch) can break: the impact analysis, then either the
14
+ * find-tests agent, which reads the candidates and the tests and gives an exact selection with list and run commands,
15
+ * or (agent: false, for CI) a selection of the impacted test files with a run command built for Playwright or pytest.
16
+ * The tests run from the working tree, so in CI check the pull request's branch out first.
17
+ */
18
+ export type PrTests = {
19
+ selection: TestSelection | null
20
+ impact: Impact
21
+ pr?: PrInfo
22
+ /** Something the user should know: the working tree is not the PR's head, or no test was found. */
23
+ notes: string[]
24
+ }
25
+
26
+ export async function selectPrTests(opts: {
27
+ config: AppConfig
28
+ repo: string
29
+ pr?: string
30
+ platform?: Platform
31
+ /** Without pr: the branch to compare HEAD with (default: the remote's default branch). */
32
+ base?: string
33
+ agent: boolean
34
+ signal?: AbortSignal
35
+ onEvent?: (e: CodeEvent) => void
36
+ open?: (o: Parameters<typeof openSession>[0]) => Promise<OpencodeSession>
37
+ runTest?: typeof runTestCommand
38
+ }): Promise<PrTests> {
39
+ const emit = opts.onEvent || (() => {})
40
+ const notes: string[] = []
41
+ let root = path.resolve(opts.repo)
42
+ let changed: string[]
43
+ let pr: PrInfo | undefined
44
+ if (opts.pr) {
45
+ const r = await resolvePr(root, opts.pr, opts.platform)
46
+ root = r.root
47
+ emit({ type: "code", kind: "info", text: `Reading pull request ${r.ref.number}…` })
48
+ pr = await fetchPr(r.ref, opts.config, root)
49
+ const { base, dropRefs } = await fetchPrBranches(root, r.remote, pr)
50
+ try {
51
+ changed = changedBetween(root, base, pr.headSha)
52
+ } finally {
53
+ await dropRefs()
54
+ }
55
+ const head = spawnSync("git", ["rev-parse", "HEAD"], { cwd: root, encoding: "utf8" }).stdout.trim()
56
+ if (head && head !== pr.headSha) notes.push(`The working tree is at ${head.slice(0, 10)}, not the pull request's head ${pr.headSha.slice(0, 10)}: the tests run as they are here, so check out ${pr.sourceBranch} to run the pull request's own versions (and any tests it adds).`)
57
+ } else {
58
+ const base = opts.base || defaultBase(root)
59
+ changed = changedBetween(root, base)
60
+ notes.push(`Changes since ${base}.`)
61
+ }
62
+ const mapped = pr?.workItemIds?.length ? await testsForWorkItems(opts.config, root, pr.workItemIds) : []
63
+ const impact = analyzeImpact(root, changed, mapped)
64
+ emit({ type: "code", kind: "info", text: `${changed.length} changed files; ${impact.tests.length} tests reach them${impact.untested.length ? `; no test reaches ${impact.untested.length}` : ""}` })
65
+ const what = pr ? `pull request ${pr.ref.number} "${pr.title}"` : "the changes since the base branch"
66
+ if (!opts.agent) {
67
+ if (!impact.tests.length) return { selection: null, impact, pr, notes: [...notes, "No test reaches the changed files."] }
68
+ const selection = impactSelection(opts.config, root, `tests affected by ${what}`, impact)
69
+ if (!selection) notes.push("The impacted tests are not Playwright or pytest files in one project, so there is no run command without the find-tests agent: run it with the agent, or run the files listed.")
70
+ return { selection, impact, pr, notes }
71
+ }
72
+ const request = [
73
+ `The tests that ${what} can break.`,
74
+ pr?.description ? `What it does: ${pr.description.slice(0, 600)}` : "",
75
+ `Changed files: ${changed.slice(0, 80).join(", ")}${changed.length > 80 ? `, and ${changed.length - 80} more` : ""}.`,
76
+ impact.tests.length ? `Candidates from the imports and names (check each; keep the ones that exercise what changed): ${impact.tests.map((t) => `${t.file} (${t.reasons.join("; ")})`).join("; ")}.` : "",
77
+ "Also add tests that drive the changed behaviour through the UI without importing the changed files (a page whose markup or route changed). Leave out tests that only share a helper the change does not alter.",
78
+ ]
79
+ .filter(Boolean)
80
+ .join("\n")
81
+ const selection = await findTests({ config: opts.config, repo: root, request, signal: opts.signal, onEvent: emit, open: opts.open, runTest: opts.runTest })
82
+ return { selection, impact, pr, notes }
83
+ }
84
+
85
+ /** origin/HEAD's branch (origin/main), or origin/main. */
86
+ function defaultBase(repo: string): string {
87
+ const r = spawnSync("git", ["symbolic-ref", "--quiet", "--short", "refs/remotes/origin/HEAD"], { cwd: repo, encoding: "utf8" })
88
+ return r.status === 0 && r.stdout.trim() ? r.stdout.trim() : "origin/main"
89
+ }
90
+
91
+ /** The run's results as a pull request comment. */
92
+ export function resultsMarkdown(run: TestsRun, what: string): string {
93
+ const failed = run.tests.filter((t) => t.status === "failed")
94
+ const mark = run.status === "passed" ? "✅" : "❌"
95
+ return [
96
+ `### ${mark} ForgeQE: tests affected by ${what}`,
97
+ "",
98
+ `${run.counts.passed} passed, ${run.counts.failed} failed${run.counts.skipped ? `, ${run.counts.skipped} skipped` : ""} in ${run.seconds}s${run.status === "timed out" ? " (timed out)" : ""}.`,
99
+ ...(failed.length ? ["", "| Failed test | Message |", "|---|---|", ...failed.slice(0, 25).map((t) => `| ${t.name.replace(/\|/g, "\\|")} | ${(t.message || "").replace(/\|/g, "\\|").slice(0, 200)} |`)] : []),
100
+ "",
101
+ `Command: \`${run.command}\``,
102
+ ].join("\n")
103
+ }