@capagents/forgeqe 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HOW_TO_USE.md +1639 -0
- package/README.md +338 -2
- package/bin/forgeqe.d.ts +3 -0
- package/bin/forgeqe.js +188 -0
- package/docs/ARCHITECTURE.md +408 -0
- package/docs/security-data-flow.html +1870 -0
- package/docs/user-guide.html +2094 -0
- package/evals/domain/access-role-change.yaml +37 -0
- package/evals/domain/banking-payment-transfer.yaml +41 -0
- package/evals/domain/gdpr-account-erasure.yaml +30 -0
- package/evals/domain/insurance-claim-fnol.yaml +30 -0
- package/evals/domain/insurance-policy-renewal.yaml +37 -0
- package/evals/domain/lending-loan-application.yaml +36 -0
- package/forgeqe-architecture.html +718 -0
- package/forgeqe.example.yaml +203 -0
- package/knowledge/README.md +18 -0
- package/knowledge/business-rules.md +10 -0
- package/knowledge/compliance.md +16 -0
- package/knowledge/environments.md +5 -0
- package/knowledge/glossary.md +5 -0
- package/knowledge/product.md +16 -0
- package/knowledge/roles.md +9 -0
- package/knowledge/test-data.md +7 -0
- package/llms.example.json +51 -0
- package/package.json +63 -4
- package/prompts/README.md +34 -0
- package/prompts/api-scenarios.md +21 -0
- package/prompts/api-tests.md +39 -0
- package/prompts/brain.md +166 -0
- package/prompts/browser-capture.md +7 -0
- package/prompts/browser-case-report.md +7 -0
- package/prompts/browser-checks.md +14 -0
- package/prompts/browser-efficiency.md +7 -0
- package/prompts/browser-error-recovery.md +15 -0
- package/prompts/browser-extra.md +5 -0
- package/prompts/browser-goal-verification.md +13 -0
- package/prompts/browser-skill-select.md +6 -0
- package/prompts/domain-rule.md +13 -0
- package/prompts/eval-judge.md +19 -0
- package/prompts/explore-charters.md +27 -0
- package/prompts/find-tests.md +28 -0
- package/prompts/heal.md +40 -0
- package/prompts/pr-review.md +29 -0
- package/prompts/skill-rule.md +6 -0
- package/prompts/test-agent.md +34 -0
- package/prompts/test-reviewer.md +30 -0
- package/prompts/test-rules.md +28 -0
- package/py/forgeqe_engine/__init__.py +3 -0
- package/py/forgeqe_engine/__main__.py +3 -0
- package/py/forgeqe_engine/brand.py +453 -0
- package/py/forgeqe_engine/brand_assets.py +6 -0
- package/py/forgeqe_engine/browser.py +196 -0
- package/py/forgeqe_engine/capture.py +538 -0
- package/py/forgeqe_engine/checks.py +98 -0
- package/py/forgeqe_engine/cli.py +188 -0
- package/py/forgeqe_engine/diagnostics.py +609 -0
- package/py/forgeqe_engine/llm.py +195 -0
- package/py/forgeqe_engine/logins.py +251 -0
- package/py/forgeqe_engine/loops.py +224 -0
- package/py/forgeqe_engine/memory.py +1004 -0
- package/py/forgeqe_engine/network.py +244 -0
- package/py/forgeqe_engine/prompts.py +20 -0
- package/py/forgeqe_engine/replay.py +240 -0
- package/py/forgeqe_engine/report.py +173 -0
- package/py/forgeqe_engine/service.py +1335 -0
- package/py/forgeqe_engine/settings.py +93 -0
- package/py/forgeqe_engine/skills.py +88 -0
- package/py/forgeqe_engine/summary.py +239 -0
- package/py/forgeqe_engine/urls.py +81 -0
- package/py/forgeqe_engine/workflow_yaml.py +689 -0
- package/skills/dotnet-nunit-playwright/SKILL.md +34 -0
- package/skills/dynamics-365/SKILL.md +21 -0
- package/skills/playwright-typescript/SKILL.md +35 -0
- package/skills/writing-skills/SKILL.md +30 -0
- package/src/api/plan.ts +246 -0
- package/src/api/run.ts +204 -0
- package/src/api/scenario.ts +502 -0
- package/src/api/schema.ts +170 -0
- package/src/api/spec.ts +624 -0
- package/src/api/store.ts +232 -0
- package/src/api/traffic.ts +281 -0
- package/src/api/types.ts +163 -0
- package/src/api/write.ts +272 -0
- package/src/auth/signin.ts +494 -0
- package/src/auth/store.ts +170 -0
- package/src/brain/index.ts +189 -0
- package/src/brain/prompt.ts +19 -0
- package/src/capabilities/docs.ts +101 -0
- package/src/capabilities/guide.ts +455 -0
- package/src/capabilities/registry.ts +343 -0
- package/src/capabilities/render.ts +106 -0
- package/src/capabilities/status.ts +137 -0
- package/src/card.ts +11 -0
- package/src/cases/ado.ts +325 -0
- package/src/cases/api.ts +117 -0
- package/src/cases/bugs.ts +223 -0
- package/src/cases/confluence.ts +111 -0
- package/src/cases/context.ts +223 -0
- package/src/cases/dashboards.ts +137 -0
- package/src/cases/failure.ts +97 -0
- package/src/cases/files.ts +295 -0
- package/src/cases/goal.ts +53 -0
- package/src/cases/http.ts +111 -0
- package/src/cases/index.ts +131 -0
- package/src/cases/jira.ts +122 -0
- package/src/cases/qtest.ts +108 -0
- package/src/cases/quality.ts +190 -0
- package/src/cases/rag.ts +100 -0
- package/src/cases/readiness.ts +284 -0
- package/src/cases/save.ts +149 -0
- package/src/cases/sprints.ts +148 -0
- package/src/cases/testrail.ts +176 -0
- package/src/cases/types.ts +107 -0
- package/src/cases/wiki.ts +105 -0
- package/src/cases/xray.ts +206 -0
- package/src/cases/zephyr.ts +153 -0
- package/src/childEnv.ts +86 -0
- package/src/cli/args.ts +114 -0
- package/src/cli/help.ts +167 -0
- package/src/cli/index.ts +1142 -0
- package/src/cli/terminal.ts +187 -0
- package/src/code/areas.ts +337 -0
- package/src/code/attention.ts +214 -0
- package/src/code/find.ts +540 -0
- package/src/code/handoff.ts +541 -0
- package/src/code/history.ts +170 -0
- package/src/code/impact.ts +231 -0
- package/src/code/index.ts +34 -0
- package/src/code/livebrowser.ts +67 -0
- package/src/code/loop.ts +603 -0
- package/src/code/notes.ts +75 -0
- package/src/code/profile.ts +226 -0
- package/src/code/prompt.ts +303 -0
- package/src/code/prreview.ts +649 -0
- package/src/code/prtests.ts +103 -0
- package/src/code/replay.ts +772 -0
- package/src/code/review.ts +202 -0
- package/src/code/runtime.ts +781 -0
- package/src/code/slices.ts +159 -0
- package/src/code/testrun.ts +187 -0
- package/src/code/traceability.ts +100 -0
- package/src/code/worktree.ts +153 -0
- package/src/commands.ts +101 -0
- package/src/config.ts +970 -0
- package/src/detail.ts +65 -0
- package/src/domain.ts +19 -0
- package/src/engine/bridge.ts +359 -0
- package/src/engine/mock.ts +102 -0
- package/src/engine/setup.ts +298 -0
- package/src/entra.ts +154 -0
- package/src/env.ts +24 -0
- package/src/evals/domain.ts +338 -0
- package/src/explore/charters.ts +151 -0
- package/src/explore/run.ts +280 -0
- package/src/explore/story.ts +106 -0
- package/src/guard.ts +51 -0
- package/src/heal/loop.ts +357 -0
- package/src/heal/prompt.ts +143 -0
- package/src/heal/report.ts +95 -0
- package/src/index.ts +12 -0
- package/src/init.ts +102 -0
- package/src/knowledge.ts +114 -0
- package/src/legacyEnv.ts +9 -0
- package/src/llm.ts +61 -0
- package/src/locale.ts +25 -0
- package/src/logins.ts +148 -0
- package/src/managed.ts +101 -0
- package/src/mcp/apitools.ts +335 -0
- package/src/mcp/captools.ts +25 -0
- package/src/mcp/casetools.ts +223 -0
- package/src/mcp/commands.ts +421 -0
- package/src/mcp/exploretools.ts +129 -0
- package/src/mcp/external.ts +172 -0
- package/src/mcp/git.ts +78 -0
- package/src/mcp/notifytools.ts +49 -0
- package/src/mcp/prtools.ts +261 -0
- package/src/mcp/qualitytools.ts +154 -0
- package/src/mcp/repotests.ts +286 -0
- package/src/mcp/server.ts +234 -0
- package/src/mcp/tools.ts +810 -0
- package/src/memory.ts +250 -0
- package/src/money.ts +39 -0
- package/src/monitor/alerts.ts +94 -0
- package/src/monitor/background.ts +68 -0
- package/src/monitor/run.ts +263 -0
- package/src/monitor/state.ts +105 -0
- package/src/notify/events.ts +144 -0
- package/src/notify/notice.ts +177 -0
- package/src/prices.ts +175 -0
- package/src/print.ts +54 -0
- package/src/privacy.ts +35 -0
- package/src/prompts.ts +165 -0
- package/src/quality/budgets.ts +249 -0
- package/src/quality/history.ts +149 -0
- package/src/quality/visual.ts +201 -0
- package/src/report/data.ts +475 -0
- package/src/report/html.ts +106 -0
- package/src/report/template.html +84 -0
- package/src/run.ts +243 -0
- package/src/sessionLog.ts +216 -0
- package/src/sessionLogins.ts +94 -0
- package/src/skills/registry.ts +217 -0
- package/src/skills/scaffold.ts +65 -0
- package/src/skills/select.ts +37 -0
- package/src/skills/view.ts +44 -0
- package/src/suite/report.ts +135 -0
- package/src/suite/run.ts +303 -0
- package/src/summary.ts +188 -0
- package/src/tools.ts +130 -0
- package/src/tui/App.tsx +983 -0
- package/src/tui/clipboard.ts +36 -0
- package/src/tui/components.tsx +263 -0
- package/src/tui/dialogs.ts +65 -0
- package/src/tui/main.tsx +20 -0
- package/src/tui/text.ts +28 -0
- package/src/tui/theme.ts +104 -0
- package/src/tui/transcript.tsx +344 -0
- package/src/types.ts +146 -0
- package/src/update.ts +311 -0
- 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
|
+
}
|