@sentry/warden 0.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/.agents/skills/find-bugs/SKILL.md +75 -0
- package/.agents/skills/vercel-react-best-practices/AGENTS.md +2934 -0
- package/.agents/skills/vercel-react-best-practices/SKILL.md +136 -0
- package/.agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/.agents/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
- package/.agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
- package/.agents/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
- package/.agents/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
- package/.agents/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
- package/.agents/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
- package/.agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/.agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/.agents/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
- package/.agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/.agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/.agents/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
- package/.agents/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
- package/.agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/.agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/.agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/.agents/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
- package/.agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/.agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/.agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/.agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/.agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/.agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
- package/.agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/.agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/.agents/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
- package/.agents/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
- package/.agents/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
- package/.agents/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
- package/.agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/.agents/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
- package/.claude/settings.json +57 -0
- package/.claude/settings.local.json +88 -0
- package/.claude/skills/agent-prompt/SKILL.md +54 -0
- package/.claude/skills/agent-prompt/references/agentic-patterns.md +94 -0
- package/.claude/skills/agent-prompt/references/anti-patterns.md +140 -0
- package/.claude/skills/agent-prompt/references/context-design.md +124 -0
- package/.claude/skills/agent-prompt/references/core-principles.md +75 -0
- package/.claude/skills/agent-prompt/references/model-guidance.md +118 -0
- package/.claude/skills/agent-prompt/references/output-formats.md +98 -0
- package/.claude/skills/agent-prompt/references/skill-structure.md +115 -0
- package/.claude/skills/agent-prompt/references/system-prompts.md +115 -0
- package/.claude/skills/notseer/SKILL.md +131 -0
- package/.claude/skills/skill-writer/SKILL.md +140 -0
- package/.claude/skills/testing-guidelines/SKILL.md +132 -0
- package/.claude/skills/warden-skill/SKILL.md +250 -0
- package/.claude/skills/warden-skill/references/config-schema.md +133 -0
- package/.dex/config.toml +2 -0
- package/.github/workflows/ci.yml +33 -0
- package/.github/workflows/release.yml +54 -0
- package/.github/workflows/warden.yml +40 -0
- package/AGENTS.md +89 -0
- package/CONTRIBUTING.md +60 -0
- package/LICENSE +105 -0
- package/README.md +43 -0
- package/SPEC.md +263 -0
- package/action.yml +87 -0
- package/assets/favicon.png +0 -0
- package/assets/warden-icon-bw.svg +5 -0
- package/assets/warden-icon-purple.png +0 -0
- package/assets/warden-icon-purple.svg +5 -0
- package/docs/.claude/settings.local.json +11 -0
- package/docs/astro.config.mjs +43 -0
- package/docs/package.json +19 -0
- package/docs/pnpm-lock.yaml +4000 -0
- package/docs/public/favicon.svg +5 -0
- package/docs/src/components/Code.astro +141 -0
- package/docs/src/components/PackageManagerTabs.astro +183 -0
- package/docs/src/components/Terminal.astro +212 -0
- package/docs/src/layouts/Base.astro +380 -0
- package/docs/src/pages/cli.astro +167 -0
- package/docs/src/pages/config.astro +394 -0
- package/docs/src/pages/guide.astro +449 -0
- package/docs/src/pages/index.astro +490 -0
- package/docs/src/styles/global.css +551 -0
- package/docs/tsconfig.json +3 -0
- package/docs/vercel.json +5 -0
- package/eslint.config.js +33 -0
- package/package.json +73 -0
- package/src/action/index.ts +1 -0
- package/src/action/main.ts +868 -0
- package/src/cli/args.test.ts +477 -0
- package/src/cli/args.ts +415 -0
- package/src/cli/commands/add.ts +447 -0
- package/src/cli/commands/init.test.ts +136 -0
- package/src/cli/commands/init.ts +132 -0
- package/src/cli/commands/setup-app/browser.ts +38 -0
- package/src/cli/commands/setup-app/credentials.ts +45 -0
- package/src/cli/commands/setup-app/manifest.ts +48 -0
- package/src/cli/commands/setup-app/server.ts +172 -0
- package/src/cli/commands/setup-app.ts +156 -0
- package/src/cli/commands/sync.ts +114 -0
- package/src/cli/context.ts +131 -0
- package/src/cli/files.test.ts +155 -0
- package/src/cli/files.ts +89 -0
- package/src/cli/fix.test.ts +310 -0
- package/src/cli/fix.ts +387 -0
- package/src/cli/git.test.ts +119 -0
- package/src/cli/git.ts +318 -0
- package/src/cli/index.ts +14 -0
- package/src/cli/main.ts +672 -0
- package/src/cli/output/box.ts +235 -0
- package/src/cli/output/formatters.test.ts +187 -0
- package/src/cli/output/formatters.ts +269 -0
- package/src/cli/output/icons.ts +13 -0
- package/src/cli/output/index.ts +44 -0
- package/src/cli/output/ink-runner.tsx +337 -0
- package/src/cli/output/jsonl.test.ts +347 -0
- package/src/cli/output/jsonl.ts +126 -0
- package/src/cli/output/reporter.ts +435 -0
- package/src/cli/output/tasks.ts +374 -0
- package/src/cli/output/tty.test.ts +117 -0
- package/src/cli/output/tty.ts +60 -0
- package/src/cli/output/verbosity.test.ts +40 -0
- package/src/cli/output/verbosity.ts +31 -0
- package/src/cli/terminal.test.ts +148 -0
- package/src/cli/terminal.ts +301 -0
- package/src/config/index.ts +3 -0
- package/src/config/loader.test.ts +313 -0
- package/src/config/loader.ts +103 -0
- package/src/config/schema.ts +168 -0
- package/src/config/writer.test.ts +119 -0
- package/src/config/writer.ts +84 -0
- package/src/diff/classify.test.ts +162 -0
- package/src/diff/classify.ts +92 -0
- package/src/diff/coalesce.test.ts +208 -0
- package/src/diff/coalesce.ts +133 -0
- package/src/diff/context.test.ts +226 -0
- package/src/diff/context.ts +201 -0
- package/src/diff/index.ts +4 -0
- package/src/diff/parser.test.ts +212 -0
- package/src/diff/parser.ts +149 -0
- package/src/event/context.ts +132 -0
- package/src/event/index.ts +2 -0
- package/src/event/schedule-context.ts +101 -0
- package/src/examples/examples.integration.test.ts +66 -0
- package/src/examples/index.test.ts +101 -0
- package/src/examples/index.ts +122 -0
- package/src/examples/setup.ts +25 -0
- package/src/index.ts +115 -0
- package/src/output/dedup.test.ts +419 -0
- package/src/output/dedup.ts +607 -0
- package/src/output/github-checks.test.ts +300 -0
- package/src/output/github-checks.ts +476 -0
- package/src/output/github-issues.ts +329 -0
- package/src/output/index.ts +5 -0
- package/src/output/issue-renderer.ts +197 -0
- package/src/output/renderer.test.ts +727 -0
- package/src/output/renderer.ts +217 -0
- package/src/output/stale.test.ts +375 -0
- package/src/output/stale.ts +155 -0
- package/src/output/types.ts +34 -0
- package/src/sdk/index.ts +1 -0
- package/src/sdk/runner.test.ts +806 -0
- package/src/sdk/runner.ts +1232 -0
- package/src/skills/index.ts +36 -0
- package/src/skills/loader.test.ts +300 -0
- package/src/skills/loader.ts +423 -0
- package/src/skills/remote.test.ts +704 -0
- package/src/skills/remote.ts +604 -0
- package/src/triggers/matcher.test.ts +277 -0
- package/src/triggers/matcher.ts +152 -0
- package/src/types/index.ts +194 -0
- package/src/utils/async.ts +18 -0
- package/src/utils/index.test.ts +84 -0
- package/src/utils/index.ts +50 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +8 -0
- package/vitest.integration.config.ts +11 -0
- package/warden.toml +19 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { Octokit } from '@octokit/rest';
|
|
2
|
+
import type { ExistingComment } from './dedup.js';
|
|
3
|
+
import type { Finding, FileChange } from '../types/index.js';
|
|
4
|
+
import { generateContentHash } from './dedup.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Scope of analyzed files in the PR.
|
|
8
|
+
*/
|
|
9
|
+
export interface AnalyzedScope {
|
|
10
|
+
/** Set of file paths that were in the diff */
|
|
11
|
+
files: Set<string>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Build the analyzed scope from file changes.
|
|
16
|
+
*/
|
|
17
|
+
export function buildAnalyzedScope(fileChanges: FileChange[]): AnalyzedScope {
|
|
18
|
+
return {
|
|
19
|
+
files: new Set(fileChanges.map((f) => f.filename)),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check if a comment's file was in the analyzed scope.
|
|
25
|
+
* Only comments on files that were analyzed should be considered for resolution.
|
|
26
|
+
*/
|
|
27
|
+
export function isInAnalyzedScope(comment: ExistingComment, scope: AnalyzedScope): boolean {
|
|
28
|
+
return scope.files.has(comment.path);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Check if a finding matches a comment (same location and similar content).
|
|
33
|
+
*/
|
|
34
|
+
function findingMatchesComment(finding: Finding, comment: ExistingComment): boolean {
|
|
35
|
+
// Must have a location to match
|
|
36
|
+
if (!finding.location) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// File path must match
|
|
41
|
+
if (finding.location.path !== comment.path) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check line proximity - findings may shift a few lines
|
|
46
|
+
const findingLine = finding.location.endLine ?? finding.location.startLine;
|
|
47
|
+
const lineDiff = Math.abs(findingLine - comment.line);
|
|
48
|
+
if (lineDiff > 5) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check content hash for exact match
|
|
53
|
+
const findingHash = generateContentHash(finding.title, finding.description);
|
|
54
|
+
if (findingHash === comment.contentHash) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// If hashes don't match exactly, check if the title is similar enough
|
|
59
|
+
// This handles cases where description might have minor changes
|
|
60
|
+
const normalizedFindingTitle = finding.title.toLowerCase().trim();
|
|
61
|
+
const normalizedCommentTitle = comment.title.toLowerCase().trim();
|
|
62
|
+
return normalizedFindingTitle === normalizedCommentTitle;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Find comments that no longer have matching findings (stale comments).
|
|
67
|
+
* Only considers comments on files that were in the analyzed scope.
|
|
68
|
+
*/
|
|
69
|
+
export function findStaleComments(
|
|
70
|
+
existingComments: ExistingComment[],
|
|
71
|
+
allFindings: Finding[],
|
|
72
|
+
scope: AnalyzedScope
|
|
73
|
+
): ExistingComment[] {
|
|
74
|
+
const staleComments: ExistingComment[] = [];
|
|
75
|
+
|
|
76
|
+
for (const comment of existingComments) {
|
|
77
|
+
// Skip comments that don't have thread IDs (can't resolve them)
|
|
78
|
+
if (!comment.threadId) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Skip already-resolved comments (nothing to do)
|
|
83
|
+
if (comment.isResolved) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Comments on files NOT in scope are orphaned (file renamed, reverted, etc.)
|
|
88
|
+
if (!isInAnalyzedScope(comment, scope)) {
|
|
89
|
+
staleComments.push(comment);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Check if any finding matches this comment
|
|
94
|
+
const hasMatchingFinding = allFindings.some((finding) =>
|
|
95
|
+
findingMatchesComment(finding, comment)
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// If no matching finding, this comment is stale
|
|
99
|
+
if (!hasMatchingFinding) {
|
|
100
|
+
staleComments.push(comment);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return staleComments;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const RESOLVE_THREAD_MUTATION = `
|
|
108
|
+
mutation($threadId: ID!) {
|
|
109
|
+
resolveReviewThread(input: { threadId: $threadId }) {
|
|
110
|
+
thread {
|
|
111
|
+
id
|
|
112
|
+
isResolved
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
`;
|
|
117
|
+
|
|
118
|
+
/** Maximum stale comments to resolve per run (matches default maxFindings) */
|
|
119
|
+
const MAX_STALE_RESOLUTIONS = 50;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Resolve stale comment threads via GraphQL.
|
|
123
|
+
* Returns the number of threads successfully resolved.
|
|
124
|
+
* Limited to MAX_STALE_RESOLUTIONS per run as a safeguard.
|
|
125
|
+
*/
|
|
126
|
+
export async function resolveStaleComments(
|
|
127
|
+
octokit: Octokit,
|
|
128
|
+
staleComments: ExistingComment[]
|
|
129
|
+
): Promise<number> {
|
|
130
|
+
let resolvedCount = 0;
|
|
131
|
+
|
|
132
|
+
const commentsToResolve = staleComments.slice(0, MAX_STALE_RESOLUTIONS);
|
|
133
|
+
if (staleComments.length > MAX_STALE_RESOLUTIONS) {
|
|
134
|
+
console.log(
|
|
135
|
+
`Limiting stale comment resolution to ${MAX_STALE_RESOLUTIONS} of ${staleComments.length} comments`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
for (const comment of commentsToResolve) {
|
|
140
|
+
if (!comment.threadId) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
await octokit.graphql(RESOLVE_THREAD_MUTATION, {
|
|
146
|
+
threadId: comment.threadId,
|
|
147
|
+
});
|
|
148
|
+
resolvedCount++;
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.warn(`Failed to resolve thread for comment ${comment.id}: ${error}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return resolvedCount;
|
|
155
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SeverityThreshold } from '../types/index.js';
|
|
2
|
+
|
|
3
|
+
export interface GitHubComment {
|
|
4
|
+
body: string;
|
|
5
|
+
path?: string;
|
|
6
|
+
line?: number;
|
|
7
|
+
side?: 'LEFT' | 'RIGHT';
|
|
8
|
+
start_line?: number;
|
|
9
|
+
start_side?: 'LEFT' | 'RIGHT';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface GitHubReview {
|
|
13
|
+
event: 'APPROVE' | 'REQUEST_CHANGES' | 'COMMENT';
|
|
14
|
+
body: string;
|
|
15
|
+
comments: GitHubComment[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RenderResult {
|
|
19
|
+
review?: GitHubReview;
|
|
20
|
+
summaryComment: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface RenderOptions {
|
|
24
|
+
includeSuggestions?: boolean;
|
|
25
|
+
maxFindings?: number;
|
|
26
|
+
groupByFile?: boolean;
|
|
27
|
+
extraLabels?: string[];
|
|
28
|
+
/** Only include findings at or above this severity level in rendered output. Use 'off' to disable comments. */
|
|
29
|
+
commentOn?: SeverityThreshold;
|
|
30
|
+
/** URL to the GitHub Check run containing the full report (used when findings are filtered) */
|
|
31
|
+
checkRunUrl?: string;
|
|
32
|
+
/** Total number of findings before filtering (used to show "X more findings" link) */
|
|
33
|
+
totalFindings?: number;
|
|
34
|
+
}
|
package/src/sdk/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './runner.js';
|