@mirnoorata/codexa 0.2.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/LICENSE +21 -0
- package/README.md +634 -0
- package/dist/artifacts.d.ts +2 -0
- package/dist/artifacts.js +375 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/autonomy.d.ts +17 -0
- package/dist/autonomy.js +124 -0
- package/dist/autonomy.js.map +1 -0
- package/dist/autoverify/policy.d.ts +5 -0
- package/dist/autoverify/policy.js +18 -0
- package/dist/autoverify/policy.js.map +1 -0
- package/dist/autoverify.d.ts +45 -0
- package/dist/autoverify.js +1041 -0
- package/dist/autoverify.js.map +1 -0
- package/dist/cache-lock.d.ts +16 -0
- package/dist/cache-lock.js +181 -0
- package/dist/cache-lock.js.map +1 -0
- package/dist/cli/hooks.d.ts +5 -0
- package/dist/cli/hooks.js +264 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1034 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-contract.d.ts +2 -0
- package/dist/codex-contract.js +78 -0
- package/dist/codex-contract.js.map +1 -0
- package/dist/command.d.ts +34 -0
- package/dist/command.js +162 -0
- package/dist/command.js.map +1 -0
- package/dist/doctor.d.ts +112 -0
- package/dist/doctor.js +518 -0
- package/dist/doctor.js.map +1 -0
- package/dist/eval/baseline.d.ts +7 -0
- package/dist/eval/baseline.js +146 -0
- package/dist/eval/baseline.js.map +1 -0
- package/dist/eval/historical.d.ts +4 -0
- package/dist/eval/historical.js +663 -0
- package/dist/eval/historical.js.map +1 -0
- package/dist/eval/render.d.ts +2 -0
- package/dist/eval/render.js +53 -0
- package/dist/eval/render.js.map +1 -0
- package/dist/eval/scoring.d.ts +21 -0
- package/dist/eval/scoring.js +618 -0
- package/dist/eval/scoring.js.map +1 -0
- package/dist/eval/synthetic.d.ts +36 -0
- package/dist/eval/synthetic.js +107 -0
- package/dist/eval/synthetic.js.map +1 -0
- package/dist/eval/types.d.ts +36 -0
- package/dist/eval/types.js +2 -0
- package/dist/eval/types.js.map +1 -0
- package/dist/eval.d.ts +140 -0
- package/dist/eval.js +551 -0
- package/dist/eval.js.map +1 -0
- package/dist/git.d.ts +17 -0
- package/dist/git.js +189 -0
- package/dist/git.js.map +1 -0
- package/dist/github-release.d.ts +47 -0
- package/dist/github-release.js +610 -0
- package/dist/github-release.js.map +1 -0
- package/dist/github-sync.d.ts +68 -0
- package/dist/github-sync.js +345 -0
- package/dist/github-sync.js.map +1 -0
- package/dist/graph.d.ts +10 -0
- package/dist/graph.js +665 -0
- package/dist/graph.js.map +1 -0
- package/dist/indexer/aliases.d.ts +2 -0
- package/dist/indexer/aliases.js +190 -0
- package/dist/indexer/aliases.js.map +1 -0
- package/dist/indexer/artifact-writing.d.ts +3 -0
- package/dist/indexer/artifact-writing.js +79 -0
- package/dist/indexer/artifact-writing.js.map +1 -0
- package/dist/indexer/discovery.d.ts +2 -0
- package/dist/indexer/discovery.js +5 -0
- package/dist/indexer/discovery.js.map +1 -0
- package/dist/indexer/external-facts.d.ts +6 -0
- package/dist/indexer/external-facts.js +45 -0
- package/dist/indexer/external-facts.js.map +1 -0
- package/dist/indexer/freshness.d.ts +8 -0
- package/dist/indexer/freshness.js +56 -0
- package/dist/indexer/freshness.js.map +1 -0
- package/dist/indexer/graph-stage.d.ts +2 -0
- package/dist/indexer/graph-stage.js +21 -0
- package/dist/indexer/graph-stage.js.map +1 -0
- package/dist/indexer/parsing.d.ts +30 -0
- package/dist/indexer/parsing.js +177 -0
- package/dist/indexer/parsing.js.map +1 -0
- package/dist/indexer/pipeline.d.ts +5 -0
- package/dist/indexer/pipeline.js +8 -0
- package/dist/indexer/pipeline.js.map +1 -0
- package/dist/indexer/ranking.d.ts +4 -0
- package/dist/indexer/ranking.js +134 -0
- package/dist/indexer/ranking.js.map +1 -0
- package/dist/indexer.d.ts +13 -0
- package/dist/indexer.js +395 -0
- package/dist/indexer.js.map +1 -0
- package/dist/init.d.ts +24 -0
- package/dist/init.js +566 -0
- package/dist/init.js.map +1 -0
- package/dist/language.d.ts +8 -0
- package/dist/language.js +123 -0
- package/dist/language.js.map +1 -0
- package/dist/live-index.d.ts +68 -0
- package/dist/live-index.js +215 -0
- package/dist/live-index.js.map +1 -0
- package/dist/lsp/assist.d.ts +44 -0
- package/dist/lsp/assist.js +331 -0
- package/dist/lsp/assist.js.map +1 -0
- package/dist/lsp/client.d.ts +59 -0
- package/dist/lsp/client.js +208 -0
- package/dist/lsp/client.js.map +1 -0
- package/dist/mcp/compaction.d.ts +15 -0
- package/dist/mcp/compaction.js +1249 -0
- package/dist/mcp/compaction.js.map +1 -0
- package/dist/mcp/envelope.d.ts +44 -0
- package/dist/mcp/envelope.js +425 -0
- package/dist/mcp/envelope.js.map +1 -0
- package/dist/mcp/prompts.d.ts +2 -0
- package/dist/mcp/prompts.js +109 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +2 -0
- package/dist/mcp/resources.js +132 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/runtime.d.ts +15 -0
- package/dist/mcp/runtime.js +122 -0
- package/dist/mcp/runtime.js.map +1 -0
- package/dist/mcp/session-memory.d.ts +3 -0
- package/dist/mcp/session-memory.js +61 -0
- package/dist/mcp/session-memory.js.map +1 -0
- package/dist/mcp/tool-registry.d.ts +269 -0
- package/dist/mcp/tool-registry.js +284 -0
- package/dist/mcp/tool-registry.js.map +1 -0
- package/dist/mcp/tools.d.ts +53 -0
- package/dist/mcp/tools.js +372 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp-repo-root.d.ts +16 -0
- package/dist/mcp-repo-root.js +322 -0
- package/dist/mcp-repo-root.js.map +1 -0
- package/dist/mcp-tool-catalog.d.ts +2 -0
- package/dist/mcp-tool-catalog.js +2 -0
- package/dist/mcp-tool-catalog.js.map +1 -0
- package/dist/mcp.d.ts +11 -0
- package/dist/mcp.js +332 -0
- package/dist/mcp.js.map +1 -0
- package/dist/outcome-ranking.d.ts +5 -0
- package/dist/outcome-ranking.js +115 -0
- package/dist/outcome-ranking.js.map +1 -0
- package/dist/parser/context.d.ts +28 -0
- package/dist/parser/context.js +2 -0
- package/dist/parser/context.js.map +1 -0
- package/dist/parser/ecma.d.ts +5 -0
- package/dist/parser/ecma.js +388 -0
- package/dist/parser/ecma.js.map +1 -0
- package/dist/parser/facts.d.ts +12 -0
- package/dist/parser/facts.js +137 -0
- package/dist/parser/facts.js.map +1 -0
- package/dist/parser/json.d.ts +3 -0
- package/dist/parser/json.js +318 -0
- package/dist/parser/json.js.map +1 -0
- package/dist/parser/markdown.d.ts +3 -0
- package/dist/parser/markdown.js +180 -0
- package/dist/parser/markdown.js.map +1 -0
- package/dist/parser/nodes.d.ts +5 -0
- package/dist/parser/nodes.js +75 -0
- package/dist/parser/nodes.js.map +1 -0
- package/dist/parser/python.d.ts +2 -0
- package/dist/parser/python.js +307 -0
- package/dist/parser/python.js.map +1 -0
- package/dist/parser/references.d.ts +3 -0
- package/dist/parser/references.js +204 -0
- package/dist/parser/references.js.map +1 -0
- package/dist/parser/risks.d.ts +4 -0
- package/dist/parser/risks.js +62 -0
- package/dist/parser/risks.js.map +1 -0
- package/dist/parser/routes.d.ts +5 -0
- package/dist/parser/routes.js +97 -0
- package/dist/parser/routes.js.map +1 -0
- package/dist/parser/shallow.d.ts +3 -0
- package/dist/parser/shallow.js +545 -0
- package/dist/parser/shallow.js.map +1 -0
- package/dist/parser/source.d.ts +4 -0
- package/dist/parser/source.js +127 -0
- package/dist/parser/source.js.map +1 -0
- package/dist/parser.d.ts +2 -0
- package/dist/parser.js +2 -0
- package/dist/parser.js.map +1 -0
- package/dist/placeholder-signals.d.ts +15 -0
- package/dist/placeholder-signals.js +511 -0
- package/dist/placeholder-signals.js.map +1 -0
- package/dist/post-edit-outcomes.d.ts +167 -0
- package/dist/post-edit-outcomes.js +484 -0
- package/dist/post-edit-outcomes.js.map +1 -0
- package/dist/queries.d.ts +12 -0
- package/dist/queries.js +13 -0
- package/dist/queries.js.map +1 -0
- package/dist/query/change-plan.d.ts +48 -0
- package/dist/query/change-plan.js +858 -0
- package/dist/query/change-plan.js.map +1 -0
- package/dist/query/compact-data.d.ts +25 -0
- package/dist/query/compact-data.js +74 -0
- package/dist/query/compact-data.js.map +1 -0
- package/dist/query/context.d.ts +5 -0
- package/dist/query/context.js +1162 -0
- package/dist/query/context.js.map +1 -0
- package/dist/query/diff.d.ts +5 -0
- package/dist/query/diff.js +111 -0
- package/dist/query/diff.js.map +1 -0
- package/dist/query/edge-evidence.d.ts +3 -0
- package/dist/query/edge-evidence.js +36 -0
- package/dist/query/edge-evidence.js.map +1 -0
- package/dist/query/formatting.d.ts +14 -0
- package/dist/query/formatting.js +67 -0
- package/dist/query/formatting.js.map +1 -0
- package/dist/query/graph-traversal.d.ts +22 -0
- package/dist/query/graph-traversal.js +218 -0
- package/dist/query/graph-traversal.js.map +1 -0
- package/dist/query/graph.d.ts +14 -0
- package/dist/query/graph.js +102 -0
- package/dist/query/graph.js.map +1 -0
- package/dist/query/impact.d.ts +28 -0
- package/dist/query/impact.js +568 -0
- package/dist/query/impact.js.map +1 -0
- package/dist/query/inspection.d.ts +9 -0
- package/dist/query/inspection.js +290 -0
- package/dist/query/inspection.js.map +1 -0
- package/dist/query/next-tools.d.ts +3 -0
- package/dist/query/next-tools.js +25 -0
- package/dist/query/next-tools.js.map +1 -0
- package/dist/query/placeholders.d.ts +24 -0
- package/dist/query/placeholders.js +121 -0
- package/dist/query/placeholders.js.map +1 -0
- package/dist/query/post-edit/decision.d.ts +49 -0
- package/dist/query/post-edit/decision.js +130 -0
- package/dist/query/post-edit/decision.js.map +1 -0
- package/dist/query/post-edit/dirty-scope.d.ts +16 -0
- package/dist/query/post-edit/dirty-scope.js +21 -0
- package/dist/query/post-edit/dirty-scope.js.map +1 -0
- package/dist/query/post-edit/next-actions.d.ts +22 -0
- package/dist/query/post-edit/next-actions.js +44 -0
- package/dist/query/post-edit/next-actions.js.map +1 -0
- package/dist/query/post-edit/snapshot-contract.d.ts +8 -0
- package/dist/query/post-edit/snapshot-contract.js +111 -0
- package/dist/query/post-edit/snapshot-contract.js.map +1 -0
- package/dist/query/post-edit.d.ts +5 -0
- package/dist/query/post-edit.js +1108 -0
- package/dist/query/post-edit.js.map +1 -0
- package/dist/query/quality.d.ts +43 -0
- package/dist/query/quality.js +134 -0
- package/dist/query/quality.js.map +1 -0
- package/dist/query/raw-search.d.ts +23 -0
- package/dist/query/raw-search.js +147 -0
- package/dist/query/raw-search.js.map +1 -0
- package/dist/query/runtime.d.ts +11 -0
- package/dist/query/runtime.js +79 -0
- package/dist/query/runtime.js.map +1 -0
- package/dist/query/search.d.ts +25 -0
- package/dist/query/search.js +429 -0
- package/dist/query/search.js.map +1 -0
- package/dist/query/session-memory.d.ts +3 -0
- package/dist/query/session-memory.js +108 -0
- package/dist/query/session-memory.js.map +1 -0
- package/dist/query/session.d.ts +41 -0
- package/dist/query/session.js +90 -0
- package/dist/query/session.js.map +1 -0
- package/dist/query/targets.d.ts +25 -0
- package/dist/query/targets.js +97 -0
- package/dist/query/targets.js.map +1 -0
- package/dist/query/test-commands.d.ts +10 -0
- package/dist/query/test-commands.js +110 -0
- package/dist/query/test-commands.js.map +1 -0
- package/dist/query/test-plan.d.ts +6 -0
- package/dist/query/test-plan.js +104 -0
- package/dist/query/test-plan.js.map +1 -0
- package/dist/query/tests.d.ts +48 -0
- package/dist/query/tests.js +444 -0
- package/dist/query/tests.js.map +1 -0
- package/dist/query/verification/shell.d.ts +20 -0
- package/dist/query/verification/shell.js +164 -0
- package/dist/query/verification/shell.js.map +1 -0
- package/dist/query/verification.d.ts +47 -0
- package/dist/query/verification.js +1123 -0
- package/dist/query/verification.js.map +1 -0
- package/dist/query/workflow.d.ts +17 -0
- package/dist/query/workflow.js +252 -0
- package/dist/query/workflow.js.map +1 -0
- package/dist/query/workspace-guidance.d.ts +26 -0
- package/dist/query/workspace-guidance.js +214 -0
- package/dist/query/workspace-guidance.js.map +1 -0
- package/dist/query/worktree-state.d.ts +22 -0
- package/dist/query/worktree-state.js +32 -0
- package/dist/query/worktree-state.js.map +1 -0
- package/dist/query/worktree.d.ts +16 -0
- package/dist/query/worktree.js +194 -0
- package/dist/query/worktree.js.map +1 -0
- package/dist/query-data.d.ts +4 -0
- package/dist/query-data.js +112 -0
- package/dist/query-data.js.map +1 -0
- package/dist/repo-files.d.ts +24 -0
- package/dist/repo-files.js +105 -0
- package/dist/repo-files.js.map +1 -0
- package/dist/resolver.d.ts +9 -0
- package/dist/resolver.js +555 -0
- package/dist/resolver.js.map +1 -0
- package/dist/retrieval.d.ts +46 -0
- package/dist/retrieval.js +783 -0
- package/dist/retrieval.js.map +1 -0
- package/dist/risk-ingest.d.ts +16 -0
- package/dist/risk-ingest.js +458 -0
- package/dist/risk-ingest.js.map +1 -0
- package/dist/rules.d.ts +10 -0
- package/dist/rules.js +107 -0
- package/dist/rules.js.map +1 -0
- package/dist/semantic/python.d.ts +9 -0
- package/dist/semantic/python.js +817 -0
- package/dist/semantic/python.js.map +1 -0
- package/dist/semantic/typescript.d.ts +10 -0
- package/dist/semantic/typescript.js +714 -0
- package/dist/semantic/typescript.js.map +1 -0
- package/dist/semantic-retrieval.d.ts +53 -0
- package/dist/semantic-retrieval.js +673 -0
- package/dist/semantic-retrieval.js.map +1 -0
- package/dist/session-memory/derivation.d.ts +6 -0
- package/dist/session-memory/derivation.js +400 -0
- package/dist/session-memory/derivation.js.map +1 -0
- package/dist/session-memory/event-log.d.ts +23 -0
- package/dist/session-memory/event-log.js +126 -0
- package/dist/session-memory/event-log.js.map +1 -0
- package/dist/session-memory/formatting.d.ts +7 -0
- package/dist/session-memory/formatting.js +86 -0
- package/dist/session-memory/formatting.js.map +1 -0
- package/dist/session-memory/model.d.ts +94 -0
- package/dist/session-memory/model.js +17 -0
- package/dist/session-memory/model.js.map +1 -0
- package/dist/session-memory/runtime.d.ts +24 -0
- package/dist/session-memory/runtime.js +289 -0
- package/dist/session-memory/runtime.js.map +1 -0
- package/dist/session-memory/store.d.ts +27 -0
- package/dist/session-memory/store.js +447 -0
- package/dist/session-memory/store.js.map +1 -0
- package/dist/session-memory.d.ts +1 -0
- package/dist/session-memory.js +2 -0
- package/dist/session-memory.js.map +1 -0
- package/dist/static-analysis.d.ts +36 -0
- package/dist/static-analysis.js +505 -0
- package/dist/static-analysis.js.map +1 -0
- package/dist/symbol-report-ingest.d.ts +8 -0
- package/dist/symbol-report-ingest.js +504 -0
- package/dist/symbol-report-ingest.js.map +1 -0
- package/dist/task-snapshots.d.ts +41 -0
- package/dist/task-snapshots.js +430 -0
- package/dist/task-snapshots.js.map +1 -0
- package/dist/types.d.ts +848 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +11 -0
- package/dist/util.js +63 -0
- package/dist/util.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/package.json +81 -0
- package/plugins/codexa/.codex-plugin/plugin.json +38 -0
- package/plugins/codexa/.mcp.json +20 -0
- package/plugins/codexa/scripts/codexa-mcp.js +100 -0
- package/plugins/codexa/skills/codexa/SKILL.md +48 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { isTestPath } from "../language.js";
|
|
3
|
+
import { uniqueSorted } from "../util.js";
|
|
4
|
+
import { candidateTestCommand } from "./test-commands.js";
|
|
5
|
+
/**
|
|
6
|
+
* Recommend tests to run for a set of changed paths.
|
|
7
|
+
*
|
|
8
|
+
* `changeType` narrows cross-language recommendations so editorial noise
|
|
9
|
+
* stays low:
|
|
10
|
+
*
|
|
11
|
+
* - "style" — the edit is a cosmetic/presentation change (CSS,
|
|
12
|
+
* Tailwind-class swap, template-only markup). Python pytest files are
|
|
13
|
+
* dropped from the recommendation list when no Python source was
|
|
14
|
+
* actually edited, because a style diff cannot break Python behavior.
|
|
15
|
+
* Likewise, TypeScript test files are dropped when no TS/JS source
|
|
16
|
+
* was edited.
|
|
17
|
+
* - "rename" / "delete" / "api" / "behavior" / "unknown" — today's
|
|
18
|
+
* behavior: surface everything the graph indicates.
|
|
19
|
+
*
|
|
20
|
+
* The filter only prunes authoritative/derived entries whose language
|
|
21
|
+
* demonstrably cannot be affected by the edited files. Heuristic/fallback
|
|
22
|
+
* entries already go through `compatibleKindWithTest()` for the same
|
|
23
|
+
* reason.
|
|
24
|
+
*/
|
|
25
|
+
export function recommendTests(index, paths, repoRoot = index.snapshot.repoRoot, changeType = "unknown") {
|
|
26
|
+
const changedSet = new Set(paths);
|
|
27
|
+
const candidates = new Map();
|
|
28
|
+
const changedKinds = new Set(paths.map(sourceKindForPath));
|
|
29
|
+
const add = (pathValue, reason, rank = 1, sourcePath, evidenceTier = "derived", directlyCoversChanged = false, provenanceSource = evidenceTier === "heuristic" || evidenceTier === "fallback" ? "heuristic_match" : "derived_impact_expansion", provenanceTargets = sourcePath ? [sourcePath] : paths) => {
|
|
30
|
+
const compatibilityGate = evidenceTier === "heuristic" || evidenceTier === "fallback";
|
|
31
|
+
if (sourcePath && compatibilityGate && !compatibleTestPath(sourcePath, pathValue)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!sourcePath && compatibilityGate && !compatibleWithAnyChanged(changedKinds, pathValue)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const existing = candidates.get(pathValue);
|
|
38
|
+
if (existing) {
|
|
39
|
+
existing.reasons.add(reason);
|
|
40
|
+
existing.rank += rank;
|
|
41
|
+
existing.evidenceTier = betterTier(existing.evidenceTier, evidenceTier);
|
|
42
|
+
existing.provenanceSources.add(provenanceSource);
|
|
43
|
+
for (const target of provenanceTargets) {
|
|
44
|
+
existing.provenanceTargets.add(target);
|
|
45
|
+
}
|
|
46
|
+
if (directlyCoversChanged) {
|
|
47
|
+
existing.directlyCoversChanged = true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
candidates.set(pathValue, {
|
|
52
|
+
path: pathValue,
|
|
53
|
+
reasons: new Set([reason]),
|
|
54
|
+
rank,
|
|
55
|
+
evidenceTier,
|
|
56
|
+
provenanceSources: new Set([provenanceSource]),
|
|
57
|
+
provenanceTargets: new Set(provenanceTargets),
|
|
58
|
+
directlyCoversChanged
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
for (const edge of index.testEdges) {
|
|
63
|
+
if (edge.targetPath && changedSet.has(edge.targetPath)) {
|
|
64
|
+
// Direct coverage of an edited file. NEVER filter this out on
|
|
65
|
+
// change-type narrowing — even if the test is a different language
|
|
66
|
+
// than the edit, this edge is the whole point.
|
|
67
|
+
add(edge.path, `${edge.reason}; covers ${edge.targetPath}`, 5, edge.targetPath, confidenceTier(edge.confidence), true, "authoritative_test_edge", [edge.targetPath]);
|
|
68
|
+
}
|
|
69
|
+
if (changedSet.has(edge.path)) {
|
|
70
|
+
add(edge.path, "changed test file", 4, edge.path, "authoritative", true, "explicit_target", [edge.path]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const related = transitiveImporters(index, paths, 2);
|
|
74
|
+
for (const [relatedPath, source] of related) {
|
|
75
|
+
const relatedFile = index.files.find((file) => file.path === relatedPath);
|
|
76
|
+
if (relatedFile?.test) {
|
|
77
|
+
// Reached via transitive importers — NOT direct coverage. Subject
|
|
78
|
+
// to change-type narrowing.
|
|
79
|
+
add(relatedFile.path, `imports ${source} through affected path`, 4, source, "authoritative", false, "derived_impact_expansion", [source]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
for (const edge of index.testEdges) {
|
|
83
|
+
if (edge.targetPath && related.has(edge.targetPath)) {
|
|
84
|
+
const source = related.get(edge.targetPath) ?? edge.targetPath;
|
|
85
|
+
add(edge.path, `${edge.reason}; covers ${edge.targetPath} via ${source}`, 4, source, confidenceTier(edge.confidence), false, "derived_impact_expansion", [source, edge.targetPath]);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const file of paths) {
|
|
89
|
+
const basename = path.posix.basename(file).replace(/\.[^.]+$/, "");
|
|
90
|
+
if (basename.length < 3) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
for (const testFile of index.files.filter((candidate) => candidate.test)) {
|
|
94
|
+
if (testFile.path.includes(basename)) {
|
|
95
|
+
add(testFile.path, `near ${file}`, 2, file, "heuristic", false, "heuristic_match", [file]);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const broadPackageRoots = new Set(["api", "backend", "server", "service", "src", "web", "tests", "scripts"]);
|
|
100
|
+
for (const file of paths.filter((candidate) => sourceKindForPath(candidate) === "python")) {
|
|
101
|
+
const packageRoot = file.split("/")[0];
|
|
102
|
+
if (!packageRoot || broadPackageRoots.has(packageRoot)) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const packageImportTests = new Set(index.imports.filter((edge) => isTestPath(edge.path) && edge.specifier.replace(/^\.+/, "").startsWith(packageRoot)).map((edge) => edge.path));
|
|
106
|
+
for (const testPath of packageImportTests) {
|
|
107
|
+
add(testPath, `imports ${packageRoot} package near ${file}`, 3, file, "derived", false, "package_import", [file]);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
for (const candidate of candidates.values()) {
|
|
111
|
+
const testFile = index.files.find((file) => file.path === candidate.path);
|
|
112
|
+
const outcomeBoost = Math.min(3, testFile?.rankReasons?.outcomeHistory ?? 0);
|
|
113
|
+
if (outcomeBoost > 0) {
|
|
114
|
+
candidate.rank += outcomeBoost;
|
|
115
|
+
candidate.reasons.add("outcome history: this test was recently missed, unaccounted for, or repeatedly needed");
|
|
116
|
+
candidate.provenanceSources.add("outcome_history");
|
|
117
|
+
candidate.provenanceTargets.add(candidate.path);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const withDirectCoverage = new Set();
|
|
121
|
+
for (const candidate of candidates.values()) {
|
|
122
|
+
if (candidate.directlyCoversChanged) {
|
|
123
|
+
withDirectCoverage.add(candidate.path);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const results = [...candidates.values()]
|
|
127
|
+
.map((candidate) => {
|
|
128
|
+
const command = candidateTestCommand(repoRoot, candidate.path);
|
|
129
|
+
const provenance = {
|
|
130
|
+
schemaVersion: 1,
|
|
131
|
+
origin: "current",
|
|
132
|
+
sources: uniqueSorted(candidate.provenanceSources),
|
|
133
|
+
targetPaths: uniqueSorted(candidate.provenanceTargets),
|
|
134
|
+
evidence: [...candidate.reasons].sort().slice(0, 8)
|
|
135
|
+
};
|
|
136
|
+
return {
|
|
137
|
+
path: candidate.path,
|
|
138
|
+
reason: limitReasonText([...candidate.reasons].sort().join("; ")),
|
|
139
|
+
rank: candidate.rank,
|
|
140
|
+
evidenceTier: candidate.evidenceTier,
|
|
141
|
+
command: command?.command,
|
|
142
|
+
commandCwd: command?.commandCwd,
|
|
143
|
+
commandExecutable: command?.commandExecutable,
|
|
144
|
+
commandArgs: command?.commandArgs,
|
|
145
|
+
commandSource: command?.source,
|
|
146
|
+
commandConfidence: command?.confidence,
|
|
147
|
+
provenance
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
const narrowed = narrowByChangeType(results, changedKinds, changeType, withDirectCoverage);
|
|
151
|
+
return narrowed.sort((a, b) => tierScore(a.evidenceTier ?? "fallback") - tierScore(b.evidenceTier ?? "fallback") ||
|
|
152
|
+
b.rank - a.rank ||
|
|
153
|
+
a.path.localeCompare(b.path));
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Apply change-type narrowing to an already-merged test recommendation
|
|
157
|
+
* set (e.g. snapshot-planned + context-derived + freshly-recommended).
|
|
158
|
+
* Safe to run on any list; it's a no-op for change types other than
|
|
159
|
+
* style and it never drops authoritative/derived tier entries.
|
|
160
|
+
*
|
|
161
|
+
* Used by post-edit review to ensure that a snapshot saved WITHOUT a
|
|
162
|
+
* change-type — the common case when `/codexa-plan` runs before the
|
|
163
|
+
* user decides the edit is cosmetic — still produces a clean
|
|
164
|
+
* recommendation set when the user later runs `--change-type style`.
|
|
165
|
+
*/
|
|
166
|
+
export function narrowTestRecommendationsByChangeType(results, paths, changeType) {
|
|
167
|
+
if (changeType !== "style") {
|
|
168
|
+
return results;
|
|
169
|
+
}
|
|
170
|
+
const changedKinds = new Set(paths.map(sourceKindForPath));
|
|
171
|
+
return narrowByChangeType(results, changedKinds, changeType, new Set());
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Drop test entries whose language demonstrably cannot be affected by the
|
|
175
|
+
* edited files for the given change type. For `style`, this means: if no
|
|
176
|
+
* Python source is in the dirty set, Python pytest files that came in
|
|
177
|
+
* only via a heuristic guess (package-scope, basename match, fallback)
|
|
178
|
+
* disappear — they would otherwise show up as low-signal noise in a
|
|
179
|
+
* pure CSS diff.
|
|
180
|
+
*
|
|
181
|
+
* What the filter deliberately does NOT touch:
|
|
182
|
+
* - authoritative / derived entries — the index proved coverage
|
|
183
|
+
* through explicit testEdges or transitive import chains. A TS
|
|
184
|
+
* snapshot test that covers a CSS file through App.tsx, or a
|
|
185
|
+
* server-rendering pytest that covers a template through a route,
|
|
186
|
+
* is exactly the test a style edit should run.
|
|
187
|
+
* - entries whose path directly covers an edited file (even at
|
|
188
|
+
* heuristic tier) — a deliberate match on the exact asset stays.
|
|
189
|
+
*
|
|
190
|
+
* So the effective scope of narrowing is: heuristic/fallback tier
|
|
191
|
+
* candidates whose language doesn't match any edited file's language.
|
|
192
|
+
*/
|
|
193
|
+
function narrowByChangeType(results, changedKinds, changeType, withDirectCoverage) {
|
|
194
|
+
if (changeType !== "style") {
|
|
195
|
+
return results;
|
|
196
|
+
}
|
|
197
|
+
const hasPythonChanges = changedKinds.has("python");
|
|
198
|
+
const hasTypescriptChanges = changedKinds.has("typescript");
|
|
199
|
+
return results.filter((entry) => {
|
|
200
|
+
if (withDirectCoverage.has(entry.path)) {
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
// Authoritative / derived entries come from the explicit test-edge
|
|
204
|
+
// graph and from transitive importers — both are proof of coverage
|
|
205
|
+
// through the dependency graph, not a guess. Never drop those on
|
|
206
|
+
// change-type narrowing; at worst the graph is wrong about a
|
|
207
|
+
// cross-language edge, which is a separate class of bug.
|
|
208
|
+
if (entry.evidenceTier === "authoritative" || entry.evidenceTier === "derived") {
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
const testKind = testFileKind(entry.path);
|
|
212
|
+
if (testKind === "python" && !hasPythonChanges) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
if (testKind === "typescript" && !hasTypescriptChanges) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
return true;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
function testFileKind(testPath) {
|
|
222
|
+
if (/\.py$/.test(testPath)) {
|
|
223
|
+
return "python";
|
|
224
|
+
}
|
|
225
|
+
if (/\.(test|spec)\.[cm]?[jt]sx?$/.test(testPath)) {
|
|
226
|
+
return "typescript";
|
|
227
|
+
}
|
|
228
|
+
return "other";
|
|
229
|
+
}
|
|
230
|
+
export function formatTestRecommendations(tests) {
|
|
231
|
+
if (tests.length === 0) {
|
|
232
|
+
return ["- No targeted test file found."];
|
|
233
|
+
}
|
|
234
|
+
const lines = tests.map((test) => {
|
|
235
|
+
const degraded = test.provenance?.degraded ? `; degraded: ${test.provenance.degradedReason ?? "provenance degraded"}` : "";
|
|
236
|
+
return `- ${test.path}: ${test.evidenceTier ?? "derived"}; ${test.reason}${degraded}`;
|
|
237
|
+
});
|
|
238
|
+
const commands = uniqueSorted(tests.flatMap((test) => (test.command ? [test.command] : [])));
|
|
239
|
+
if (commands.length === 0) {
|
|
240
|
+
return lines;
|
|
241
|
+
}
|
|
242
|
+
return [
|
|
243
|
+
...lines,
|
|
244
|
+
"",
|
|
245
|
+
"Candidate test commands:",
|
|
246
|
+
...commands.slice(0, 8).map((command) => {
|
|
247
|
+
const matching = tests.find((test) => test.command === command);
|
|
248
|
+
const source = matching?.commandSource ?? "unknown";
|
|
249
|
+
const confidence = matching?.commandConfidence ?? "heuristic";
|
|
250
|
+
return `- ${command} (${confidence}; source: ${source})`;
|
|
251
|
+
})
|
|
252
|
+
];
|
|
253
|
+
}
|
|
254
|
+
export function outcomeLearningRecommendations(tests, limit = 8) {
|
|
255
|
+
return tests
|
|
256
|
+
.filter((test) => hasOutcomeHistory(test))
|
|
257
|
+
.map((test) => {
|
|
258
|
+
const evidence = outcomeLearningEvidence(test);
|
|
259
|
+
return {
|
|
260
|
+
path: test.path,
|
|
261
|
+
rank: test.rank,
|
|
262
|
+
reason: test.reason,
|
|
263
|
+
command: test.command,
|
|
264
|
+
targetPaths: uniqueSorted(test.provenance?.targetPaths ?? [test.path]).slice(0, 8),
|
|
265
|
+
sources: uniqueSorted(test.provenance?.sources ?? ["outcome_history"]),
|
|
266
|
+
evidence
|
|
267
|
+
};
|
|
268
|
+
})
|
|
269
|
+
.sort((a, b) => b.rank - a.rank || a.path.localeCompare(b.path))
|
|
270
|
+
.slice(0, limit);
|
|
271
|
+
}
|
|
272
|
+
export function formatOutcomeLearningRecommendations(recommendations) {
|
|
273
|
+
if (recommendations.length === 0) {
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
return recommendations.map((entry) => {
|
|
277
|
+
const evidence = entry.evidence.length > 0 ? `; ${entry.evidence.slice(0, 2).join("; ")}` : "";
|
|
278
|
+
const command = entry.command ? `; command: ${entry.command}` : "";
|
|
279
|
+
return `- ${entry.path}: outcome history raised priority${evidence}${command}`;
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
export function uniqueTests(tests) {
|
|
283
|
+
const byPath = new Map();
|
|
284
|
+
for (const test of tests) {
|
|
285
|
+
const existing = byPath.get(test.path);
|
|
286
|
+
if (!existing) {
|
|
287
|
+
byPath.set(test.path, test);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
byPath.set(test.path, mergeTestRecommendations(existing, test));
|
|
291
|
+
}
|
|
292
|
+
return [...byPath.values()].sort((a, b) => tierScore(a.evidenceTier ?? "fallback") - tierScore(b.evidenceTier ?? "fallback") || b.rank - a.rank || a.path.localeCompare(b.path));
|
|
293
|
+
}
|
|
294
|
+
export function wasTestRun(test, ranTests) {
|
|
295
|
+
if (ranTests.length === 0) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
const expected = normalizeDirectTestIdentity(test.path);
|
|
299
|
+
return ranTests.some((entry) => normalizeDirectTestIdentity(entry) === expected);
|
|
300
|
+
}
|
|
301
|
+
function mergeTestRecommendations(existing, candidate) {
|
|
302
|
+
const existingDegraded = existing.provenance?.degraded === true;
|
|
303
|
+
const candidateDegraded = candidate.provenance?.degraded === true;
|
|
304
|
+
const preferred = existingDegraded !== candidateDegraded
|
|
305
|
+
? candidateDegraded
|
|
306
|
+
? existing
|
|
307
|
+
: candidate
|
|
308
|
+
: tierScore(candidate.evidenceTier ?? "fallback") < tierScore(existing.evidenceTier ?? "fallback") || candidate.rank > existing.rank
|
|
309
|
+
? candidate
|
|
310
|
+
: existing;
|
|
311
|
+
const other = preferred === existing ? candidate : existing;
|
|
312
|
+
return {
|
|
313
|
+
...preferred,
|
|
314
|
+
reason: limitReasonText(uniqueSorted([preferred.reason, other.reason].filter(Boolean)).join("; ")),
|
|
315
|
+
rank: Math.max(preferred.rank, other.rank),
|
|
316
|
+
evidenceTier: betterTier(preferred.evidenceTier ?? "fallback", other.evidenceTier ?? "fallback"),
|
|
317
|
+
provenance: mergeTestProvenance(preferred.provenance, other.provenance)
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
function mergeTestProvenance(a, b) {
|
|
321
|
+
if (!a && !b) {
|
|
322
|
+
return undefined;
|
|
323
|
+
}
|
|
324
|
+
if (a?.degraded === true && b && b.degraded !== true) {
|
|
325
|
+
return b;
|
|
326
|
+
}
|
|
327
|
+
if (b?.degraded === true && a && a.degraded !== true) {
|
|
328
|
+
return a;
|
|
329
|
+
}
|
|
330
|
+
const base = a && !a.degraded ? a : b && !b.degraded ? b : a ?? b;
|
|
331
|
+
return {
|
|
332
|
+
schemaVersion: 1,
|
|
333
|
+
origin: base.origin,
|
|
334
|
+
sources: uniqueSorted([...(a?.sources ?? []), ...(b?.sources ?? [])]),
|
|
335
|
+
targetPaths: uniqueSorted([...(a?.targetPaths ?? []), ...(b?.targetPaths ?? [])]),
|
|
336
|
+
evidence: uniqueSorted([...(a?.evidence ?? []), ...(b?.evidence ?? [])]).slice(0, 10),
|
|
337
|
+
degraded: a?.degraded === true && b?.degraded === true ? true : undefined,
|
|
338
|
+
degradedReason: a?.degraded === true && b?.degraded === true ? a.degradedReason ?? b.degradedReason : undefined
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function hasOutcomeHistory(test) {
|
|
342
|
+
return test.provenance?.sources.includes("outcome_history") === true || /\boutcome history\b/iu.test(test.reason);
|
|
343
|
+
}
|
|
344
|
+
function outcomeLearningEvidence(test) {
|
|
345
|
+
const evidence = uniqueSorted([
|
|
346
|
+
...(test.provenance?.evidence ?? []).filter((entry) => /\boutcome\b/iu.test(entry)),
|
|
347
|
+
...test.reason
|
|
348
|
+
.split(";")
|
|
349
|
+
.map((entry) => entry.trim())
|
|
350
|
+
.filter((entry) => /\boutcome\b/iu.test(entry))
|
|
351
|
+
]).slice(0, 5);
|
|
352
|
+
return evidence.length > 0 ? evidence : [test.reason];
|
|
353
|
+
}
|
|
354
|
+
function transitiveImporters(index, sourcePaths, maxDepth) {
|
|
355
|
+
const result = new Map();
|
|
356
|
+
const queue = sourcePaths.map((sourcePath) => ({ path: sourcePath, origin: sourcePath, depth: 0 }));
|
|
357
|
+
const seen = new Set(queue.map((entry) => entry.path));
|
|
358
|
+
for (const entry of queue) {
|
|
359
|
+
result.set(entry.path, entry.origin);
|
|
360
|
+
}
|
|
361
|
+
for (let cursor = 0; cursor < queue.length; cursor += 1) {
|
|
362
|
+
const current = queue[cursor];
|
|
363
|
+
if (current.depth >= maxDepth) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
for (const edge of index.imports.filter((candidate) => candidate.resolvedPath === current.path)) {
|
|
367
|
+
if (seen.has(edge.path)) {
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
seen.add(edge.path);
|
|
371
|
+
result.set(edge.path, current.origin);
|
|
372
|
+
queue.push({ path: edge.path, origin: current.origin, depth: current.depth + 1 });
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return result;
|
|
376
|
+
}
|
|
377
|
+
function compatibleWithAnyChanged(changedKinds, testPath) {
|
|
378
|
+
if (changedKinds.size === 0) {
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
381
|
+
return [...changedKinds].some((kind) => kind === "unknown" || compatibleKindWithTest(kind, testPath));
|
|
382
|
+
}
|
|
383
|
+
function compatibleTestPath(sourcePath, testPath) {
|
|
384
|
+
return compatibleKindWithTest(sourceKindForPath(sourcePath), testPath);
|
|
385
|
+
}
|
|
386
|
+
function compatibleKindWithTest(kind, testPath) {
|
|
387
|
+
if (kind === "python") {
|
|
388
|
+
return /\.py$/.test(testPath);
|
|
389
|
+
}
|
|
390
|
+
if (kind === "typescript") {
|
|
391
|
+
return /\.(test|spec)\.[cm]?[jt]sx?$/.test(testPath);
|
|
392
|
+
}
|
|
393
|
+
if (kind === "manifest") {
|
|
394
|
+
return /\.py$/.test(testPath) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(testPath);
|
|
395
|
+
}
|
|
396
|
+
if (kind === "operator" || kind === "unknown") {
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
function sourceKindForPath(filePath) {
|
|
402
|
+
if (/\.py$/.test(filePath)) {
|
|
403
|
+
return "python";
|
|
404
|
+
}
|
|
405
|
+
if (/\.[cm]?[jt]sx?$/.test(filePath)) {
|
|
406
|
+
return "typescript";
|
|
407
|
+
}
|
|
408
|
+
if (/\.json$/.test(filePath)) {
|
|
409
|
+
return "manifest";
|
|
410
|
+
}
|
|
411
|
+
if (/\.(sh|service)$/.test(filePath) || filePath.startsWith("scripts/")) {
|
|
412
|
+
return "operator";
|
|
413
|
+
}
|
|
414
|
+
return "unknown";
|
|
415
|
+
}
|
|
416
|
+
function confidenceTier(confidence) {
|
|
417
|
+
if (confidence === "authoritative")
|
|
418
|
+
return "authoritative";
|
|
419
|
+
if (confidence === "derived")
|
|
420
|
+
return "derived";
|
|
421
|
+
return "heuristic";
|
|
422
|
+
}
|
|
423
|
+
function betterTier(a, b) {
|
|
424
|
+
return tierScore(a) <= tierScore(b) ? a : b;
|
|
425
|
+
}
|
|
426
|
+
function tierScore(tier) {
|
|
427
|
+
return tier === "authoritative" ? 0 : tier === "derived" ? 1 : tier === "heuristic" ? 2 : 3;
|
|
428
|
+
}
|
|
429
|
+
function normalizeDirectTestIdentity(value) {
|
|
430
|
+
const trimmed = value.trim();
|
|
431
|
+
if (/\s/u.test(trimmed)) {
|
|
432
|
+
return "";
|
|
433
|
+
}
|
|
434
|
+
return trimmed
|
|
435
|
+
.replace(/\\/gu, "/")
|
|
436
|
+
.replace(/^\.\//u, "")
|
|
437
|
+
.replace(/\/+/gu, "/")
|
|
438
|
+
.replace(/(\.py)::.*$/u, "$1")
|
|
439
|
+
.toLowerCase();
|
|
440
|
+
}
|
|
441
|
+
function limitReasonText(value, maxLength = 360) {
|
|
442
|
+
return value.length <= maxLength ? value : `${value.slice(0, maxLength - 14).trimEnd()} ... truncated`;
|
|
443
|
+
}
|
|
444
|
+
//# sourceMappingURL=tests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tests.js","sourceRoot":"","sources":["../../src/query/tests.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type ShellControlOperator = "start" | "&&" | "||" | "|" | ";";
|
|
2
|
+
export type ShellTruthiness = "true" | "false" | "unknown";
|
|
3
|
+
export declare function splitShellSequence(command: string): Array<{
|
|
4
|
+
text: string;
|
|
5
|
+
operator: ShellControlOperator;
|
|
6
|
+
}>;
|
|
7
|
+
export declare function segmentTruthiness(segment: string): ShellTruthiness;
|
|
8
|
+
export declare function shellWords(value: string): string[];
|
|
9
|
+
export declare function shellQuote(value: string): string;
|
|
10
|
+
export declare function stripQuotes(value: string): string;
|
|
11
|
+
export declare function isNonRunningCommand(words: string[]): boolean;
|
|
12
|
+
export declare function shellWrappedCommand(words: string[]): string | undefined;
|
|
13
|
+
export declare function hasNonRunningJavaScriptTestArg(args: string[]): boolean;
|
|
14
|
+
export declare function hasNonRunningPythonTestArg(args: string[]): boolean;
|
|
15
|
+
export declare function hasNonRunningCommandArg(args: string[]): boolean;
|
|
16
|
+
export declare function stripPackageManagerFlags(words: string[]): string[];
|
|
17
|
+
export declare function hasPnpmWorkspaceFlag(words: string[]): boolean;
|
|
18
|
+
export declare function stripLeadingEnvironment(words: string[]): string[];
|
|
19
|
+
export declare function stripShellControlWords(words: string[]): string[];
|
|
20
|
+
export declare function isEnvironmentAssignment(value: string | undefined): boolean;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
export function splitShellSequence(command) {
|
|
2
|
+
const segments = [];
|
|
3
|
+
let quote;
|
|
4
|
+
let current = "";
|
|
5
|
+
let operator = "start";
|
|
6
|
+
for (let index = 0; index < command.length; index += 1) {
|
|
7
|
+
const char = command[index];
|
|
8
|
+
const next = command[index + 1];
|
|
9
|
+
if ((char === "'" || char === '"') && command[index - 1] !== "\\") {
|
|
10
|
+
quote = quote === char ? undefined : quote ?? char;
|
|
11
|
+
current += char;
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (!quote && ((char === "&" && next === "&") || (char === "|" && next === "|"))) {
|
|
15
|
+
if (current.trim()) {
|
|
16
|
+
segments.push({ text: current.trim(), operator });
|
|
17
|
+
}
|
|
18
|
+
operator = char === "&" ? "&&" : "||";
|
|
19
|
+
current = "";
|
|
20
|
+
index += 1;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (!quote && char === "|") {
|
|
24
|
+
if (current.trim()) {
|
|
25
|
+
segments.push({ text: current.trim(), operator });
|
|
26
|
+
}
|
|
27
|
+
operator = "|";
|
|
28
|
+
current = "";
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (!quote && char === ";") {
|
|
32
|
+
if (current.trim()) {
|
|
33
|
+
segments.push({ text: current.trim(), operator });
|
|
34
|
+
}
|
|
35
|
+
operator = ";";
|
|
36
|
+
current = "";
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
current += char;
|
|
40
|
+
}
|
|
41
|
+
if (current.trim()) {
|
|
42
|
+
segments.push({ text: current.trim(), operator });
|
|
43
|
+
}
|
|
44
|
+
return segments;
|
|
45
|
+
}
|
|
46
|
+
export function segmentTruthiness(segment) {
|
|
47
|
+
const words = stripShellControlWords(stripLeadingEnvironment(shellWords(segment)));
|
|
48
|
+
const first = words[0];
|
|
49
|
+
if (first === "true" || first === ":") {
|
|
50
|
+
return "true";
|
|
51
|
+
}
|
|
52
|
+
if (first === "false") {
|
|
53
|
+
return "false";
|
|
54
|
+
}
|
|
55
|
+
if (first === "exit" && words[1]) {
|
|
56
|
+
const code = Number.parseInt(words[1], 10);
|
|
57
|
+
if (Number.isFinite(code)) {
|
|
58
|
+
return code === 0 ? "true" : "false";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return "unknown";
|
|
62
|
+
}
|
|
63
|
+
export function shellWords(value) {
|
|
64
|
+
return [...value.matchAll(/'([^']*)'|"([^"]*)"|(\S+)/gu)].map((match) => stripQuotes(match[1] ?? match[2] ?? match[3] ?? ""));
|
|
65
|
+
}
|
|
66
|
+
export function shellQuote(value) {
|
|
67
|
+
if (/^[A-Za-z0-9_@%+=:,./-]+$/u.test(value)) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
return `'${value.replace(/'/gu, "'\\''")}'`;
|
|
71
|
+
}
|
|
72
|
+
export function stripQuotes(value) {
|
|
73
|
+
return value.replace(/^['"]|['"]$/gu, "");
|
|
74
|
+
}
|
|
75
|
+
export function isNonRunningCommand(words) {
|
|
76
|
+
return words[0] === "echo" || words[0] === "printf";
|
|
77
|
+
}
|
|
78
|
+
export function shellWrappedCommand(words) {
|
|
79
|
+
const first = words[0];
|
|
80
|
+
if (first !== "bash" && first !== "sh" && first !== "zsh") {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
for (let index = 1; index < words.length; index += 1) {
|
|
84
|
+
const word = words[index];
|
|
85
|
+
if (word === "-c" || word === "-lc" || word === "-cl" || (word.startsWith("-") && word.includes("c"))) {
|
|
86
|
+
return words[index + 1];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
export function hasNonRunningJavaScriptTestArg(args) {
|
|
92
|
+
return args.some((arg) => ["--version", "-v", "-V", "--help", "-h", "help"].includes(arg));
|
|
93
|
+
}
|
|
94
|
+
export function hasNonRunningPythonTestArg(args) {
|
|
95
|
+
return args.some((arg) => ["--version", "-V", "--help", "-h", "help"].includes(arg));
|
|
96
|
+
}
|
|
97
|
+
export function hasNonRunningCommandArg(args) {
|
|
98
|
+
return args.some((arg) => ["--version", "-v", "-V", "--help", "-h", "help"].includes(arg));
|
|
99
|
+
}
|
|
100
|
+
export function stripPackageManagerFlags(words) {
|
|
101
|
+
const first = words[0];
|
|
102
|
+
if (first !== "npm" && first !== "pnpm" && first !== "yarn") {
|
|
103
|
+
return words;
|
|
104
|
+
}
|
|
105
|
+
const noValueFlags = new Set(["--silent", "-s", "--no-progress", "--color", "--no-color"]);
|
|
106
|
+
const valueFlags = new Set(["--loglevel", "--userconfig", "--cache"]);
|
|
107
|
+
const stripped = [first];
|
|
108
|
+
let index = 1;
|
|
109
|
+
while (index < words.length) {
|
|
110
|
+
const word = words[index];
|
|
111
|
+
if (noValueFlags.has(word) || /^--(?:color|no-color|silent|no-progress)=/u.test(word)) {
|
|
112
|
+
index += 1;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (valueFlags.has(word) && words[index + 1]) {
|
|
116
|
+
index += 2;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (flagValue(word, [...valueFlags])) {
|
|
120
|
+
index += 1;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
return [...stripped, ...words.slice(index)];
|
|
126
|
+
}
|
|
127
|
+
export function hasPnpmWorkspaceFlag(words) {
|
|
128
|
+
return words.some((word) => word === "-r" || word === "recursive" || word === "--recursive" || word === "--filter" || word === "-F" || word.startsWith("--filter=") || word.startsWith("-F="));
|
|
129
|
+
}
|
|
130
|
+
export function stripLeadingEnvironment(words) {
|
|
131
|
+
let index = 0;
|
|
132
|
+
if (words[index] === "env") {
|
|
133
|
+
index += 1;
|
|
134
|
+
while (index < words.length && (words[index] === "-i" || words[index] === "--ignore-environment")) {
|
|
135
|
+
index += 1;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
while (index < words.length && isEnvironmentAssignment(words[index])) {
|
|
139
|
+
index += 1;
|
|
140
|
+
}
|
|
141
|
+
return words.slice(index);
|
|
142
|
+
}
|
|
143
|
+
export function stripShellControlWords(words) {
|
|
144
|
+
let index = 0;
|
|
145
|
+
while (words[index] === "then" || words[index] === "do") {
|
|
146
|
+
index += 1;
|
|
147
|
+
}
|
|
148
|
+
return words.slice(index);
|
|
149
|
+
}
|
|
150
|
+
export function isEnvironmentAssignment(value) {
|
|
151
|
+
return Boolean(value && /^[A-Za-z_][A-Za-z0-9_]*=/u.test(value));
|
|
152
|
+
}
|
|
153
|
+
function flagValue(word, flags) {
|
|
154
|
+
if (!word) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
for (const flag of flags) {
|
|
158
|
+
if (word.startsWith(`${flag}=`)) {
|
|
159
|
+
return word.slice(flag.length + 1);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=shell.js.map
|