ndrstnd 0.1.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 +201 -0
- package/README.md +56 -0
- package/dist/server/agent.d.ts +51 -0
- package/dist/server/agent.js +77 -0
- package/dist/server/agent.js.map +1 -0
- package/dist/server/analysis-core.d.ts +93 -0
- package/dist/server/analysis-core.js +442 -0
- package/dist/server/analysis-core.js.map +1 -0
- package/dist/server/analyze.d.ts +55 -0
- package/dist/server/analyze.js +72 -0
- package/dist/server/analyze.js.map +1 -0
- package/dist/server/artifact.d.ts +8 -0
- package/dist/server/artifact.js +43 -0
- package/dist/server/artifact.js.map +1 -0
- package/dist/server/claude.d.ts +29 -0
- package/dist/server/claude.js +243 -0
- package/dist/server/claude.js.map +1 -0
- package/dist/server/cli-support.d.ts +7 -0
- package/dist/server/cli-support.js +13 -0
- package/dist/server/cli-support.js.map +1 -0
- package/dist/server/cli.d.ts +2 -0
- package/dist/server/cli.js +276 -0
- package/dist/server/cli.js.map +1 -0
- package/dist/server/codex.d.ts +34 -0
- package/dist/server/codex.js +256 -0
- package/dist/server/codex.js.map +1 -0
- package/dist/server/conversation.d.ts +9 -0
- package/dist/server/conversation.js +57 -0
- package/dist/server/conversation.js.map +1 -0
- package/dist/server/evidence-ordering.d.ts +13 -0
- package/dist/server/evidence-ordering.js +143 -0
- package/dist/server/evidence-ordering.js.map +1 -0
- package/dist/server/git-model.d.ts +15 -0
- package/dist/server/git-model.js +156 -0
- package/dist/server/git-model.js.map +1 -0
- package/dist/server/git.d.ts +29 -0
- package/dist/server/git.js +124 -0
- package/dist/server/git.js.map +1 -0
- package/dist/server/http.d.ts +14 -0
- package/dist/server/http.js +139 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/preview-fixture.d.ts +1 -0
- package/dist/server/preview-fixture.js +23 -0
- package/dist/server/preview-fixture.js.map +1 -0
- package/dist/server/review-presentation.d.ts +3 -0
- package/dist/server/review-presentation.js +14 -0
- package/dist/server/review-presentation.js.map +1 -0
- package/dist/server/skill.d.ts +14 -0
- package/dist/server/skill.js +94 -0
- package/dist/server/skill.js.map +1 -0
- package/dist/server/store.d.ts +36 -0
- package/dist/server/store.js +134 -0
- package/dist/server/store.js.map +1 -0
- package/dist/server/version.d.ts +2 -0
- package/dist/server/version.js +13 -0
- package/dist/server/version.js.map +1 -0
- package/dist/shared/analysis-schema.d.ts +325 -0
- package/dist/shared/analysis-schema.js +50 -0
- package/dist/shared/analysis-schema.js.map +1 -0
- package/dist/shared/domain.d.ts +33 -0
- package/dist/shared/domain.js +2 -0
- package/dist/shared/domain.js.map +1 -0
- package/dist/web/evidence-model.d.ts +36 -0
- package/dist/web/evidence-model.js +134 -0
- package/dist/web/evidence-model.js.map +1 -0
- package/dist/web/frozen-review-data.d.ts +3 -0
- package/dist/web/frozen-review-data.js +202 -0
- package/dist/web/frozen-review-data.js.map +1 -0
- package/dist/web/language.d.ts +4 -0
- package/dist/web/language.js +14 -0
- package/dist/web/language.js.map +1 -0
- package/dist/web/page.d.ts +10 -0
- package/dist/web/page.js +1038 -0
- package/dist/web/page.js.map +1 -0
- package/dist/web/review-data.d.ts +20 -0
- package/dist/web/review-data.js +2 -0
- package/dist/web/review-data.js.map +1 -0
- package/dist/web/test-plan-model.d.ts +27 -0
- package/dist/web/test-plan-model.js +89 -0
- package/dist/web/test-plan-model.js.map +1 -0
- package/package.json +47 -0
- package/src/skill-assets/ndrstnd/SKILL.md +22 -0
- package/src/skill-assets/ndrstnd/agents/openai.yaml +4 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const RiskCategorySchema = z.enum(["formatting", "refactor", "behavior", "performance", "security"]);
|
|
3
|
+
export const AttentionSchema = z.enum(["low", "contained", "elevated", "high", "critical"]);
|
|
4
|
+
export const ChapterSchema = z.object({
|
|
5
|
+
id: z.string().min(1).max(80),
|
|
6
|
+
title: z.string().min(1).max(120),
|
|
7
|
+
kind: z.enum(["feature", "decision", "behavior", "non_functional", "risk", "test", "other"]),
|
|
8
|
+
synopsis: z.string().min(1).max(420),
|
|
9
|
+
before: z.string().max(300).optional(),
|
|
10
|
+
after: z.string().max(300).optional(),
|
|
11
|
+
confidence: z.enum(["high", "medium", "low"]),
|
|
12
|
+
attention: AttentionSchema,
|
|
13
|
+
riskCategories: z.array(RiskCategorySchema),
|
|
14
|
+
evidenceIds: z.array(z.string().min(1)).min(1),
|
|
15
|
+
});
|
|
16
|
+
export const AnalysisStepSchema = z.object({
|
|
17
|
+
id: z.string().min(1).max(80),
|
|
18
|
+
title: z.string().min(1).max(120),
|
|
19
|
+
goal: z.string().min(1).max(320),
|
|
20
|
+
youNowHave: z.string().min(1).max(320),
|
|
21
|
+
deferred: z.array(z.object({
|
|
22
|
+
concern: z.string().min(1).max(220),
|
|
23
|
+
resolvedByStepId: z.string().min(1).max(80).optional(),
|
|
24
|
+
})),
|
|
25
|
+
dependsOn: z.array(z.string().min(1).max(80)),
|
|
26
|
+
forwardRefs: z.record(z.string().min(1), z.string().min(1).max(80)),
|
|
27
|
+
advancesChapterIds: z.array(z.string().min(1).max(80)).min(1),
|
|
28
|
+
evidenceIds: z.array(z.string().min(1)).min(1),
|
|
29
|
+
});
|
|
30
|
+
export const FocusRangeSchema = z.object({ start: z.number().int().min(1), end: z.number().int().min(1) });
|
|
31
|
+
export const TestExecutionSchema = z.object({
|
|
32
|
+
command: z.string().min(1).max(200),
|
|
33
|
+
outcome: z.enum(["passed", "failed", "mixed", "unknown"]),
|
|
34
|
+
summary: z.string().min(1).max(300),
|
|
35
|
+
source: z.enum(["conversation", "repository"]),
|
|
36
|
+
});
|
|
37
|
+
export const AnalysisDocumentSchema = z.object({
|
|
38
|
+
summary: z.string().min(1).max(560),
|
|
39
|
+
chapters: z.array(ChapterSchema),
|
|
40
|
+
steps: z.array(AnalysisStepSchema),
|
|
41
|
+
omittedGroups: z.array(z.object({ title: z.string().min(1).max(120), reason: z.string().min(1).max(220), evidenceIds: z.array(z.string().min(1)).min(1) })),
|
|
42
|
+
unclassifiedEvidenceIds: z.array(z.string().min(1)),
|
|
43
|
+
/** Reviewer-critical new-file line ranges per evidence ID; they drive the focused excerpts at the Evidence zoom. */
|
|
44
|
+
focus: z.record(z.string().min(1), z.array(FocusRangeSchema).min(1).max(5)).optional(),
|
|
45
|
+
/** Test or build runs actually observed in the conversation or repository; never inferred. */
|
|
46
|
+
testExecution: z.array(TestExecutionSchema).max(5).optional(),
|
|
47
|
+
});
|
|
48
|
+
/** Bump on any incompatible change to AnalysisDocument so cached revisions from older versions are re-analyzed instead of rendered broken. */
|
|
49
|
+
export const ANALYSIS_DOCUMENT_VERSION = 1;
|
|
50
|
+
//# sourceMappingURL=analysis-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysis-schema.js","sourceRoot":"","sources":["../../src/shared/analysis-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type RiskCategory = "formatting" | "refactor" | "behavior" | "performance" | "security";
|
|
2
|
+
export type Attention = "low" | "contained" | "elevated" | "high" | "critical";
|
|
3
|
+
export type ZoomLevel = 0 | 1 | 2 | 3 | 4;
|
|
4
|
+
export interface ReviewSession {
|
|
5
|
+
id: string;
|
|
6
|
+
repoPath: string;
|
|
7
|
+
targetRef: string;
|
|
8
|
+
mergeBase: string;
|
|
9
|
+
}
|
|
10
|
+
export type DiffLineKind = "context" | "addition" | "deletion";
|
|
11
|
+
export interface DiffLine {
|
|
12
|
+
kind: DiffLineKind;
|
|
13
|
+
content: string;
|
|
14
|
+
oldLine?: number;
|
|
15
|
+
newLine?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface DiffHunk {
|
|
18
|
+
id: string;
|
|
19
|
+
fileId: string;
|
|
20
|
+
oldStart: number;
|
|
21
|
+
newStart: number;
|
|
22
|
+
lines: DiffLine[];
|
|
23
|
+
}
|
|
24
|
+
export type FileSignal = "meaningful" | "low-signal";
|
|
25
|
+
export interface ChangedFile {
|
|
26
|
+
id: string;
|
|
27
|
+
path: string;
|
|
28
|
+
previousPath?: string;
|
|
29
|
+
status: "added" | "modified" | "deleted" | "renamed" | "copied" | "unknown";
|
|
30
|
+
binary: boolean;
|
|
31
|
+
signal: FileSignal;
|
|
32
|
+
signalReason?: string;
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain.js","sourceRoot":"","sources":["../../src/shared/domain.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { AnalysisDocument } from "../shared/analysis-schema.js";
|
|
2
|
+
import type { ChangedFile, DiffHunk, DiffLine } from "../shared/domain.js";
|
|
3
|
+
export interface ChapterMetrics {
|
|
4
|
+
additions: number;
|
|
5
|
+
deletions: number;
|
|
6
|
+
files: number;
|
|
7
|
+
hunks: number;
|
|
8
|
+
addShare: number;
|
|
9
|
+
deleteShare: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function chapterMetrics(chapter: AnalysisDocument["chapters"][number], hunks: DiffHunk[]): ChapterMetrics;
|
|
12
|
+
/**
|
|
13
|
+
* Selects the lines the analysis marked as reviewer-critical for one hunk.
|
|
14
|
+
* Deletion runs adjacent to a selected line stay visible so replaced code
|
|
15
|
+
* keeps its before-image. Returns undefined when the ranges select nothing,
|
|
16
|
+
* so callers can fall back to the heuristic selection.
|
|
17
|
+
*/
|
|
18
|
+
export declare function focusLinesFromRanges(lines: DiffLine[], ranges: Array<{
|
|
19
|
+
start: number;
|
|
20
|
+
end: number;
|
|
21
|
+
}> | undefined): Array<{
|
|
22
|
+
line: DiffLine;
|
|
23
|
+
index: number;
|
|
24
|
+
}> | undefined;
|
|
25
|
+
export declare function focusedEvidenceLines(lines: DiffLine[]): Array<{
|
|
26
|
+
line: DiffLine;
|
|
27
|
+
index: number;
|
|
28
|
+
}>;
|
|
29
|
+
export declare function evidenceLineScore(line: DiffLine): number;
|
|
30
|
+
export declare function isRoutineLine(source: string): boolean;
|
|
31
|
+
export declare function isSupportingFile(file: ChangedFile | undefined): boolean;
|
|
32
|
+
export declare function toUnifiedDiff(file: ChangedFile, hunks: DiffHunk[]): string;
|
|
33
|
+
export declare function linePrefix(kind: DiffLine["kind"]): string;
|
|
34
|
+
export declare function attentionCounts(document: AnalysisDocument): Record<string, number>;
|
|
35
|
+
export declare function categoryCounts(document: AnalysisDocument): Record<string, number>;
|
|
36
|
+
export declare function basename(path: string): string;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
export function chapterMetrics(chapter, hunks) {
|
|
2
|
+
const seen = new Set();
|
|
3
|
+
const chapterHunks = chapter.evidenceIds.flatMap((id) => {
|
|
4
|
+
if (seen.has(id))
|
|
5
|
+
return [];
|
|
6
|
+
seen.add(id);
|
|
7
|
+
const hunk = hunks.find((candidate) => candidate.id === id);
|
|
8
|
+
return hunk === undefined ? [] : [hunk];
|
|
9
|
+
});
|
|
10
|
+
const additions = chapterHunks.flatMap((hunk) => hunk.lines).filter((line) => line.kind === "addition").length;
|
|
11
|
+
const deletions = chapterHunks.flatMap((hunk) => hunk.lines).filter((line) => line.kind === "deletion").length;
|
|
12
|
+
const total = additions + deletions;
|
|
13
|
+
const addShare = total === 0 ? 0 : Math.round((additions / total) * 100);
|
|
14
|
+
return { additions, deletions, files: new Set(chapterHunks.map((hunk) => hunk.fileId)).size, hunks: chapterHunks.length, addShare, deleteShare: total === 0 ? 0 : 100 - addShare };
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Selects the lines the analysis marked as reviewer-critical for one hunk.
|
|
18
|
+
* Deletion runs adjacent to a selected line stay visible so replaced code
|
|
19
|
+
* keeps its before-image. Returns undefined when the ranges select nothing,
|
|
20
|
+
* so callers can fall back to the heuristic selection.
|
|
21
|
+
*/
|
|
22
|
+
export function focusLinesFromRanges(lines, ranges) {
|
|
23
|
+
if (ranges === undefined || ranges.length === 0)
|
|
24
|
+
return undefined;
|
|
25
|
+
const selected = new Set();
|
|
26
|
+
lines.forEach((line, index) => {
|
|
27
|
+
if (line.newLine !== undefined && ranges.some((range) => line.newLine >= range.start && line.newLine <= range.end))
|
|
28
|
+
selected.add(index);
|
|
29
|
+
});
|
|
30
|
+
if (selected.size === 0)
|
|
31
|
+
return undefined;
|
|
32
|
+
let grew = true;
|
|
33
|
+
while (grew) {
|
|
34
|
+
grew = false;
|
|
35
|
+
lines.forEach((line, index) => {
|
|
36
|
+
if (line.kind === "deletion" && !selected.has(index) && (selected.has(index - 1) || selected.has(index + 1))) {
|
|
37
|
+
selected.add(index);
|
|
38
|
+
grew = true;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return [...selected].sort((left, right) => left - right).map((index) => ({ line: lines[index], index }));
|
|
43
|
+
}
|
|
44
|
+
export function focusedEvidenceLines(lines) {
|
|
45
|
+
let changed = lines
|
|
46
|
+
.map((line, index) => ({ line, index, score: evidenceLineScore(line) }))
|
|
47
|
+
.filter(({ line, score }) => line.kind !== "context" && score > 1)
|
|
48
|
+
.sort((left, right) => right.score - left.score || left.index - right.index)
|
|
49
|
+
.slice(0, 10)
|
|
50
|
+
.sort((left, right) => left.index - right.index);
|
|
51
|
+
// A hunk whose changed lines are all routine or import churn still deserves
|
|
52
|
+
// a focused excerpt; fall back to its first changed lines rather than nothing.
|
|
53
|
+
if (changed.length === 0)
|
|
54
|
+
changed = lines.map((line, index) => ({ line, index, score: 1 })).filter(({ line }) => line.kind !== "context").slice(0, 6);
|
|
55
|
+
if (changed.length === 0)
|
|
56
|
+
return [];
|
|
57
|
+
const selected = new Set(changed.map(({ index }) => index));
|
|
58
|
+
for (const { index } of changed) {
|
|
59
|
+
for (const neighbour of [index - 1, index + 1]) {
|
|
60
|
+
const line = lines[neighbour];
|
|
61
|
+
if (line?.kind === "context" && !isRoutineLine(line.content))
|
|
62
|
+
selected.add(neighbour);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return [...selected].sort((left, right) => left - right).map((index) => ({ line: lines[index], index }));
|
|
66
|
+
}
|
|
67
|
+
/** Definition-introducing words across mainstream languages (TS/JS, Python, Go, Rust, Ruby, Swift, Kotlin, Java, C#, Elixir, PHP...). */
|
|
68
|
+
const DEFINITION_WORDS = new Set(["function", "func", "fn", "fun", "def", "defp", "defmodule", "defmacro", "sub", "proc", "class", "struct", "enum", "union", "interface", "trait", "impl", "protocol", "extension", "module", "record", "typedef", "macro", "constructor", "init", "lambda"]);
|
|
69
|
+
/** Control-flow and effect words that usually carry the behavioral meaning of a change. */
|
|
70
|
+
const FLOW_WORDS = new Set(["return", "throw", "throws", "raise", "panic", "yield", "await", "defer", "break", "continue", "if", "elif", "elsif", "unless", "switch", "case", "match", "when", "guard", "for", "foreach", "while", "loop", "try", "catch", "except", "finally", "rescue", "ensure", "assert", "expect"]);
|
|
71
|
+
const IMPORT_LINE = /^(?:import\s|from\s+\S+\s+import\s|require\s*\(|require\s+['"]|include\s|#include\b|#import\b|using\s|use\s|package\s|namespace\s|extern\s+crate\s)/;
|
|
72
|
+
const COMMENT_LINE = /^(?:\/\/|\/\*|\*(?:\s|\/|$)|#(?!include|import|define|if|ifdef|ifndef|else|elif|endif|pragma|!)|--(?:\s|$)|;;)/;
|
|
73
|
+
const BLOCK_CLOSE = /^(?:end|fi|esac|done|endif|endfor|endwhile|endfunction|endmodule|endclass)[.;,]?$/i;
|
|
74
|
+
export function evidenceLineScore(line) {
|
|
75
|
+
if (line.kind === "context" || isRoutineLine(line.content))
|
|
76
|
+
return 0;
|
|
77
|
+
const source = line.content.trim();
|
|
78
|
+
if (IMPORT_LINE.test(source))
|
|
79
|
+
return 1;
|
|
80
|
+
const words = source.toLowerCase().match(/[a-z_$][\w$]*/g) ?? [];
|
|
81
|
+
if (COMMENT_LINE.test(source))
|
|
82
|
+
return /\b(?:TODO|FIXME|HACK|NOTE|WARNING|BUG|XXX)\b/.test(source) ? 4 : 2;
|
|
83
|
+
let score = 10;
|
|
84
|
+
if (words.some((word) => DEFINITION_WORDS.has(word)))
|
|
85
|
+
score += 8;
|
|
86
|
+
if (words.some((word) => FLOW_WORDS.has(word)))
|
|
87
|
+
score += 6;
|
|
88
|
+
if (/=>|->|:=|[A-Za-z_$][\w$]*\s*\(|[=!<>]=/.test(source))
|
|
89
|
+
score += 4;
|
|
90
|
+
return score + Math.min(3, Math.floor(words.length / 5));
|
|
91
|
+
}
|
|
92
|
+
export function isRoutineLine(source) {
|
|
93
|
+
const line = source.trim();
|
|
94
|
+
return line.length === 0
|
|
95
|
+
|| /^[{}[\]()`;,]+;?$/.test(line)
|
|
96
|
+
|| BLOCK_CLOSE.test(line)
|
|
97
|
+
|| /^(?:else|then|do|try|finally|begin)\s*[{:]?$/i.test(line)
|
|
98
|
+
|| /^['"`]{3}$/.test(line)
|
|
99
|
+
|| /^(?:get|set)\s+[A-Za-z_$][\w$]*\s*\(/.test(line)
|
|
100
|
+
|| /^(?:[A-Za-z_$][\w$]*\s+){0,3}[A-Za-z_$][\w$.]*[!?]?\s*(?::\s*[\w<>[\], .?|]+)?\s*:?=\s*(?:false|true|null|nil|none|undefined|0|0\.0|""|''|\[\]|\{\}|\(\))\s*[;,]?$/i.test(line);
|
|
101
|
+
}
|
|
102
|
+
export function isSupportingFile(file) {
|
|
103
|
+
return file?.signal === "low-signal" || /(?:^|\/)(?:\.gitignore|license(?:\.[^/]+)?|readme(?:\.[^/]+)?)$/i.test(file?.path ?? "");
|
|
104
|
+
}
|
|
105
|
+
export function toUnifiedDiff(file, hunks) {
|
|
106
|
+
const path = file.path.replace(/\\/g, "/");
|
|
107
|
+
const header = [`diff --git a/${path} b/${path}`, `--- a/${path}`, `+++ b/${path}`];
|
|
108
|
+
const blocks = hunks.map((hunk) => {
|
|
109
|
+
const oldCount = hunk.lines.filter((line) => line.kind !== "addition").length;
|
|
110
|
+
const newCount = hunk.lines.filter((line) => line.kind !== "deletion").length;
|
|
111
|
+
return [`@@ -${hunk.oldStart},${oldCount} +${hunk.newStart},${newCount} @@`, ...hunk.lines.map((line) => `${linePrefix(line.kind)}${line.content}`)].join("\n");
|
|
112
|
+
});
|
|
113
|
+
return [...header, ...blocks].join("\n");
|
|
114
|
+
}
|
|
115
|
+
export function linePrefix(kind) {
|
|
116
|
+
return kind === "addition" ? "+" : kind === "deletion" ? "-" : " ";
|
|
117
|
+
}
|
|
118
|
+
export function attentionCounts(document) {
|
|
119
|
+
const counts = { low: 0, contained: 0, elevated: 0, high: 0, critical: 0 };
|
|
120
|
+
for (const chapter of document.chapters)
|
|
121
|
+
counts[chapter.attention] += 1;
|
|
122
|
+
return counts;
|
|
123
|
+
}
|
|
124
|
+
export function categoryCounts(document) {
|
|
125
|
+
const counts = {};
|
|
126
|
+
for (const chapter of document.chapters)
|
|
127
|
+
for (const category of chapter.riskCategories)
|
|
128
|
+
counts[category] = (counts[category] ?? 0) + 1;
|
|
129
|
+
return counts;
|
|
130
|
+
}
|
|
131
|
+
export function basename(path) {
|
|
132
|
+
return path.split("/").filter(Boolean).at(-1) ?? path;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=evidence-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-model.js","sourceRoot":"","sources":["../../src/web/evidence-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/** A stable, intentionally representative review for presentation and visual tests. */
|
|
2
|
+
export const frozenReviewData = {
|
|
3
|
+
sessionId: "frozen-session",
|
|
4
|
+
revisionId: "frozen-revision",
|
|
5
|
+
targetRef: "frozen-ui-change",
|
|
6
|
+
baseRef: "main",
|
|
7
|
+
mergeBase: "a1b2c3d4e5f6",
|
|
8
|
+
agentName: "Codex",
|
|
9
|
+
files: [
|
|
10
|
+
{ id: "runner", path: "src/runner.ts", status: "modified", binary: false, signal: "meaningful" },
|
|
11
|
+
{ id: "retry", path: "src/retry-policy.ts", status: "added", binary: false, signal: "meaningful" },
|
|
12
|
+
{ id: "telemetry", path: "src/telemetry.ts", status: "modified", binary: false, signal: "meaningful" },
|
|
13
|
+
{ id: "runner-test", path: "test/runner.test.ts", status: "modified", binary: false, signal: "meaningful" },
|
|
14
|
+
{ id: "changelog", path: "CHANGELOG.md", status: "modified", binary: false, signal: "low-signal", signalReason: "Release note restates the code change." },
|
|
15
|
+
{ id: "lockfile", path: "package-lock.json", status: "modified", binary: false, signal: "low-signal", signalReason: "Dependency lockfile churn." },
|
|
16
|
+
],
|
|
17
|
+
hunks: [
|
|
18
|
+
{
|
|
19
|
+
id: "runner-hunk", fileId: "runner", oldStart: 8, newStart: 8,
|
|
20
|
+
lines: [
|
|
21
|
+
{ kind: "context", content: "export class Runner {", oldLine: 8, newLine: 8 },
|
|
22
|
+
{ kind: "addition", content: " constructor(private readonly policy: RetryPolicy, private readonly telemetry: Telemetry) {}", newLine: 9 },
|
|
23
|
+
{ kind: "addition", content: "", newLine: 10 },
|
|
24
|
+
{ kind: "addition", content: " async run(job: Job): Promise<JobResult> {", newLine: 11 },
|
|
25
|
+
{ kind: "addition", content: " return this.policy.execute(() => this.execute(job), (attempt) => this.telemetry.recordRetry(job.id, attempt));", newLine: 12 },
|
|
26
|
+
{ kind: "addition", content: " }", newLine: 13 },
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "runner-guard-hunk", fileId: "runner", oldStart: 21, newStart: 26,
|
|
31
|
+
lines: [
|
|
32
|
+
{ kind: "context", content: " private async execute(job: Job): Promise<JobResult> {", oldLine: 21, newLine: 26 },
|
|
33
|
+
{ kind: "deletion", content: " return job.perform();", oldLine: 22 },
|
|
34
|
+
{ kind: "addition", content: " if (job.cancelled) throw new JobCancelledError(job.id);", newLine: 27 },
|
|
35
|
+
{ kind: "addition", content: " const result = await job.perform();", newLine: 28 },
|
|
36
|
+
{ kind: "addition", content: " return { ...result, jobId: job.id };", newLine: 29 },
|
|
37
|
+
{ kind: "context", content: " }", oldLine: 23, newLine: 30 },
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: "retry-hunk", fileId: "retry", oldStart: 0, newStart: 1,
|
|
42
|
+
lines: [
|
|
43
|
+
{ kind: "addition", content: "export class RetryPolicy {", newLine: 1 },
|
|
44
|
+
{ kind: "addition", content: " constructor(private readonly maxAttempts = 3, private readonly baseDelayMs = 250) {}", newLine: 2 },
|
|
45
|
+
{ kind: "addition", content: "", newLine: 3 },
|
|
46
|
+
{ kind: "addition", content: " async execute<T>(operation: () => Promise<T>, onRetry: (attempt: number) => void): Promise<T> {", newLine: 4 },
|
|
47
|
+
{ kind: "addition", content: " for (let attempt = 1; ; attempt += 1) {", newLine: 5 },
|
|
48
|
+
{ kind: "addition", content: " try { return await operation(); } catch (error) {", newLine: 6 },
|
|
49
|
+
{ kind: "addition", content: " if (attempt >= this.maxAttempts || !isTransient(error)) throw error;", newLine: 7 },
|
|
50
|
+
{ kind: "addition", content: " onRetry(attempt);", newLine: 8 },
|
|
51
|
+
{ kind: "addition", content: " await delay(this.baseDelayMs * 2 ** (attempt - 1));", newLine: 9 },
|
|
52
|
+
{ kind: "addition", content: " }", newLine: 10 },
|
|
53
|
+
{ kind: "addition", content: " }", newLine: 11 },
|
|
54
|
+
{ kind: "addition", content: " }", newLine: 12 },
|
|
55
|
+
{ kind: "addition", content: "}", newLine: 13 },
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "telemetry-hunk", fileId: "telemetry", oldStart: 14, newStart: 14,
|
|
60
|
+
lines: [
|
|
61
|
+
{ kind: "context", content: "export class Telemetry {", oldLine: 14, newLine: 14 },
|
|
62
|
+
{ kind: "addition", content: " recordRetry(jobId: string, attempt: number): void {", newLine: 15 },
|
|
63
|
+
{ kind: "addition", content: " this.counter('runner.retry', { jobId, attempt }).increment();", newLine: 16 },
|
|
64
|
+
{ kind: "addition", content: " }", newLine: 17 },
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: "runner-test-hunk", fileId: "runner-test", oldStart: 12, newStart: 12,
|
|
69
|
+
lines: [
|
|
70
|
+
{ kind: "addition", content: "it('runs a job', async () => {", newLine: 12 },
|
|
71
|
+
{ kind: "addition", content: " await expect(runner.run(job)).resolves.toEqual(result);", newLine: 13 },
|
|
72
|
+
{ kind: "addition", content: "});", newLine: 14 },
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "runner-retry-test-hunk", fileId: "runner-test", oldStart: 16, newStart: 16,
|
|
77
|
+
lines: [
|
|
78
|
+
{ kind: "addition", content: "it('retries a transient failure with backoff before succeeding', async () => {", newLine: 16 },
|
|
79
|
+
{ kind: "addition", content: " job.failOnce(new TransientNetworkError());", newLine: 17 },
|
|
80
|
+
{ kind: "addition", content: " await expect(runner.run(job)).resolves.toEqual(result);", newLine: 18 },
|
|
81
|
+
{ kind: "addition", content: " expect(telemetry.retries('runner.retry')).toEqual([{ jobId: job.id, attempt: 1 }]);", newLine: 19 },
|
|
82
|
+
{ kind: "addition", content: "});", newLine: 20 },
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "changelog-hunk", fileId: "changelog", oldStart: 3, newStart: 3,
|
|
87
|
+
lines: [
|
|
88
|
+
{ kind: "addition", content: "- The runner retries transient job failures with exponential backoff.", newLine: 3 },
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "lockfile-hunk", fileId: "lockfile", oldStart: 1201, newStart: 1201,
|
|
93
|
+
lines: [
|
|
94
|
+
{ kind: "deletion", content: " \"version\": \"2.4.0\",", oldLine: 1201 },
|
|
95
|
+
{ kind: "addition", content: " \"version\": \"2.4.1\",", newLine: 1201 },
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
document: {
|
|
100
|
+
summary: "The runner now executes a supplied job through a single entry point, retries transient failures with exponential backoff, and reports each retry to telemetry. The behavior is covered by focused tests for the success path and the retry path.",
|
|
101
|
+
chapters: [
|
|
102
|
+
{
|
|
103
|
+
id: "run-job", title: "Run the supplied job", kind: "behavior",
|
|
104
|
+
synopsis: "The runner delegates the job to its execution path, guards against cancelled jobs, and stamps results with the job id.",
|
|
105
|
+
before: "Jobs could not be run through this entry point, and cancelled jobs were executed anyway.",
|
|
106
|
+
after: "Callers run a job through one entry point and receive a result stamped with the job id; cancelled jobs fail fast.",
|
|
107
|
+
confidence: "high", attention: "contained", riskCategories: ["behavior"], evidenceIds: ["runner-hunk", "runner-guard-hunk"],
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: "retry-policy", title: "Retry transient failures", kind: "decision",
|
|
111
|
+
synopsis: "A dedicated `RetryPolicy` retries transient errors up to three times with exponential backoff instead of failing the job on first error.",
|
|
112
|
+
before: "Any transient infrastructure error failed the job immediately.",
|
|
113
|
+
after: "Transient errors are retried up to three times with 250ms exponential backoff; permanent errors still fail fast.",
|
|
114
|
+
confidence: "medium", attention: "elevated", riskCategories: ["behavior", "performance"], evidenceIds: ["retry-hunk"],
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: "retry-telemetry", title: "Surface retry telemetry", kind: "non_functional",
|
|
118
|
+
synopsis: "Every retry increments a runner.retry counter tagged with the job id and attempt number so operators can watch retry pressure.",
|
|
119
|
+
before: "Retries would have been invisible to operators.",
|
|
120
|
+
after: "Each retry is counted per job and attempt, making retry storms observable.",
|
|
121
|
+
confidence: "high", attention: "low", riskCategories: ["performance"], evidenceIds: ["telemetry-hunk"],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: "test-job", title: "Cover job execution", kind: "test",
|
|
125
|
+
synopsis: "Focused tests verify the returned result on the success path and the backoff-then-succeed retry path, including the telemetry counter.",
|
|
126
|
+
confidence: "high", attention: "low", riskCategories: [], evidenceIds: ["runner-test-hunk", "runner-retry-test-hunk"],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
steps: [
|
|
130
|
+
{
|
|
131
|
+
id: "step-01",
|
|
132
|
+
title: "Run jobs through one entry point",
|
|
133
|
+
goal: "Introduce the runner entry point so every job flows through a single run(job) call. The entry point owns cancellation checks and result stamping, which gives the later retry and telemetry work one seam to attach to.",
|
|
134
|
+
youNowHave: "Callers can run a supplied job through `Runner.run` and receive a `JobResult` stamped with the job id. Cancelled jobs fail fast with `JobCancelledError` instead of executing.",
|
|
135
|
+
deferred: [
|
|
136
|
+
{ concern: "Transient failures still bubble up immediately; retry semantics arrive with the policy.", resolvedByStepId: "step-02" },
|
|
137
|
+
{ concern: "Retries are not yet observable to operators.", resolvedByStepId: "step-03" },
|
|
138
|
+
{ concern: "Neither the success path nor the guard has test coverage yet.", resolvedByStepId: "step-04" },
|
|
139
|
+
],
|
|
140
|
+
dependsOn: [],
|
|
141
|
+
forwardRefs: { RetryPolicy: "step-02", recordRetry: "step-03" },
|
|
142
|
+
advancesChapterIds: ["run-job"],
|
|
143
|
+
evidenceIds: ["runner-hunk", "runner-guard-hunk"],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: "step-02",
|
|
147
|
+
title: "Retry transient failures with backoff",
|
|
148
|
+
goal: "Add a RetryPolicy that wraps the execution seam from the previous step. It retries only errors classified as transient, caps attempts at three, and doubles a 250ms base delay per attempt so a stuck dependency is not hammered.",
|
|
149
|
+
youNowHave: "Runner.run survives transient infrastructure errors: up to three attempts with exponential backoff, while permanent errors and exhausted attempts still propagate to the caller unchanged.",
|
|
150
|
+
deferred: [
|
|
151
|
+
{ concern: "Each retry should increment an operator-facing counter.", resolvedByStepId: "step-03" },
|
|
152
|
+
{ concern: "The backoff-then-succeed path needs a regression test.", resolvedByStepId: "step-04" },
|
|
153
|
+
{ concern: "Making maxAttempts and the base delay configurable per job class is left for a follow-up branch." },
|
|
154
|
+
],
|
|
155
|
+
dependsOn: ["step-01"],
|
|
156
|
+
forwardRefs: {},
|
|
157
|
+
advancesChapterIds: ["retry-policy"],
|
|
158
|
+
evidenceIds: ["retry-hunk"],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: "step-03",
|
|
162
|
+
title: "Count retries in telemetry",
|
|
163
|
+
goal: "Close the observability gap opened by the retry policy: report every retry attempt through Telemetry.recordRetry so operators can distinguish healthy occasional retries from a retry storm.",
|
|
164
|
+
youNowHave: "Every retry increments the runner.retry counter tagged with job id and attempt number, satisfying the forward reference the runner entry point made to recordRetry.",
|
|
165
|
+
deferred: [
|
|
166
|
+
{ concern: "An alerting threshold on runner.retry is intentionally left to the operations repository." },
|
|
167
|
+
],
|
|
168
|
+
dependsOn: ["step-01", "step-02"],
|
|
169
|
+
forwardRefs: {},
|
|
170
|
+
advancesChapterIds: ["retry-telemetry"],
|
|
171
|
+
evidenceIds: ["telemetry-hunk"],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: "step-04",
|
|
175
|
+
title: "Cover execution and retry behavior",
|
|
176
|
+
goal: "Lock in the observable behavior of the previous three steps with focused tests: the plain success path returns the stamped result, and a transient failure is retried with backoff until it succeeds while the retry counter records the attempt.",
|
|
177
|
+
youNowHave: "Both the success path and the retry path have regression coverage, including the telemetry side effect, so future changes to the policy or the runner seam cannot silently change job semantics.",
|
|
178
|
+
deferred: [],
|
|
179
|
+
dependsOn: ["step-01", "step-02", "step-03"],
|
|
180
|
+
forwardRefs: {},
|
|
181
|
+
advancesChapterIds: ["test-job"],
|
|
182
|
+
evidenceIds: ["runner-test-hunk", "runner-retry-test-hunk"],
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
omittedGroups: [
|
|
186
|
+
{ title: "Release bookkeeping", reason: "The changelog entry and lockfile bump restate the change without adding review signal.", evidenceIds: ["changelog-hunk", "lockfile-hunk"] },
|
|
187
|
+
],
|
|
188
|
+
unclassifiedEvidenceIds: [],
|
|
189
|
+
testExecution: [
|
|
190
|
+
{ command: "npm test", outcome: "passed", summary: "Runner suite passed; the new run and retry tests cover both execution paths.", source: "conversation" },
|
|
191
|
+
],
|
|
192
|
+
focus: {
|
|
193
|
+
"runner-hunk": [{ start: 11, end: 13 }],
|
|
194
|
+
"runner-guard-hunk": [{ start: 27, end: 29 }],
|
|
195
|
+
"retry-hunk": [{ start: 5, end: 9 }],
|
|
196
|
+
"telemetry-hunk": [{ start: 15, end: 17 }],
|
|
197
|
+
"runner-test-hunk": [{ start: 12, end: 14 }],
|
|
198
|
+
"runner-retry-test-hunk": [{ start: 17, end: 19 }],
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
//# sourceMappingURL=frozen-review-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frozen-review-data.js","sourceRoot":"","sources":["../../src/web/frozen-review-data.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ChangedFile } from "../shared/domain.js";
|
|
2
|
+
import { type BundledLanguage, type Highlighter } from "shiki";
|
|
3
|
+
export declare function resolveLanguage(path: string): BundledLanguage;
|
|
4
|
+
export declare function syntaxHighlighter(files: ChangedFile[]): Promise<Highlighter>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getSingletonHighlighter } from "shiki";
|
|
2
|
+
export function resolveLanguage(path) {
|
|
3
|
+
const byExtension = {
|
|
4
|
+
ts: "typescript", tsx: "tsx", js: "javascript", jsx: "jsx", json: "json", css: "css", html: "html", htm: "html", md: "markdown", mdx: "mdx", yml: "yaml", yaml: "yaml", swift: "swift", py: "python", rb: "ruby", go: "go", rs: "rust", java: "java", kt: "kotlin", kts: "kotlin", c: "c", h: "c", cpp: "cpp", hpp: "cpp", cs: "csharp", sh: "shellscript", zsh: "shellscript", bash: "shellscript", sql: "sql", xml: "xml", vue: "vue", svelte: "svelte",
|
|
5
|
+
};
|
|
6
|
+
const extension = path.toLowerCase().split(".").at(-1) ?? "";
|
|
7
|
+
return byExtension[extension] ?? "text";
|
|
8
|
+
}
|
|
9
|
+
export async function syntaxHighlighter(files) {
|
|
10
|
+
const highlighter = await getSingletonHighlighter({ themes: ["github-light", "github-dark"], langs: [] });
|
|
11
|
+
await Promise.all([...new Set(files.map((file) => resolveLanguage(file.path)))].map((language) => highlighter.loadLanguage(language)));
|
|
12
|
+
return highlighter;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=language.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.js","sourceRoot":"","sources":["../../src/web/language.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAA0C,MAAM,OAAO,CAAC;AAExF,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,WAAW,GAAoC;QACnD,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ;KAC1b,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7D,OAAO,WAAW,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAoB;IAC1D,MAAM,WAAW,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC,cAAc,EAAE,aAAa,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1G,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvI,OAAO,WAAW,CAAC;AACrB,CAAC"}
|