@newrelic/preflight 1.49.0 → 1.50.1
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/dist/dashboard/routes/api-handler.d.ts +14 -0
- package/dist/dashboard/routes/api-handler.d.ts.map +1 -1
- package/dist/dashboard/routes/api-handler.js +31 -32
- package/dist/dashboard/routes/api-handler.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/metrics/git-activity-recorder.d.ts +51 -0
- package/dist/metrics/git-activity-recorder.d.ts.map +1 -0
- package/dist/metrics/git-activity-recorder.js +178 -0
- package/dist/metrics/git-activity-recorder.js.map +1 -0
- package/dist/metrics/git-activity-store.d.ts +63 -0
- package/dist/metrics/git-activity-store.d.ts.map +1 -0
- package/dist/metrics/git-activity-store.js +115 -0
- package/dist/metrics/git-activity-store.js.map +1 -0
- package/dist/metrics/git-efficiency-tracker.d.ts +2 -15
- package/dist/metrics/git-efficiency-tracker.d.ts.map +1 -1
- package/dist/metrics/git-efficiency-tracker.js +12 -118
- package/dist/metrics/git-efficiency-tracker.js.map +1 -1
- package/dist/metrics/git-event-classifier.d.ts +36 -0
- package/dist/metrics/git-event-classifier.d.ts.map +1 -0
- package/dist/metrics/git-event-classifier.js +138 -0
- package/dist/metrics/git-event-classifier.js.map +1 -0
- package/dist/metrics/git-window-params.d.ts +22 -0
- package/dist/metrics/git-window-params.d.ts.map +1 -0
- package/dist/metrics/git-window-params.js +65 -0
- package/dist/metrics/git-window-params.js.map +1 -0
- package/dist/metrics/git-workspace-identity.d.ts +38 -0
- package/dist/metrics/git-workspace-identity.d.ts.map +1 -0
- package/dist/metrics/git-workspace-identity.js +136 -0
- package/dist/metrics/git-workspace-identity.js.map +1 -0
- package/dist/metrics/git-workspace-report.d.ts +114 -0
- package/dist/metrics/git-workspace-report.d.ts.map +1 -0
- package/dist/metrics/git-workspace-report.js +1187 -0
- package/dist/metrics/git-workspace-report.js.map +1 -0
- package/dist/metrics/git-workspace-reporter.d.ts +138 -0
- package/dist/metrics/git-workspace-reporter.d.ts.map +1 -0
- package/dist/metrics/git-workspace-reporter.js +326 -0
- package/dist/metrics/git-workspace-reporter.js.map +1 -0
- package/dist/metrics/local-session-aggregator.d.ts.map +1 -1
- package/dist/metrics/local-session-aggregator.js +1 -0
- package/dist/metrics/local-session-aggregator.js.map +1 -1
- package/dist/platforms/kiro-adapter.d.ts.map +1 -1
- package/dist/platforms/kiro-adapter.js +12 -3
- package/dist/platforms/kiro-adapter.js.map +1 -1
- package/dist/storage/session-store.d.ts.map +1 -1
- package/dist/storage/session-store.js +2 -0
- package/dist/storage/session-store.js.map +1 -1
- package/dist/storage/types.d.ts +1 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/tools/session-stats.d.ts +27 -0
- package/dist/tools/session-stats.d.ts.map +1 -1
- package/dist/tools/session-stats.js +29 -7
- package/dist/tools/session-stats.js.map +1 -1
- package/dist/web/assets/index-4h4AORA2.js +64 -0
- package/dist/web/assets/index-qULXLTB2.css +2 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/index-C14Y4BRS.js +0 -64
- package/dist/web/assets/index-CQvdP3BR.css +0 -2
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { basename, dirname } from 'node:path';
|
|
4
|
+
import { repoNameFromRemote } from './local-session-aggregator.js';
|
|
5
|
+
const GIT_OPTS = {
|
|
6
|
+
encoding: 'utf-8',
|
|
7
|
+
timeout: 2000,
|
|
8
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
9
|
+
get env() {
|
|
10
|
+
return { ...process.env, GIT_DIR: undefined, GIT_WORK_TREE: undefined };
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
export class WorktreeIdentityResolver {
|
|
14
|
+
cache = new Map();
|
|
15
|
+
branchTtlMs = 30_000;
|
|
16
|
+
resolve(dir) {
|
|
17
|
+
if (typeof dir !== 'string' || dir.length === 0)
|
|
18
|
+
return null;
|
|
19
|
+
const cached = this.cache.get(dir);
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
if (cached) {
|
|
22
|
+
if (now - cached.branchResolvedAt >= this.branchTtlMs) {
|
|
23
|
+
const refreshed = this.resolveBranch(dir);
|
|
24
|
+
// `refreshed.branch` is legitimately null for detached HEAD, which is
|
|
25
|
+
// a real state a worktree can transition into — `refreshed.ok`, not
|
|
26
|
+
// the branch value itself, is what distinguishes that from "the
|
|
27
|
+
// subprocess call failed, keep reporting the last known branch".
|
|
28
|
+
const updated = {
|
|
29
|
+
...cached.identity,
|
|
30
|
+
branch: refreshed.ok ? refreshed.branch : cached.identity.branch,
|
|
31
|
+
};
|
|
32
|
+
this.cache.set(dir, { identity: updated, branchResolvedAt: now });
|
|
33
|
+
return updated;
|
|
34
|
+
}
|
|
35
|
+
return cached.identity;
|
|
36
|
+
}
|
|
37
|
+
const identity = this.computeIdentity(dir);
|
|
38
|
+
if (identity) {
|
|
39
|
+
this.cache.set(dir, { identity, branchResolvedAt: now });
|
|
40
|
+
}
|
|
41
|
+
return identity;
|
|
42
|
+
}
|
|
43
|
+
computeIdentity(dir) {
|
|
44
|
+
let repoKey;
|
|
45
|
+
let worktreeKey;
|
|
46
|
+
// Deliberately a SEPARATE call from branch resolution, not combined into
|
|
47
|
+
// one `rev-parse`: --git-common-dir/--git-dir need no commit and no
|
|
48
|
+
// checked-out work tree, but --abbrev-ref HEAD fails with exit 128 on a
|
|
49
|
+
// freshly `git init`'d repo with zero commits yet (unborn HEAD) — the
|
|
50
|
+
// same class of landmine as --show-toplevel failing on a bare primary.
|
|
51
|
+
// Repo/worktree identity must not depend on a call that can fail for a
|
|
52
|
+
// reason that has nothing to do with identity.
|
|
53
|
+
try {
|
|
54
|
+
const result = spawnSync('git', ['-C', dir, 'rev-parse', '--path-format=absolute', '--git-common-dir', '--git-dir'], GIT_OPTS);
|
|
55
|
+
if (result.status !== 0 || typeof result.stdout !== 'string') {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const lines = result.stdout.trim().split('\n');
|
|
59
|
+
if (lines.length < 2 || !lines[0] || !lines[1]) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
repoKey = lines[0].trim();
|
|
63
|
+
worktreeKey = lines[1].trim();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
// Failure here (unborn HEAD, or any other reason) is a real, common
|
|
69
|
+
// state — not evidence that `dir` isn't a valid repo — so it degrades to
|
|
70
|
+
// `branch: null` rather than failing the whole identity resolution.
|
|
71
|
+
const branch = this.resolveBranch(dir).branch;
|
|
72
|
+
const worktreeRoot = this.deriveWorktreeRoot(dir, worktreeKey, repoKey);
|
|
73
|
+
const repoName = this.resolveRepoName(dir);
|
|
74
|
+
const worktreeLabel = this.deriveLabel(worktreeKey, repoKey, worktreeRoot);
|
|
75
|
+
return {
|
|
76
|
+
repoKey,
|
|
77
|
+
worktreeKey,
|
|
78
|
+
repoName,
|
|
79
|
+
worktreeRoot,
|
|
80
|
+
worktreeLabel,
|
|
81
|
+
branch,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
deriveWorktreeRoot(dir, worktreeKey, repoKey) {
|
|
85
|
+
if (worktreeKey === repoKey) {
|
|
86
|
+
return dirname(repoKey);
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const gitdirPath = `${worktreeKey}/gitdir`;
|
|
90
|
+
const content = readFileSync(gitdirPath, 'utf-8').trim();
|
|
91
|
+
if (content) {
|
|
92
|
+
return dirname(content);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* fall through to null */
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
deriveLabel(worktreeKey, repoKey, worktreeRoot) {
|
|
101
|
+
if (worktreeKey === repoKey) {
|
|
102
|
+
return 'primary';
|
|
103
|
+
}
|
|
104
|
+
return basename(worktreeRoot ?? worktreeKey);
|
|
105
|
+
}
|
|
106
|
+
resolveRepoName(dir) {
|
|
107
|
+
try {
|
|
108
|
+
const result = spawnSync('git', ['-C', dir, 'remote', 'get-url', 'origin'], GIT_OPTS);
|
|
109
|
+
if (result.status === 0 && typeof result.stdout === 'string') {
|
|
110
|
+
return repoNameFromRemote(result.stdout);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
/* fall through */
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
/** `ok: false` means the subprocess call itself failed (caller should keep
|
|
119
|
+
* the last known branch). `ok: true, branch: null` means the call
|
|
120
|
+
* succeeded and the worktree is genuinely in detached HEAD — a real state
|
|
121
|
+
* transition the caller must apply, not mask with the stale cached value. */
|
|
122
|
+
resolveBranch(dir) {
|
|
123
|
+
try {
|
|
124
|
+
const result = spawnSync('git', ['-C', dir, 'rev-parse', '--abbrev-ref', 'HEAD'], GIT_OPTS);
|
|
125
|
+
if (result.status === 0 && typeof result.stdout === 'string') {
|
|
126
|
+
const headRef = result.stdout.trim();
|
|
127
|
+
return { ok: true, branch: headRef === 'HEAD' ? null : headRef };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
/* fall through */
|
|
132
|
+
}
|
|
133
|
+
return { ok: false, branch: null };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=git-workspace-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-workspace-identity.js","sourceRoot":"","sources":["../../src/metrics/git-workspace-identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { GitActivityRecord } from './git-activity-recorder.js';
|
|
2
|
+
import type { GitEfficiencyMetrics } from './git-efficiency-tracker.js';
|
|
3
|
+
import type { WorktreeIdentity } from './git-workspace-identity.js';
|
|
4
|
+
/**
|
|
5
|
+
* A live sample of one workspace's own branch/divergence state, sampled
|
|
6
|
+
* separately from `GitActivityRecord` history (that sampling logic is a
|
|
7
|
+
* later phase — this is accepted as an external input here). `null` means
|
|
8
|
+
* no live sample has been taken yet for this workspace.
|
|
9
|
+
*/
|
|
10
|
+
export interface WorktreeLiveState {
|
|
11
|
+
readonly branch: string | null;
|
|
12
|
+
readonly defaultBranch: string | null;
|
|
13
|
+
readonly ahead: number | null;
|
|
14
|
+
readonly behind: number | null;
|
|
15
|
+
readonly measuredAtMs: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* `GitEfficiencyMetrics` minus `repoContext` (the caller already knows
|
|
19
|
+
* `identity`) and minus the `use_worktrees` best-practice entry (see
|
|
20
|
+
* `evaluateBestPractices` below — it doesn't belong at single-workspace
|
|
21
|
+
* scope), plus fields needed either to carry live branch-divergence state
|
|
22
|
+
* for this one workspace (`liveState`) or to let `rollupWorkspaceMetrics`
|
|
23
|
+
* recombine several already-computed `WorkspaceMetrics` without ever
|
|
24
|
+
* re-running the sequential state machine over merged raw records.
|
|
25
|
+
*/
|
|
26
|
+
export interface WorkspaceMetrics extends Omit<GitEfficiencyMetrics, 'repoContext'> {
|
|
27
|
+
readonly liveState: WorktreeLiveState | null;
|
|
28
|
+
/** This workspace's own commit timestamps — merges safely across
|
|
29
|
+
* workspaces at rollup (a commit is a commit), unlike the sequential
|
|
30
|
+
* counters above. */
|
|
31
|
+
readonly commitTimestamps: readonly number[];
|
|
32
|
+
/** This workspace's own most recent push timestamp, or null if it never
|
|
33
|
+
* pushed. Lets a rollup pick "whichever workspace pushed most recently"
|
|
34
|
+
* for its own buildBeforePush/testBeforePush without re-deriving it from
|
|
35
|
+
* merged events. */
|
|
36
|
+
readonly lastPushTimestamp: number | null;
|
|
37
|
+
/** Files edited in this workspace. Distinct from `riskIndicators.hotFiles`
|
|
38
|
+
* (conflicted AND re-edited within this one workspace) — this is the raw
|
|
39
|
+
* edited-file set, needed to detect the SAME file edited across two
|
|
40
|
+
* DIFFERENT workspaces (see `parallel_isolation` in
|
|
41
|
+
* `buildGitWorkspaceReport`), which `hotFiles` can't answer. */
|
|
42
|
+
readonly editedFiles: readonly string[];
|
|
43
|
+
/** Whether this workspace ever used a bare (non-lease) `--force` push.
|
|
44
|
+
* Kept distinct from `forcePushes` (which sums bare AND lease-protected
|
|
45
|
+
* pushes) and from `riskIndicators.usesForceWithLease`, so a rollup can
|
|
46
|
+
* tell "was ANY force-push here unsafe" without conflating it with "was
|
|
47
|
+
* --force-with-lease ever also used." */
|
|
48
|
+
readonly hasUsedBareForcePush: boolean;
|
|
49
|
+
readonly bareForcePushCount: number;
|
|
50
|
+
/** Whether a bare force-push ever landed while this workspace's own
|
|
51
|
+
* branch matched its own default branch (per the current `liveState`
|
|
52
|
+
* sample at the time of each push). */
|
|
53
|
+
readonly hasForcePushedToDefaultBranch: boolean;
|
|
54
|
+
/** Raw `merge`/`rebase` event counts (distinct from `mergeConflicts`/
|
|
55
|
+
* `rebaseConflicts`, which count only *conflicting* attempts) — needed to
|
|
56
|
+
* recompute the `prefer_rebase` best-practice check at rollup scope,
|
|
57
|
+
* since `gitCommandTimeline` is capped at 50 and can't be summed for
|
|
58
|
+
* this. */
|
|
59
|
+
readonly mergeEventCount: number;
|
|
60
|
+
readonly rebaseEventCount: number;
|
|
61
|
+
/** Latest `timestamp` across every record this workspace saw in the
|
|
62
|
+
* requested window — git, edit, verify, and PR records alike, unlike
|
|
63
|
+
* `lastPushTimestamp` which only tracks pushes. Null when the workspace
|
|
64
|
+
* had no records at all. Drives "most recently active" sort ordering; a
|
|
65
|
+
* max, so it merges safely at rollup the same way `commitTimestamps` does. */
|
|
66
|
+
readonly lastActivityMs: number | null;
|
|
67
|
+
/** Distinct Claude Code session ids that produced any record in this
|
|
68
|
+
* workspace within the requested window — 'unknown' for a record whose
|
|
69
|
+
* source ToolCallRecord had no sessionId. Lets the UI deep-link "view
|
|
70
|
+
* the exact sessions behind this repo/worktree" precisely, rather than
|
|
71
|
+
* approximating by repo name. Merges safely at rollup via a Set union
|
|
72
|
+
* (a session is a session), unlike the sequential counters above. */
|
|
73
|
+
readonly sessionIds: readonly string[];
|
|
74
|
+
}
|
|
75
|
+
export interface ScopeRef {
|
|
76
|
+
readonly kind: 'all' | 'repo' | 'worktree';
|
|
77
|
+
/** WorktreeIdentity.repoKey (kind 'repo') or .worktreeKey (kind 'worktree'). Absent for 'all'. */
|
|
78
|
+
readonly id?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface WorkspaceRow {
|
|
81
|
+
readonly identity: WorktreeIdentity;
|
|
82
|
+
readonly metrics: WorkspaceMetrics;
|
|
83
|
+
}
|
|
84
|
+
export interface GitWorkspaceReport {
|
|
85
|
+
readonly scope: ScopeRef;
|
|
86
|
+
/** Rollup metrics for the requested scope (all workspaces if scope.kind==='all',
|
|
87
|
+
* all worktrees of one repo if 'repo', or just that one workspace's own
|
|
88
|
+
* metrics — unrolled-up — if 'worktree'). */
|
|
89
|
+
readonly metrics: WorkspaceMetrics;
|
|
90
|
+
/** Every individual workspace with activity in this window, for the table —
|
|
91
|
+
* NOT filtered by scope; the UI filters/groups this client-side when
|
|
92
|
+
* drilling in, since it's cheap and avoids a second request per click. */
|
|
93
|
+
readonly rows: readonly WorkspaceRow[];
|
|
94
|
+
/** Named "worst behind" callout — the single workspace (among ALL rows,
|
|
95
|
+
* not just the requested scope) with the highest non-null `behind` in its
|
|
96
|
+
* own liveState, or null if no row has live branch-divergence data yet. */
|
|
97
|
+
readonly worstBehind: {
|
|
98
|
+
readonly identity: WorktreeIdentity;
|
|
99
|
+
readonly behind: number;
|
|
100
|
+
} | null;
|
|
101
|
+
}
|
|
102
|
+
export declare function computeWorkspaceMetrics(records: readonly GitActivityRecord[], _identity: WorktreeIdentity, liveState: WorktreeLiveState | null, nowMs?: number): WorkspaceMetrics;
|
|
103
|
+
export declare function rollupWorkspaceMetrics(nodes: readonly {
|
|
104
|
+
readonly identity: WorktreeIdentity;
|
|
105
|
+
readonly metrics: WorkspaceMetrics;
|
|
106
|
+
}[], nowMs?: number): WorkspaceMetrics;
|
|
107
|
+
export declare function buildGitWorkspaceReport(input: {
|
|
108
|
+
readonly scope: ScopeRef;
|
|
109
|
+
readonly records: readonly GitActivityRecord[];
|
|
110
|
+
readonly identities: ReadonlyMap<string, WorktreeIdentity>;
|
|
111
|
+
readonly liveStates: ReadonlyMap<string, WorktreeLiveState>;
|
|
112
|
+
readonly nowMs?: number;
|
|
113
|
+
}): GitWorkspaceReport;
|
|
114
|
+
//# sourceMappingURL=git-workspace-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-workspace-report.d.ts","sourceRoot":"","sources":["../../src/metrics/git-workspace-report.ts"],"names":[],"mappings":"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"}
|