supipowers 0.4.0 → 0.6.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.
- package/package.json +3 -3
- package/skills/context-mode/SKILL.md +38 -0
- package/skills/qa-strategy/SKILL.md +103 -21
- package/src/commands/config.ts +23 -2
- package/src/commands/fix-pr.ts +1 -1
- package/src/commands/plan.ts +1 -1
- package/src/commands/qa.ts +232 -148
- package/src/commands/release.ts +1 -1
- package/src/commands/review.ts +1 -1
- package/src/commands/run.ts +9 -4
- package/src/commands/supi.ts +1 -1
- package/src/config/defaults.ts +11 -0
- package/src/config/schema.ts +11 -0
- package/src/context-mode/compressor.ts +200 -0
- package/src/context-mode/detector.ts +43 -0
- package/src/context-mode/event-extractor.ts +170 -0
- package/src/context-mode/event-store.ts +168 -0
- package/src/context-mode/hooks.ts +176 -0
- package/src/context-mode/installer.ts +71 -0
- package/src/context-mode/snapshot-builder.ts +127 -0
- package/src/discipline/debugging.ts +7 -7
- package/src/discipline/receiving-review.ts +5 -5
- package/src/discipline/tdd.ts +2 -2
- package/src/discipline/verification.ts +9 -9
- package/src/git/base-branch.ts +30 -0
- package/src/git/branch-finish.ts +12 -3
- package/src/git/sanitize.ts +19 -0
- package/src/git/worktree.ts +38 -11
- package/src/index.ts +8 -1
- package/src/orchestrator/agent-prompts.ts +15 -7
- package/src/orchestrator/conflict-resolver.ts +3 -2
- package/src/orchestrator/dispatcher.ts +76 -21
- package/src/orchestrator/prompts.ts +46 -6
- package/src/planning/plan-reviewer.ts +1 -1
- package/src/planning/plan-writer-prompt.ts +6 -9
- package/src/planning/prompt-builder.ts +17 -16
- package/src/planning/spec-reviewer.ts +2 -2
- package/src/qa/config.ts +43 -0
- package/src/qa/matrix.ts +84 -0
- package/src/qa/prompt-builder.ts +212 -0
- package/src/qa/scripts/detect-app-type.sh +68 -0
- package/src/qa/scripts/discover-routes.sh +143 -0
- package/src/qa/scripts/ensure-playwright.sh +38 -0
- package/src/qa/scripts/run-e2e-tests.sh +99 -0
- package/src/qa/scripts/start-dev-server.sh +46 -0
- package/src/qa/scripts/stop-dev-server.sh +36 -0
- package/src/qa/session.ts +39 -55
- package/src/qa/types.ts +97 -0
- package/src/storage/qa-sessions.ts +9 -9
- package/src/types.ts +22 -70
- package/src/qa/detector.ts +0 -61
- package/src/qa/phases/discovery.ts +0 -34
- package/src/qa/phases/execution.ts +0 -65
- package/src/qa/phases/matrix.ts +0 -41
- package/src/qa/phases/reporting.ts +0 -71
- package/src/qa/report.ts +0 -22
- package/src/qa/runner.ts +0 -46
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { DetectedFramework } from "../detector.js";
|
|
2
|
-
|
|
3
|
-
export function buildDiscoveryPrompt(framework: DetectedFramework, cwd: string): string {
|
|
4
|
-
const sections: string[] = [
|
|
5
|
-
"# QA Phase: Test Discovery",
|
|
6
|
-
"",
|
|
7
|
-
`Project: ${cwd}`,
|
|
8
|
-
`Test framework: ${framework.name} (command: \`${framework.command}\`)`,
|
|
9
|
-
"",
|
|
10
|
-
"## Task",
|
|
11
|
-
"",
|
|
12
|
-
"Scan the project for all test files and enumerate every individual test case.",
|
|
13
|
-
"",
|
|
14
|
-
"1. Find all test files matching the framework's conventions",
|
|
15
|
-
"2. Parse each file to extract individual test/it/describe blocks",
|
|
16
|
-
"3. Classify each test with tags (unit, integration, e2e) based on file path or naming",
|
|
17
|
-
"",
|
|
18
|
-
"## Expected Output",
|
|
19
|
-
"",
|
|
20
|
-
"Write a JSON array to the QA session ledger's `tests` field. Each entry:",
|
|
21
|
-
"",
|
|
22
|
-
"```json",
|
|
23
|
-
'[{ "id": "<filePath>:<testName>", "filePath": "relative/path.test.ts", "testName": "test name", "suiteName": "describe block", "tags": ["unit"] }]',
|
|
24
|
-
"```",
|
|
25
|
-
"",
|
|
26
|
-
"The `id` must be deterministic: use `filePath:testName` so it stays stable across sessions.",
|
|
27
|
-
"",
|
|
28
|
-
"## After Completion",
|
|
29
|
-
"",
|
|
30
|
-
"Update the QA session ledger with the discovered tests, mark the discovery phase as completed, then invoke `/supi:qa` to continue to the next phase.",
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
return sections.join("\n");
|
|
34
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import type { QaSessionLedger, QaTestCase } from "../../types.js";
|
|
2
|
-
|
|
3
|
-
export interface ExecutionOptions {
|
|
4
|
-
failedOnly: true;
|
|
5
|
-
failedTests: QaTestCase[];
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function buildExecutionPrompt(
|
|
9
|
-
ledger: QaSessionLedger,
|
|
10
|
-
options?: ExecutionOptions
|
|
11
|
-
): string {
|
|
12
|
-
const isRetry = options?.failedOnly === true;
|
|
13
|
-
const targetTests = isRetry ? options.failedTests : ledger.tests;
|
|
14
|
-
|
|
15
|
-
const testList = targetTests
|
|
16
|
-
.map((t) => `- ${t.id}: ${t.testName} (${t.filePath})`)
|
|
17
|
-
.join("\n");
|
|
18
|
-
|
|
19
|
-
const sections: string[] = [
|
|
20
|
-
"# QA Phase: Test Execution",
|
|
21
|
-
"",
|
|
22
|
-
`Framework: ${ledger.framework}`,
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
if (isRetry) {
|
|
26
|
-
sections.push(
|
|
27
|
-
"",
|
|
28
|
-
`## Re-running ${targetTests.length} failed test(s)`,
|
|
29
|
-
"",
|
|
30
|
-
"Run ONLY the following failed tests:",
|
|
31
|
-
"",
|
|
32
|
-
testList,
|
|
33
|
-
);
|
|
34
|
-
} else {
|
|
35
|
-
sections.push(
|
|
36
|
-
"",
|
|
37
|
-
`## Running all ${targetTests.length} test(s)`,
|
|
38
|
-
"",
|
|
39
|
-
testList,
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
sections.push(
|
|
44
|
-
"",
|
|
45
|
-
"## Instructions",
|
|
46
|
-
"",
|
|
47
|
-
"1. Run the tests using the framework's CLI",
|
|
48
|
-
"2. Collect per-test results: pass, fail, or skip",
|
|
49
|
-
"3. For failures, capture the error message",
|
|
50
|
-
"",
|
|
51
|
-
"## Expected Output",
|
|
52
|
-
"",
|
|
53
|
-
"Write a JSON array to the QA session ledger's `results` field:",
|
|
54
|
-
"",
|
|
55
|
-
"```json",
|
|
56
|
-
'[{ "testId": "file.test.ts:test name", "status": "pass|fail|skip", "duration": 123, "error": "only if failed" }]',
|
|
57
|
-
"```",
|
|
58
|
-
"",
|
|
59
|
-
"## After Completion",
|
|
60
|
-
"",
|
|
61
|
-
"Update the QA session ledger with results, mark the execution phase as completed, then invoke `/supi:qa` to continue to the next phase.",
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
return sections.join("\n");
|
|
65
|
-
}
|
package/src/qa/phases/matrix.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { QaSessionLedger } from "../../types.js";
|
|
2
|
-
|
|
3
|
-
export function buildMatrixPrompt(ledger: QaSessionLedger): string {
|
|
4
|
-
const testSummary = ledger.tests
|
|
5
|
-
.map((t) => `- ${t.id}: ${t.testName} (${t.filePath})${t.tags ? ` [${t.tags.join(", ")}]` : ""}`)
|
|
6
|
-
.join("\n");
|
|
7
|
-
|
|
8
|
-
const sections: string[] = [
|
|
9
|
-
"# QA Phase: Traceability Matrix",
|
|
10
|
-
"",
|
|
11
|
-
`Framework: ${ledger.framework}`,
|
|
12
|
-
`Discovered tests: ${ledger.tests.length}`,
|
|
13
|
-
"",
|
|
14
|
-
"## Discovered Tests",
|
|
15
|
-
"",
|
|
16
|
-
testSummary,
|
|
17
|
-
"",
|
|
18
|
-
"## Task",
|
|
19
|
-
"",
|
|
20
|
-
"Build a traceability matrix that maps requirements to test cases and platforms.",
|
|
21
|
-
"",
|
|
22
|
-
"1. Read the project's README, PR descriptions, code comments, and doc files to identify requirements",
|
|
23
|
-
"2. Map each requirement to the test case IDs that cover it",
|
|
24
|
-
"3. Identify target platforms (node, browser, CI) from project config",
|
|
25
|
-
"4. Assess coverage: full (all paths tested), partial (some paths), none (no tests)",
|
|
26
|
-
"",
|
|
27
|
-
"## Expected Output",
|
|
28
|
-
"",
|
|
29
|
-
"Write a JSON array to the QA session ledger's `matrix` field:",
|
|
30
|
-
"",
|
|
31
|
-
"```json",
|
|
32
|
-
'[{ "requirement": "User login validates email format", "testIds": ["auth.test.ts:validates email"], "platforms": ["node"], "coverage": "full" }]',
|
|
33
|
-
"```",
|
|
34
|
-
"",
|
|
35
|
-
"## After Completion",
|
|
36
|
-
"",
|
|
37
|
-
"Update the QA session ledger with the matrix, mark the matrix phase as completed, then invoke `/supi:qa` to continue to the next phase.",
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
return sections.join("\n");
|
|
41
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import type { QaSessionLedger } from "../../types.js";
|
|
2
|
-
|
|
3
|
-
export function buildReportingPrompt(ledger: QaSessionLedger): string {
|
|
4
|
-
const passed = ledger.results.filter((r) => r.status === "pass").length;
|
|
5
|
-
const failed = ledger.results.filter((r) => r.status === "fail").length;
|
|
6
|
-
const skipped = ledger.results.filter((r) => r.status === "skip").length;
|
|
7
|
-
const total = ledger.results.length;
|
|
8
|
-
|
|
9
|
-
const failedList = ledger.results
|
|
10
|
-
.filter((r) => r.status === "fail")
|
|
11
|
-
.map((r) => {
|
|
12
|
-
const test = ledger.tests.find((t) => t.id === r.testId);
|
|
13
|
-
return `- ${test?.testName ?? r.testId}: ${r.error ?? "no error captured"}`;
|
|
14
|
-
})
|
|
15
|
-
.join("\n");
|
|
16
|
-
|
|
17
|
-
const matrixSummary = ledger.matrix.length > 0
|
|
18
|
-
? ledger.matrix
|
|
19
|
-
.map((m) => `- ${m.requirement}: ${m.coverage} coverage (${m.testIds.length} tests)`)
|
|
20
|
-
.join("\n")
|
|
21
|
-
: "No traceability matrix available.";
|
|
22
|
-
|
|
23
|
-
const sections: string[] = [
|
|
24
|
-
"# QA Phase: Reporting",
|
|
25
|
-
"",
|
|
26
|
-
`Framework: ${ledger.framework}`,
|
|
27
|
-
`Session: ${ledger.id}`,
|
|
28
|
-
"",
|
|
29
|
-
"## Execution Summary",
|
|
30
|
-
"",
|
|
31
|
-
`- Total: ${total}`,
|
|
32
|
-
`- Passed: ${passed}`,
|
|
33
|
-
`- Failed: ${failed}`,
|
|
34
|
-
`- Skipped: ${skipped}`,
|
|
35
|
-
`- Pass rate: ${total > 0 ? Math.round((passed / total) * 100) : 0}%`,
|
|
36
|
-
"",
|
|
37
|
-
];
|
|
38
|
-
|
|
39
|
-
if (failed > 0) {
|
|
40
|
-
sections.push("## Failed Tests", "", failedList, "");
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
sections.push(
|
|
44
|
-
"## Traceability Matrix",
|
|
45
|
-
"",
|
|
46
|
-
matrixSummary,
|
|
47
|
-
"",
|
|
48
|
-
"## Task",
|
|
49
|
-
"",
|
|
50
|
-
"Analyze the test results and traceability matrix above. Produce a QA report summary that includes:",
|
|
51
|
-
"",
|
|
52
|
-
"1. Overall assessment of test health",
|
|
53
|
-
"2. Coverage gaps identified from the matrix",
|
|
54
|
-
"3. Recommendations for improving coverage",
|
|
55
|
-
"4. Risk areas where failures cluster",
|
|
56
|
-
"",
|
|
57
|
-
"## Expected Output",
|
|
58
|
-
"",
|
|
59
|
-
"Write a JSON object to the QA session ledger's `report` field:",
|
|
60
|
-
"",
|
|
61
|
-
"```json",
|
|
62
|
-
`{ "generatedAt": "ISO timestamp", "total": ${total}, "passed": ${passed}, "failed": ${failed}, "skipped": ${skipped}, "passRate": ${total > 0 ? Math.round((passed / total) * 100) : 0}, "failedTests": [...], "coverageSummary": "free-text analysis" }`,
|
|
63
|
-
"```",
|
|
64
|
-
"",
|
|
65
|
-
"## After Completion",
|
|
66
|
-
"",
|
|
67
|
-
"Update the QA session ledger with the report, mark the reporting phase as completed. The QA pipeline is now complete.",
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
return sections.join("\n");
|
|
71
|
-
}
|
package/src/qa/report.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
|
|
4
|
-
export interface QaReport {
|
|
5
|
-
timestamp: string;
|
|
6
|
-
framework: string;
|
|
7
|
-
scope: string;
|
|
8
|
-
totalTests: number;
|
|
9
|
-
passed: number;
|
|
10
|
-
failed: number;
|
|
11
|
-
skipped: number;
|
|
12
|
-
failures: { name: string; file: string; error: string }[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function saveQaReport(cwd: string, report: QaReport): string {
|
|
16
|
-
const dir = path.join(cwd, ".omp", "supipowers", "reports");
|
|
17
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
18
|
-
const filename = `qa-${report.timestamp.slice(0, 10)}.json`;
|
|
19
|
-
const filePath = path.join(dir, filename);
|
|
20
|
-
fs.writeFileSync(filePath, JSON.stringify(report, null, 2) + "\n");
|
|
21
|
-
return filePath;
|
|
22
|
-
}
|
package/src/qa/runner.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export function buildQaRunPrompt(
|
|
2
|
-
command: string,
|
|
3
|
-
scope: "all" | "changed" | "e2e",
|
|
4
|
-
changedFiles?: string[]
|
|
5
|
-
): string {
|
|
6
|
-
const sections: string[] = ["# QA Pipeline", ""];
|
|
7
|
-
|
|
8
|
-
switch (scope) {
|
|
9
|
-
case "all":
|
|
10
|
-
sections.push(`Run the full test suite: \`${command}\``);
|
|
11
|
-
break;
|
|
12
|
-
case "changed":
|
|
13
|
-
sections.push(
|
|
14
|
-
"Run tests related to changed files only:",
|
|
15
|
-
...(changedFiles ?? []).map((f) => `- ${f}`),
|
|
16
|
-
"",
|
|
17
|
-
`Base command: \`${command}\``,
|
|
18
|
-
"Filter to only tests relevant to the files above."
|
|
19
|
-
);
|
|
20
|
-
break;
|
|
21
|
-
case "e2e":
|
|
22
|
-
sections.push(
|
|
23
|
-
"Run end-to-end tests only.",
|
|
24
|
-
"Use Playwright or the configured E2E framework.",
|
|
25
|
-
"Command: `npx playwright test`"
|
|
26
|
-
);
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
sections.push(
|
|
31
|
-
"",
|
|
32
|
-
"Report results in this format:",
|
|
33
|
-
"- Total tests: N",
|
|
34
|
-
"- Passed: N",
|
|
35
|
-
"- Failed: N",
|
|
36
|
-
"- Skipped: N",
|
|
37
|
-
"",
|
|
38
|
-
"For each failure, include:",
|
|
39
|
-
"- Test name",
|
|
40
|
-
"- File path",
|
|
41
|
-
"- Error message",
|
|
42
|
-
"- Stack trace (first 5 lines)"
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
return sections.join("\n");
|
|
46
|
-
}
|