@loopover/engine 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.
- package/CHANGELOG.md +94 -0
- package/LICENSE +661 -0
- package/README.md +676 -0
- package/dist/advisory/gate-advisory.d.ts +151 -0
- package/dist/advisory/gate-advisory.js +512 -0
- package/dist/ai-policy-map.d.ts +97 -0
- package/dist/ai-policy-map.js +377 -0
- package/dist/ams-policy-spec.d.ts +56 -0
- package/dist/ams-policy-spec.js +165 -0
- package/dist/calibration-dashboard.d.ts +23 -0
- package/dist/calibration-dashboard.js +65 -0
- package/dist/calibration-trend.d.ts +40 -0
- package/dist/calibration-trend.js +60 -0
- package/dist/contributor-fit.d.ts +24 -0
- package/dist/contributor-fit.js +50 -0
- package/dist/discovery-index-contract.d.ts +74 -0
- package/dist/discovery-index-contract.js +184 -0
- package/dist/discovery-soft-claim.d.ts +35 -0
- package/dist/discovery-soft-claim.js +50 -0
- package/dist/duplicate-winner.d.ts +57 -0
- package/dist/duplicate-winner.js +98 -0
- package/dist/feasibility.d.ts +27 -0
- package/dist/feasibility.js +86 -0
- package/dist/finding-severity-calibration.d.ts +116 -0
- package/dist/finding-severity-calibration.js +457 -0
- package/dist/fleet-run-manifest.d.ts +41 -0
- package/dist/fleet-run-manifest.js +151 -0
- package/dist/focus-manifest/guidance.d.ts +21 -0
- package/dist/focus-manifest/guidance.js +222 -0
- package/dist/focus-manifest.d.ts +826 -0
- package/dist/focus-manifest.js +2730 -0
- package/dist/gate-verdict-calibration.d.ts +111 -0
- package/dist/gate-verdict-calibration.js +411 -0
- package/dist/github/constants.d.ts +1 -0
- package/dist/github/constants.js +1 -0
- package/dist/github/sanitize-public-comment.d.ts +1 -0
- package/dist/github/sanitize-public-comment.js +26 -0
- package/dist/goal-model.d.ts +7 -0
- package/dist/goal-model.js +87 -0
- package/dist/governor/action-mode.d.ts +55 -0
- package/dist/governor/action-mode.js +74 -0
- package/dist/governor/budget-cap.d.ts +49 -0
- package/dist/governor/budget-cap.js +34 -0
- package/dist/governor/chokepoint.d.ts +58 -0
- package/dist/governor/chokepoint.js +269 -0
- package/dist/governor/kill-switch.d.ts +38 -0
- package/dist/governor/kill-switch.js +62 -0
- package/dist/governor/rate-limit.d.ts +40 -0
- package/dist/governor/rate-limit.js +63 -0
- package/dist/governor/reputation-throttle.d.ts +50 -0
- package/dist/governor/reputation-throttle.js +94 -0
- package/dist/governor/run-halt.d.ts +39 -0
- package/dist/governor/run-halt.js +83 -0
- package/dist/governor/self-plagiarism.d.ts +47 -0
- package/dist/governor/self-plagiarism.js +200 -0
- package/dist/governor/write-rate-limit.d.ts +52 -0
- package/dist/governor/write-rate-limit.js +132 -0
- package/dist/governor-ledger.d.ts +25 -0
- package/dist/governor-ledger.js +91 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.js +120 -0
- package/dist/issue-plan-decomposition.d.ts +18 -0
- package/dist/issue-plan-decomposition.js +56 -0
- package/dist/issue-rag-query.d.ts +12 -0
- package/dist/issue-rag-query.js +35 -0
- package/dist/local-scorer.d.ts +34 -0
- package/dist/local-scorer.js +36 -0
- package/dist/metadata-best-min-score.d.ts +9 -0
- package/dist/metadata-best-min-score.js +9 -0
- package/dist/metadata-best-pick.d.ts +9 -0
- package/dist/metadata-best-pick.js +9 -0
- package/dist/metadata-min-score.d.ts +9 -0
- package/dist/metadata-min-score.js +13 -0
- package/dist/metadata-top-min-score.d.ts +9 -0
- package/dist/metadata-top-min-score.js +13 -0
- package/dist/metadata-top-pick.d.ts +9 -0
- package/dist/metadata-top-pick.js +13 -0
- package/dist/miner/acceptance-criteria.d.ts +43 -0
- package/dist/miner/acceptance-criteria.js +77 -0
- package/dist/miner/agent-sdk-driver.d.ts +39 -0
- package/dist/miner/agent-sdk-driver.js +162 -0
- package/dist/miner/attempt-log.d.ts +29 -0
- package/dist/miner/attempt-log.js +100 -0
- package/dist/miner/attempt-metering.d.ts +39 -0
- package/dist/miner/attempt-metering.js +67 -0
- package/dist/miner/cli-subprocess-driver.d.ts +68 -0
- package/dist/miner/cli-subprocess-driver.js +272 -0
- package/dist/miner/coding-agent-driver.d.ts +33 -0
- package/dist/miner/coding-agent-driver.js +36 -0
- package/dist/miner/coding-agent-invoke.d.ts +11 -0
- package/dist/miner/coding-agent-invoke.js +80 -0
- package/dist/miner/coding-agent-mode.d.ts +25 -0
- package/dist/miner/coding-agent-mode.js +43 -0
- package/dist/miner/driver-factory.d.ts +82 -0
- package/dist/miner/driver-factory.js +169 -0
- package/dist/miner/harness-submission-trigger.d.ts +37 -0
- package/dist/miner/harness-submission-trigger.js +46 -0
- package/dist/miner/iterate-loop.d.ts +97 -0
- package/dist/miner/iterate-loop.js +278 -0
- package/dist/miner/iterate-policy.d.ts +98 -0
- package/dist/miner/iterate-policy.js +98 -0
- package/dist/miner/lint-guard.d.ts +50 -0
- package/dist/miner/lint-guard.js +68 -0
- package/dist/miner/local-write-tools.d.ts +81 -0
- package/dist/miner/local-write-tools.js +113 -0
- package/dist/miner/loop-reentry-policy.d.ts +36 -0
- package/dist/miner/loop-reentry-policy.js +53 -0
- package/dist/miner/repo-map.d.ts +51 -0
- package/dist/miner/repo-map.js +268 -0
- package/dist/miner/self-review-adapter.d.ts +106 -0
- package/dist/miner/self-review-adapter.js +83 -0
- package/dist/miner/submission-gate.d.ts +40 -0
- package/dist/miner/submission-gate.js +89 -0
- package/dist/miner/worktree-allocator.d.ts +59 -0
- package/dist/miner/worktree-allocator.js +60 -0
- package/dist/miner/worktree-pool.d.ts +55 -0
- package/dist/miner/worktree-pool.js +65 -0
- package/dist/miner-goal-lane-fit.d.ts +18 -0
- package/dist/miner-goal-lane-fit.js +76 -0
- package/dist/miner-goal-spec.d.ts +139 -0
- package/dist/miner-goal-spec.js +281 -0
- package/dist/miner-prediction-metrics.d.ts +16 -0
- package/dist/miner-prediction-metrics.js +61 -0
- package/dist/miner-telemetry.d.ts +32 -0
- package/dist/miner-telemetry.js +87 -0
- package/dist/objective-anchor.d.ts +125 -0
- package/dist/objective-anchor.js +401 -0
- package/dist/opportunity-competition.d.ts +6 -0
- package/dist/opportunity-competition.js +29 -0
- package/dist/opportunity-freshness.d.ts +18 -0
- package/dist/opportunity-freshness.js +55 -0
- package/dist/opportunity-metadata.d.ts +53 -0
- package/dist/opportunity-metadata.js +204 -0
- package/dist/opportunity-ranker.d.ts +46 -0
- package/dist/opportunity-ranker.js +74 -0
- package/dist/pairwise-calibration.d.ts +49 -0
- package/dist/pairwise-calibration.js +106 -0
- package/dist/phase7-calibration-loop.d.ts +136 -0
- package/dist/phase7-calibration-loop.js +437 -0
- package/dist/plan-blocked.d.ts +6 -0
- package/dist/plan-blocked.js +24 -0
- package/dist/plan-completed.d.ts +5 -0
- package/dist/plan-completed.js +6 -0
- package/dist/plan-completion.d.ts +6 -0
- package/dist/plan-completion.js +7 -0
- package/dist/plan-empty.d.ts +5 -0
- package/dist/plan-empty.js +6 -0
- package/dist/plan-export.d.ts +27 -0
- package/dist/plan-export.js +86 -0
- package/dist/plan-failure.d.ts +5 -0
- package/dist/plan-failure.js +6 -0
- package/dist/plan-overall-status.d.ts +6 -0
- package/dist/plan-overall-status.js +25 -0
- package/dist/plan-pending.d.ts +5 -0
- package/dist/plan-pending.js +6 -0
- package/dist/plan-progress-complete.d.ts +7 -0
- package/dist/plan-progress-complete.js +10 -0
- package/dist/plan-ready.d.ts +6 -0
- package/dist/plan-ready.js +12 -0
- package/dist/plan-running.d.ts +5 -0
- package/dist/plan-running.js +6 -0
- package/dist/plan-skipped.d.ts +5 -0
- package/dist/plan-skipped.js +6 -0
- package/dist/plan-step-count.d.ts +5 -0
- package/dist/plan-step-count.js +6 -0
- package/dist/plan-step-stats.d.ts +5 -0
- package/dist/plan-step-stats.js +6 -0
- package/dist/plan-templates.d.ts +25 -0
- package/dist/plan-templates.js +107 -0
- package/dist/plan-terminated.d.ts +6 -0
- package/dist/plan-terminated.js +9 -0
- package/dist/portfolio/non-convergence.d.ts +37 -0
- package/dist/portfolio/non-convergence.js +57 -0
- package/dist/portfolio/queue.d.ts +30 -0
- package/dist/portfolio/queue.js +150 -0
- package/dist/predicted-gate.d.ts +103 -0
- package/dist/predicted-gate.js +218 -0
- package/dist/prompt-packet.d.ts +11 -0
- package/dist/prompt-packet.js +34 -0
- package/dist/ranked-opportunity-best-min-score.d.ts +8 -0
- package/dist/ranked-opportunity-best-min-score.js +9 -0
- package/dist/ranked-opportunity-best-pick.d.ts +8 -0
- package/dist/ranked-opportunity-best-pick.js +9 -0
- package/dist/ranked-opportunity-min-score.d.ts +8 -0
- package/dist/ranked-opportunity-min-score.js +13 -0
- package/dist/ranked-opportunity-top-min-score.d.ts +8 -0
- package/dist/ranked-opportunity-top-min-score.js +13 -0
- package/dist/review/advisory-ai-routing-config.d.ts +8 -0
- package/dist/review/advisory-ai-routing-config.js +40 -0
- package/dist/review/check-names.d.ts +1 -0
- package/dist/review/check-names.js +1 -0
- package/dist/review/cla-check.d.ts +49 -0
- package/dist/review/cla-check.js +71 -0
- package/dist/review/diff-file-priority.d.ts +1 -0
- package/dist/review/diff-file-priority.js +12 -0
- package/dist/review/enrichment-analyzer-names.d.ts +3 -0
- package/dist/review/enrichment-analyzer-names.js +63 -0
- package/dist/review/guardrail-config.d.ts +10 -0
- package/dist/review/guardrail-config.js +62 -0
- package/dist/review/linked-issue-hard-rules-config.d.ts +4 -0
- package/dist/review/linked-issue-hard-rules-config.js +79 -0
- package/dist/review/linked-issue-label-propagation.d.ts +9 -0
- package/dist/review/linked-issue-label-propagation.js +114 -0
- package/dist/review/pre-merge-checks.d.ts +28 -0
- package/dist/review/pre-merge-checks.js +66 -0
- package/dist/review/review-thread-findings.d.ts +1 -0
- package/dist/review/review-thread-findings.js +1 -0
- package/dist/review/safe-url.d.ts +5 -0
- package/dist/review/safe-url.js +137 -0
- package/dist/review/screenshot-table-gate.d.ts +87 -0
- package/dist/review/screenshot-table-gate.js +340 -0
- package/dist/review/unlinked-issue-guardrail-config.d.ts +9 -0
- package/dist/review/unlinked-issue-guardrail-config.js +44 -0
- package/dist/reviewer-consensus-calibration.d.ts +113 -0
- package/dist/reviewer-consensus-calibration.js +493 -0
- package/dist/reward-risk.d.ts +223 -0
- package/dist/reward-risk.js +618 -0
- package/dist/scoring/label-match.d.ts +4 -0
- package/dist/scoring/label-match.js +145 -0
- package/dist/scoring/model.d.ts +31 -0
- package/dist/scoring/model.js +157 -0
- package/dist/scoring/pending-pr-scenarios.d.ts +44 -0
- package/dist/scoring/pending-pr-scenarios.js +145 -0
- package/dist/scoring/preview.d.ts +246 -0
- package/dist/scoring/preview.js +1108 -0
- package/dist/scoring/types.d.ts +131 -0
- package/dist/scoring/types.js +7 -0
- package/dist/settings/auto-close-exempt.d.ts +10 -0
- package/dist/settings/auto-close-exempt.js +58 -0
- package/dist/settings/autonomy.d.ts +33 -0
- package/dist/settings/autonomy.js +80 -0
- package/dist/settings/command-authorization.d.ts +49 -0
- package/dist/settings/command-authorization.js +222 -0
- package/dist/settings/contributor-blacklist.d.ts +17 -0
- package/dist/settings/contributor-blacklist.js +86 -0
- package/dist/settings/moderation-rules.d.ts +51 -0
- package/dist/settings/moderation-rules.js +104 -0
- package/dist/settings/pr-type-label.d.ts +70 -0
- package/dist/settings/pr-type-label.js +149 -0
- package/dist/signals/change-guardrail.d.ts +49 -0
- package/dist/signals/change-guardrail.js +164 -0
- package/dist/signals/check-summary.d.ts +9 -0
- package/dist/signals/check-summary.js +12 -0
- package/dist/signals/contributor-calibration.d.ts +23 -0
- package/dist/signals/contributor-calibration.js +47 -0
- package/dist/signals/duplicate-winner.d.ts +9 -0
- package/dist/signals/duplicate-winner.js +9 -0
- package/dist/signals/path-matchers.d.ts +36 -0
- package/dist/signals/path-matchers.js +371 -0
- package/dist/signals/predicted-gate-engine.d.ts +62 -0
- package/dist/signals/predicted-gate-engine.js +895 -0
- package/dist/signals/preflight-limits.d.ts +14 -0
- package/dist/signals/preflight-limits.js +14 -0
- package/dist/signals/slop.d.ts +56 -0
- package/dist/signals/slop.js +324 -0
- package/dist/signals/test-evidence.d.ts +25 -0
- package/dist/signals/test-evidence.js +108 -0
- package/dist/subprocess-env.d.ts +23 -0
- package/dist/subprocess-env.js +74 -0
- package/dist/track-record-summary.d.ts +92 -0
- package/dist/track-record-summary.js +301 -0
- package/dist/types/manifest-deps-types.d.ts +514 -0
- package/dist/types/manifest-deps-types.js +4 -0
- package/dist/types/predicted-gate-types.d.ts +338 -0
- package/dist/types/predicted-gate-types.js +3 -0
- package/dist/types/reward-risk-types.d.ts +319 -0
- package/dist/types/reward-risk-types.js +11 -0
- package/dist/utils/json.d.ts +1 -0
- package/dist/utils/json.js +3 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +3 -0
- package/package.json +80 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
const FOCUS_MANIFEST_TERMS = /\b(reward\w*|score\w*|wallets?|hotkeys?|coldkeys?|seed[-\s]?phrases?|mnemonics?|private[-\s]?keys?|farming|payouts?|rankings?|raw[-\s]?trust(?:[-\s]?scores?)?|trust[-\s]?scores?|private[-\s]?reviewability|reviewability(?:[-\s]?internals?)?|private[-\s]?scoreability|scoreability|public[-\s]?score[-\s]?(?:estimate|prediction|claim)s?|estimated[-\s]?scores?|score[-\s]?(?:estimate|prediction|preview)s?)\b/i;
|
|
2
|
+
const FOCUS_MANIFEST_LOCAL_PATH_PATTERN = new RegExp(String.raw `/Users/|/home/|/root/|/var/|/opt/|/tmp/|/private/|[A-Za-z]:[\\/]Users[\\/]|[A-Za-z]:[\\/]Program Files[\\/]`, "i");
|
|
3
|
+
export function isFocusManifestPublicSafe(text) {
|
|
4
|
+
return !FOCUS_MANIFEST_TERMS.test(text) && !FOCUS_MANIFEST_LOCAL_PATH_PATTERN.test(text);
|
|
5
|
+
}
|
|
6
|
+
const MAX_GLOBSTAR_SLASH_ALTERNATIVES = 128;
|
|
7
|
+
function normalizePathForMatch(path) {
|
|
8
|
+
return String(path).replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/+/, "").toLowerCase();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* LINEAR-TIME wildcard matcher for a `*`-glob pattern over an already-normalized path. `*` (and a collapsed
|
|
12
|
+
* run of `*`) matches any run of characters INCLUDING `/` (gittensory globs cross slashes). Implemented as a
|
|
13
|
+
* prefix + suffix + ordered-substring (indexOf) scan rather than a `.*`-per-star regex: the old regex
|
|
14
|
+
* (`^.*a.*a...$`) backtracks catastrophically on a near-miss path and could hang the gate for an entire repo
|
|
15
|
+
* (a manifest glob with many non-adjacent `*`). This algorithm is O(path × parts) with NO backtracking.
|
|
16
|
+
*/
|
|
17
|
+
function linearGlobMatcher(pattern) {
|
|
18
|
+
// The caller only compiles this for a pattern that contains a wildcard, so split always yields >= 2 parts.
|
|
19
|
+
const parts = pattern.split(/\*+/); // literal segments between (collapsed) wildcard runs
|
|
20
|
+
const first = parts[0];
|
|
21
|
+
const last = parts[parts.length - 1];
|
|
22
|
+
const middles = parts.slice(1, -1).filter((part) => part.length > 0);
|
|
23
|
+
return (path) => {
|
|
24
|
+
if (!path.startsWith(first) || !path.endsWith(last))
|
|
25
|
+
return false;
|
|
26
|
+
let idx = first.length;
|
|
27
|
+
for (const part of middles) {
|
|
28
|
+
const found = path.indexOf(part, idx);
|
|
29
|
+
if (found === -1)
|
|
30
|
+
return false;
|
|
31
|
+
idx = found + part.length;
|
|
32
|
+
}
|
|
33
|
+
return path.length - last.length >= idx; // the suffix must not overlap the consumed prefix/middles
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Compile a manifest path pattern into a predicate over an ALREADY-normalized path. Supports exact paths,
|
|
38
|
+
* directory prefixes (`src/` or `src`), and `*` wildcards (`*` and a double-star both match any run of chars
|
|
39
|
+
* across `/`). A double-star-then-separator prefix means "zero or more path segments", so the mandatory slash
|
|
40
|
+
* is absorbed and a double-star glob also matches a ROOT-level (zero-depth) file, not only nested ones.
|
|
41
|
+
* Compiling once lets a caller test many paths against one pattern without recompiling per path — see
|
|
42
|
+
* {@link matchedPatterns}. An empty/blank pattern never matches.
|
|
43
|
+
*/
|
|
44
|
+
function expandGlobstarSlash(pattern) {
|
|
45
|
+
const alternatives = [""];
|
|
46
|
+
for (let idx = 0; idx < pattern.length;) {
|
|
47
|
+
if (pattern.startsWith("**/", idx)) {
|
|
48
|
+
const count = alternatives.length;
|
|
49
|
+
const canKeepRootAlternatives = count * 2 <= MAX_GLOBSTAR_SLASH_ALTERNATIVES;
|
|
50
|
+
for (let altIdx = count - 1; altIdx >= 0; altIdx -= 1) {
|
|
51
|
+
const prefix = alternatives[altIdx];
|
|
52
|
+
alternatives[altIdx] = `${prefix}*/`;
|
|
53
|
+
if (canKeepRootAlternatives)
|
|
54
|
+
alternatives.push(prefix);
|
|
55
|
+
}
|
|
56
|
+
idx += 3;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
for (let altIdx = 0; altIdx < alternatives.length; altIdx += 1)
|
|
60
|
+
alternatives[altIdx] += pattern[idx];
|
|
61
|
+
idx += 1;
|
|
62
|
+
}
|
|
63
|
+
return alternatives;
|
|
64
|
+
}
|
|
65
|
+
function compileManifestPathMatcher(pattern) {
|
|
66
|
+
const normalizedPattern = normalizePathForMatch(pattern);
|
|
67
|
+
if (!normalizedPattern)
|
|
68
|
+
return () => false;
|
|
69
|
+
if (normalizedPattern.includes("*")) {
|
|
70
|
+
// `**/` means zero or more whole path segments. Keep the slash in the non-root alternative so
|
|
71
|
+
// basename globs (e.g. `**/safe.ts`) do not degrade into suffix globs that match `unsafe.ts`.
|
|
72
|
+
const matchers = expandGlobstarSlash(normalizedPattern).map((globbed) => globbed.includes("*") ? linearGlobMatcher(globbed) : (normalizedPath) => normalizedPath === globbed);
|
|
73
|
+
return (normalizedPath) => matchers.some((matcher) => matcher(normalizedPath));
|
|
74
|
+
}
|
|
75
|
+
const dirPattern = normalizedPattern.endsWith("/") ? normalizedPattern : `${normalizedPattern}/`;
|
|
76
|
+
return (normalizedPath) => normalizedPath === normalizedPattern || normalizedPath.startsWith(dirPattern);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Match a changed path against a manifest path pattern. Supports exact paths, directory
|
|
80
|
+
* prefixes (`src/` or `src`), and `*` wildcards (`**` collapses to `*`).
|
|
81
|
+
*/
|
|
82
|
+
export function matchesManifestPath(path, pattern) {
|
|
83
|
+
const normalizedPath = normalizePathForMatch(path);
|
|
84
|
+
if (!normalizedPath)
|
|
85
|
+
return false;
|
|
86
|
+
return compileManifestPathMatcher(pattern)(normalizedPath);
|
|
87
|
+
}
|
|
88
|
+
function matchedPatterns(paths, patterns) {
|
|
89
|
+
// Normalize each path once and compile each pattern once, instead of redoing both for every (path,
|
|
90
|
+
// pattern) pair — the wildcard regex was previously recompiled per path.
|
|
91
|
+
const normalizedPaths = paths.map(normalizePathForMatch).filter(Boolean);
|
|
92
|
+
return patterns.filter((pattern) => {
|
|
93
|
+
const matches = compileManifestPathMatcher(pattern);
|
|
94
|
+
return normalizedPaths.some((normalizedPath) => matches(normalizedPath));
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Build deterministic, public-safe guidance from a focus manifest for a concrete change set.
|
|
99
|
+
* Explains why changed paths are preferred or discouraged and surfaces manifest-driven blockers
|
|
100
|
+
* without leaking maintainer-private notes into public next steps.
|
|
101
|
+
*/
|
|
102
|
+
export function buildFocusManifestGuidance(args) {
|
|
103
|
+
const { manifest } = args;
|
|
104
|
+
const changedPaths = args.changedPaths.filter((path) => typeof path === "string" && path.length > 0);
|
|
105
|
+
const labels = (args.labels ?? []).map((label) => label.toLowerCase());
|
|
106
|
+
const linkedIssueCount = Math.max(0, args.linkedIssueCount ?? 0);
|
|
107
|
+
const testFileCount = Math.max(0, args.testFileCount ?? 0);
|
|
108
|
+
const passedValidationCount = Math.max(0, args.passedValidationCount ?? 0);
|
|
109
|
+
const matchedWantedPaths = matchedPatterns(changedPaths, manifest.wantedPaths);
|
|
110
|
+
const preferredLabelHits = manifest.preferredLabels.filter((label) => labels.includes(label.toLowerCase()));
|
|
111
|
+
const findings = [];
|
|
112
|
+
const publicNextSteps = [];
|
|
113
|
+
if (!manifest.present) {
|
|
114
|
+
for (const warning of manifest.warnings) {
|
|
115
|
+
findings.push({ code: "manifest_malformed", severity: "info", title: "Maintainer focus manifest not applied", detail: warning });
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
present: false,
|
|
119
|
+
source: manifest.source,
|
|
120
|
+
linkedIssuePolicy: manifest.linkedIssuePolicy,
|
|
121
|
+
issueDiscoveryPolicy: manifest.issueDiscoveryPolicy,
|
|
122
|
+
matchedWantedPaths: [],
|
|
123
|
+
preferredLabelHits: [],
|
|
124
|
+
findings,
|
|
125
|
+
publicNextSteps: [],
|
|
126
|
+
warnings: manifest.warnings,
|
|
127
|
+
summary: "No maintainer focus manifest applied; using deterministic signals only.",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (manifest.wantedPaths.length > 0 && matchedWantedPaths.length === 0 && changedPaths.length > 0) {
|
|
131
|
+
findings.push({
|
|
132
|
+
code: "manifest_off_focus",
|
|
133
|
+
severity: "warning",
|
|
134
|
+
title: "Change is outside maintainer-wanted areas",
|
|
135
|
+
detail: `No changed path matches the maintainer-wanted patterns (${manifest.wantedPaths.slice(0, 5).join(", ")}).`,
|
|
136
|
+
action: "Refocus the change onto a maintainer-wanted area or explain why this out-of-focus work is needed.",
|
|
137
|
+
});
|
|
138
|
+
publicNextSteps.push("Refocus onto the maintainer-wanted areas, or explain why this out-of-focus change is needed.");
|
|
139
|
+
}
|
|
140
|
+
if (matchedWantedPaths.length > 0) {
|
|
141
|
+
findings.push({
|
|
142
|
+
code: "manifest_preferred_path",
|
|
143
|
+
severity: "info",
|
|
144
|
+
title: "Change aligns with maintainer-wanted areas",
|
|
145
|
+
detail: `Changed paths match maintainer-wanted patterns: ${matchedWantedPaths.slice(0, 5).join(", ")}.`,
|
|
146
|
+
});
|
|
147
|
+
publicNextSteps.push("Changed paths align with the maintainer's wanted areas for this repo.");
|
|
148
|
+
}
|
|
149
|
+
if (manifest.preferredLabels.length > 0 && preferredLabelHits.length === 0) {
|
|
150
|
+
findings.push({
|
|
151
|
+
code: "manifest_missing_preferred_label",
|
|
152
|
+
severity: "info",
|
|
153
|
+
title: "No maintainer-preferred label applied",
|
|
154
|
+
detail: `Maintainer prefers labels: ${manifest.preferredLabels.slice(0, 5).join(", ")}.`,
|
|
155
|
+
action: "Consider applying a maintainer-preferred label so triage stays aligned.",
|
|
156
|
+
});
|
|
157
|
+
publicNextSteps.push(`Consider a maintainer-preferred label (${manifest.preferredLabels.slice(0, 3).join(", ")}).`);
|
|
158
|
+
}
|
|
159
|
+
if (manifest.linkedIssuePolicy === "required" && linkedIssueCount === 0) {
|
|
160
|
+
findings.push({
|
|
161
|
+
code: "manifest_linked_issue_required",
|
|
162
|
+
severity: "warning",
|
|
163
|
+
title: "Maintainer requires a linked issue",
|
|
164
|
+
detail: "This repo's maintainer focus manifest requires every PR to reference a tracked issue.",
|
|
165
|
+
action: "Link the relevant issue (for example `Closes #123`) before opening the PR.",
|
|
166
|
+
});
|
|
167
|
+
publicNextSteps.push("Link the relevant tracked issue; the maintainer requires linked issues on PRs.");
|
|
168
|
+
}
|
|
169
|
+
else if (manifest.linkedIssuePolicy === "preferred" && linkedIssueCount === 0) {
|
|
170
|
+
findings.push({
|
|
171
|
+
code: "manifest_linked_issue_preferred",
|
|
172
|
+
severity: "info",
|
|
173
|
+
title: "Maintainer prefers a linked issue",
|
|
174
|
+
detail: "This repo's maintainer focus manifest prefers PRs to reference a tracked issue.",
|
|
175
|
+
action: "Link a tracked issue if one exists.",
|
|
176
|
+
});
|
|
177
|
+
publicNextSteps.push("Link a tracked issue if one exists; the maintainer prefers linked issues.");
|
|
178
|
+
}
|
|
179
|
+
if (manifest.testExpectations.length > 0 && testFileCount === 0 && passedValidationCount === 0) {
|
|
180
|
+
const safeExpectations = manifest.testExpectations.filter(isFocusManifestPublicSafe).slice(0, 3);
|
|
181
|
+
const expectationDetail = safeExpectations.length > 0 ? ` Expected evidence: ${safeExpectations.join("; ")}.` : "";
|
|
182
|
+
findings.push({
|
|
183
|
+
code: "manifest_missing_tests",
|
|
184
|
+
severity: "warning",
|
|
185
|
+
title: "Configured validation evidence missing",
|
|
186
|
+
detail: `No changed test files or passing validation evidence were detected for this PR.${expectationDetail}`,
|
|
187
|
+
action: "Add regression/invariant coverage, update relevant tests, or attach passing validation output that satisfies the repo's configured expectations.",
|
|
188
|
+
});
|
|
189
|
+
publicNextSteps.push("Add relevant tests or passing validation evidence that matches the repo's configured expectations.");
|
|
190
|
+
}
|
|
191
|
+
if (manifest.issueDiscoveryPolicy === "discouraged") {
|
|
192
|
+
findings.push({
|
|
193
|
+
code: "manifest_issue_discovery_discouraged",
|
|
194
|
+
severity: "info",
|
|
195
|
+
title: "Maintainer discourages issue-discovery reports",
|
|
196
|
+
detail: "This repo's maintainer focus manifest discourages new issue-discovery reports; prefer direct fixes.",
|
|
197
|
+
action: "Prefer a direct PR over filing a new issue-discovery report here.",
|
|
198
|
+
});
|
|
199
|
+
publicNextSteps.push("This repo prefers direct fixes over new issue-discovery reports.");
|
|
200
|
+
}
|
|
201
|
+
const safePublicNotes = manifest.publicNotes.filter(isFocusManifestPublicSafe);
|
|
202
|
+
const safeNextSteps = [...new Set([...publicNextSteps, ...safePublicNotes])].filter(isFocusManifestPublicSafe);
|
|
203
|
+
return {
|
|
204
|
+
present: true,
|
|
205
|
+
source: manifest.source,
|
|
206
|
+
linkedIssuePolicy: manifest.linkedIssuePolicy,
|
|
207
|
+
issueDiscoveryPolicy: manifest.issueDiscoveryPolicy,
|
|
208
|
+
matchedWantedPaths,
|
|
209
|
+
preferredLabelHits,
|
|
210
|
+
findings,
|
|
211
|
+
publicNextSteps: safeNextSteps,
|
|
212
|
+
warnings: manifest.warnings,
|
|
213
|
+
summary: summarize(manifest, matchedWantedPaths),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function summarize(manifest, wanted) {
|
|
217
|
+
if (wanted.length > 0)
|
|
218
|
+
return "Maintainer focus manifest: change aligns with a wanted area.";
|
|
219
|
+
if (manifest.wantedPaths.length > 0)
|
|
220
|
+
return "Maintainer focus manifest: change is outside the wanted areas.";
|
|
221
|
+
return "Maintainer focus manifest applied with no path-specific verdict.";
|
|
222
|
+
}
|