@yawlabs/ctxlint 0.24.0 → 0.25.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/.pre-commit-hooks.yaml +1 -1
- package/AGENT_SESSION_LINT_SPEC.md +35 -3
- package/README.md +17 -4
- package/agent-session-lint-rules.json +10 -0
- package/bin/ctxlint.mjs +360 -225
- package/dist/index.js +265 -57
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -27551,6 +27551,20 @@ import { readdir as readdir3 } from "node:fs/promises";
|
|
|
27551
27551
|
import { homedir as homedir6 } from "node:os";
|
|
27552
27552
|
import { join as join9 } from "node:path";
|
|
27553
27553
|
import { createInterface as createInterface2 } from "node:readline";
|
|
27554
|
+
function emptyRead() {
|
|
27555
|
+
return {
|
|
27556
|
+
events: [],
|
|
27557
|
+
filesRead: 0,
|
|
27558
|
+
truncated: false,
|
|
27559
|
+
sessionTurns: /* @__PURE__ */ new Map(),
|
|
27560
|
+
sessionCompactions: /* @__PURE__ */ new Map()
|
|
27561
|
+
};
|
|
27562
|
+
}
|
|
27563
|
+
function turnsCarried(read, ev) {
|
|
27564
|
+
const total = read.sessionTurns.get(ev.sessionId) ?? ev.turn;
|
|
27565
|
+
const boundary = read.sessionCompactions.get(ev.sessionId)?.find((b2) => b2 >= ev.turn);
|
|
27566
|
+
return Math.max(0, (boundary ?? total) - ev.turn);
|
|
27567
|
+
}
|
|
27554
27568
|
function asString(v2) {
|
|
27555
27569
|
return typeof v2 === "string" ? v2 : "";
|
|
27556
27570
|
}
|
|
@@ -27571,14 +27585,17 @@ function readProjectTranscript(project, home2 = resolveHome()) {
|
|
|
27571
27585
|
}
|
|
27572
27586
|
return hit;
|
|
27573
27587
|
}
|
|
27588
|
+
function clearTranscriptCache() {
|
|
27589
|
+
cache.clear();
|
|
27590
|
+
}
|
|
27574
27591
|
function candidateDirs(project, home2) {
|
|
27575
27592
|
const root = join9(home2, ".claude", "projects");
|
|
27576
27593
|
return projectDirCandidates(project).map((n7) => join9(root, n7)).filter((d) => existsSync5(d));
|
|
27577
27594
|
}
|
|
27578
27595
|
async function readUncached(project, home2) {
|
|
27579
|
-
if (!home2 || !project) return
|
|
27596
|
+
if (!home2 || !project) return emptyRead();
|
|
27580
27597
|
const dirs = candidateDirs(project, home2);
|
|
27581
|
-
if (dirs.length === 0) return
|
|
27598
|
+
if (dirs.length === 0) return emptyRead();
|
|
27582
27599
|
const names = [];
|
|
27583
27600
|
for (const dir of dirs) {
|
|
27584
27601
|
for (const name of await readdir3(dir).catch(() => [])) {
|
|
@@ -27595,8 +27612,7 @@ async function readUncached(project, home2) {
|
|
|
27595
27612
|
}).filter((f) => f !== null).sort((a, b2) => b2.mtime - a.mtime);
|
|
27596
27613
|
let truncated = files.length > MAX_TRANSCRIPTS;
|
|
27597
27614
|
const selected = files.slice(0, MAX_TRANSCRIPTS);
|
|
27598
|
-
const
|
|
27599
|
-
const pending = /* @__PURE__ */ new Map();
|
|
27615
|
+
const st2 = { events: [], pending: /* @__PURE__ */ new Map(), sessions: /* @__PURE__ */ new Map(), anonymous: 0 };
|
|
27600
27616
|
let lines = 0;
|
|
27601
27617
|
for (const { p: p2 } of selected) {
|
|
27602
27618
|
if (lines >= MAX_LINES2) {
|
|
@@ -27621,21 +27637,75 @@ async function readUncached(project, home2) {
|
|
|
27621
27637
|
} catch {
|
|
27622
27638
|
continue;
|
|
27623
27639
|
}
|
|
27624
|
-
collect(rec,
|
|
27640
|
+
collect(rec, st2);
|
|
27625
27641
|
}
|
|
27626
27642
|
} catch {
|
|
27627
27643
|
} finally {
|
|
27628
27644
|
rl.close();
|
|
27629
27645
|
}
|
|
27630
27646
|
}
|
|
27631
|
-
|
|
27647
|
+
const sessionTurns = /* @__PURE__ */ new Map();
|
|
27648
|
+
const sessionCompactions = /* @__PURE__ */ new Map();
|
|
27649
|
+
for (const [id, s] of st2.sessions) {
|
|
27650
|
+
sessionTurns.set(id, s.ordinals.size);
|
|
27651
|
+
if (s.compactions.length > 0) {
|
|
27652
|
+
sessionCompactions.set(
|
|
27653
|
+
id,
|
|
27654
|
+
[...s.compactions].sort((a, b2) => a - b2)
|
|
27655
|
+
);
|
|
27656
|
+
}
|
|
27657
|
+
}
|
|
27658
|
+
return {
|
|
27659
|
+
events: st2.events,
|
|
27660
|
+
filesRead: selected.length,
|
|
27661
|
+
truncated,
|
|
27662
|
+
sessionTurns,
|
|
27663
|
+
sessionCompactions
|
|
27664
|
+
};
|
|
27665
|
+
}
|
|
27666
|
+
function sessionState(st2, sessionId) {
|
|
27667
|
+
let s = st2.sessions.get(sessionId);
|
|
27668
|
+
if (!s) {
|
|
27669
|
+
s = { ordinals: /* @__PURE__ */ new Map(), compactions: [] };
|
|
27670
|
+
st2.sessions.set(sessionId, s);
|
|
27671
|
+
}
|
|
27672
|
+
return s;
|
|
27632
27673
|
}
|
|
27633
|
-
function
|
|
27674
|
+
function turnOf(rec, message, st2, sessionId) {
|
|
27675
|
+
const s = sessionState(st2, sessionId);
|
|
27676
|
+
if (message?.model === "<synthetic>" || rec.isSidechain === true) return s.ordinals.size;
|
|
27677
|
+
const key = asString(message?.id) || asString(rec.requestId) || `#anonymous:${++st2.anonymous}`;
|
|
27678
|
+
let ordinal = s.ordinals.get(key);
|
|
27679
|
+
if (ordinal === void 0) {
|
|
27680
|
+
ordinal = s.ordinals.size + 1;
|
|
27681
|
+
s.ordinals.set(key, ordinal);
|
|
27682
|
+
}
|
|
27683
|
+
return ordinal;
|
|
27684
|
+
}
|
|
27685
|
+
function isSet(v2) {
|
|
27686
|
+
return v2 !== void 0 && v2 !== null && v2 !== "";
|
|
27687
|
+
}
|
|
27688
|
+
function readResultLines(rec, path21) {
|
|
27689
|
+
const result = rec.toolUseResult;
|
|
27690
|
+
if (!result || typeof result !== "object") return void 0;
|
|
27691
|
+
const file2 = result.file;
|
|
27692
|
+
if (!file2 || typeof file2 !== "object") return void 0;
|
|
27693
|
+
const { filePath, numLines } = file2;
|
|
27694
|
+
if (filePath !== path21) return void 0;
|
|
27695
|
+
return typeof numLines === "number" ? numLines : void 0;
|
|
27696
|
+
}
|
|
27697
|
+
function collect(rec, st2) {
|
|
27698
|
+
const sessionId = asString(rec.sessionId) || asString(rec.session_id);
|
|
27699
|
+
if (rec.type === "system" && rec.subtype === "compact_boundary") {
|
|
27700
|
+
const s = sessionState(st2, sessionId);
|
|
27701
|
+
s.compactions.push(s.ordinals.size);
|
|
27702
|
+
return;
|
|
27703
|
+
}
|
|
27634
27704
|
const message = rec.message;
|
|
27705
|
+
const turn = rec.type === "assistant" ? turnOf(rec, message, st2, sessionId) : st2.sessions.get(sessionId)?.ordinals.size ?? 0;
|
|
27635
27706
|
const content = message?.content;
|
|
27636
27707
|
if (!Array.isArray(content)) return;
|
|
27637
27708
|
const timestamp = Date.parse(asString(rec.timestamp)) || 0;
|
|
27638
|
-
const sessionId = asString(rec.sessionId) || asString(rec.session_id);
|
|
27639
27709
|
const gitBranch = asString(rec.gitBranch) || void 0;
|
|
27640
27710
|
for (const raw of content) {
|
|
27641
27711
|
if (!raw || typeof raw !== "object") continue;
|
|
@@ -27644,7 +27714,15 @@ function collect(rec, events, pending) {
|
|
|
27644
27714
|
if (type === "text" && rec.type === "assistant") {
|
|
27645
27715
|
const text = asString(block.text);
|
|
27646
27716
|
if (text) {
|
|
27647
|
-
events.push({
|
|
27717
|
+
st2.events.push({
|
|
27718
|
+
kind: "assistant-text",
|
|
27719
|
+
text,
|
|
27720
|
+
tool: "",
|
|
27721
|
+
gitBranch,
|
|
27722
|
+
turn,
|
|
27723
|
+
timestamp,
|
|
27724
|
+
sessionId
|
|
27725
|
+
});
|
|
27648
27726
|
}
|
|
27649
27727
|
continue;
|
|
27650
27728
|
}
|
|
@@ -27653,49 +27731,76 @@ function collect(rec, events, pending) {
|
|
|
27653
27731
|
const input = block.input ?? {};
|
|
27654
27732
|
const cmdField = COMMAND_TOOLS[tool];
|
|
27655
27733
|
const writeField = WRITE_TOOLS[tool];
|
|
27734
|
+
const readField = READ_TOOLS[tool];
|
|
27656
27735
|
let ev = null;
|
|
27657
27736
|
if (cmdField) {
|
|
27658
27737
|
const text = asString(input[cmdField]);
|
|
27659
|
-
if (text) ev = { kind: "command", text, tool, gitBranch, timestamp, sessionId };
|
|
27738
|
+
if (text) ev = { kind: "command", text, tool, gitBranch, turn, timestamp, sessionId };
|
|
27660
27739
|
} else if (writeField) {
|
|
27661
27740
|
const text = asString(input[writeField]);
|
|
27662
|
-
if (text) ev = { kind: "file-write", text, tool, gitBranch, timestamp, sessionId };
|
|
27741
|
+
if (text) ev = { kind: "file-write", text, tool, gitBranch, turn, timestamp, sessionId };
|
|
27742
|
+
} else if (readField) {
|
|
27743
|
+
const text = asString(input[readField]);
|
|
27744
|
+
if (text) {
|
|
27745
|
+
ev = {
|
|
27746
|
+
kind: "file-read",
|
|
27747
|
+
text,
|
|
27748
|
+
tool,
|
|
27749
|
+
partial: PARTIAL_READ_FIELDS.some((f) => isSet(input[f])),
|
|
27750
|
+
gitBranch,
|
|
27751
|
+
turn,
|
|
27752
|
+
timestamp,
|
|
27753
|
+
sessionId
|
|
27754
|
+
};
|
|
27755
|
+
}
|
|
27663
27756
|
}
|
|
27664
27757
|
if (ev) {
|
|
27665
|
-
events.push(ev);
|
|
27666
27758
|
const id = asString(block.id);
|
|
27667
|
-
if (id)
|
|
27759
|
+
if (id) ev.toolUseId = id;
|
|
27760
|
+
st2.events.push(ev);
|
|
27761
|
+
if (id) st2.pending.set(id, ev);
|
|
27668
27762
|
}
|
|
27669
27763
|
continue;
|
|
27670
27764
|
}
|
|
27671
27765
|
if (type === "tool_result") {
|
|
27672
27766
|
const id = asString(block.tool_use_id);
|
|
27673
|
-
const ev = id ? pending.get(id) : void 0;
|
|
27767
|
+
const ev = id ? st2.pending.get(id) : void 0;
|
|
27674
27768
|
if (!ev) continue;
|
|
27675
|
-
pending.delete(id);
|
|
27769
|
+
st2.pending.delete(id);
|
|
27770
|
+
const out = resultText(block.content);
|
|
27676
27771
|
ev.isError = block.is_error === true;
|
|
27677
|
-
ev.emptyOutput =
|
|
27772
|
+
ev.emptyOutput = out.trim().length === 0;
|
|
27773
|
+
ev.outputChars = out.length;
|
|
27774
|
+
if (ev.kind === "file-read") {
|
|
27775
|
+
ev.outputTokens = countTokens(out);
|
|
27776
|
+
const lineCount = readResultLines(rec, ev.text);
|
|
27777
|
+
if (lineCount !== void 0) ev.outputLines = lineCount;
|
|
27778
|
+
}
|
|
27678
27779
|
}
|
|
27679
27780
|
}
|
|
27680
27781
|
}
|
|
27681
|
-
var WRITE_TOOLS, COMMAND_TOOLS, MAX_TRANSCRIPTS, MAX_LINES2,
|
|
27782
|
+
var WRITE_TOOLS, READ_TOOLS, PARTIAL_READ_FIELDS, COMMAND_TOOLS, MAX_TRANSCRIPTS, MAX_LINES2, cache;
|
|
27682
27783
|
var init_transcript = __esm({
|
|
27683
27784
|
"src/core/transcript.ts"() {
|
|
27684
27785
|
"use strict";
|
|
27685
27786
|
init_define_WEB_FIRST_SEGMENTS();
|
|
27787
|
+
init_tokens();
|
|
27686
27788
|
init_session_parser();
|
|
27687
27789
|
WRITE_TOOLS = {
|
|
27688
27790
|
Write: "file_path",
|
|
27689
27791
|
Edit: "file_path",
|
|
27690
27792
|
NotebookEdit: "notebook_path"
|
|
27691
27793
|
};
|
|
27794
|
+
READ_TOOLS = {
|
|
27795
|
+
Read: "file_path"
|
|
27796
|
+
};
|
|
27797
|
+
PARTIAL_READ_FIELDS = ["offset", "limit", "pages"];
|
|
27692
27798
|
COMMAND_TOOLS = {
|
|
27693
27799
|
Bash: "command",
|
|
27694
27800
|
PowerShell: "command"
|
|
27695
27801
|
};
|
|
27696
27802
|
MAX_TRANSCRIPTS = 5;
|
|
27697
27803
|
MAX_LINES2 = 2e5;
|
|
27698
|
-
EMPTY = { events: [], filesRead: 0, truncated: false };
|
|
27699
27804
|
cache = /* @__PURE__ */ new Map();
|
|
27700
27805
|
}
|
|
27701
27806
|
});
|
|
@@ -27833,7 +27938,7 @@ function isUnverified(ev) {
|
|
|
27833
27938
|
async function checkUnverifiedGateClaimedClean(ctx) {
|
|
27834
27939
|
const { events } = await readProjectTranscript(ctx.currentProject);
|
|
27835
27940
|
if (events.length === 0) return [];
|
|
27836
|
-
const ordered =
|
|
27941
|
+
const ordered = events.filter((e) => e.kind !== "file-read").sort((a, b2) => a.timestamp - b2.timestamp);
|
|
27837
27942
|
const issues = [];
|
|
27838
27943
|
const reported = /* @__PURE__ */ new Set();
|
|
27839
27944
|
for (let i2 = 0; i2 < ordered.length; i2++) {
|
|
@@ -27914,7 +28019,7 @@ function isBranchAway(cmd) {
|
|
|
27914
28019
|
async function checkDefaultBranchAccumulation(ctx) {
|
|
27915
28020
|
const { events } = await readProjectTranscript(ctx.currentProject);
|
|
27916
28021
|
if (events.length === 0) return [];
|
|
27917
|
-
const ordered =
|
|
28022
|
+
const ordered = events.filter((e) => e.kind !== "file-read").sort((a, b2) => a.timestamp - b2.timestamp);
|
|
27918
28023
|
const pending = /* @__PURE__ */ new Set();
|
|
27919
28024
|
let branch = "";
|
|
27920
28025
|
let firstWrite = "";
|
|
@@ -28058,6 +28163,93 @@ var init_unresolvable_sha = __esm({
|
|
|
28058
28163
|
}
|
|
28059
28164
|
});
|
|
28060
28165
|
|
|
28166
|
+
// src/core/checks/session/large-read.ts
|
|
28167
|
+
import { isAbsolute as isAbsolute6, relative as relative6 } from "node:path";
|
|
28168
|
+
function qualifies(ev) {
|
|
28169
|
+
if (ev.kind !== "file-read" || ev.partial || ev.isError) return false;
|
|
28170
|
+
return (ev.outputTokens ?? 0) >= LARGE_READ_TOKENS;
|
|
28171
|
+
}
|
|
28172
|
+
function fmt(n7) {
|
|
28173
|
+
return n7.toLocaleString("en-US");
|
|
28174
|
+
}
|
|
28175
|
+
function displayPath(path21, project) {
|
|
28176
|
+
const rel = relative6(project, path21);
|
|
28177
|
+
if (rel && !rel.startsWith("..") && !isAbsolute6(rel)) return rel.replace(/\\/g, "/");
|
|
28178
|
+
return path21;
|
|
28179
|
+
}
|
|
28180
|
+
function fileKey(path21) {
|
|
28181
|
+
const slashed = path21.replace(/\\/g, "/");
|
|
28182
|
+
return process.platform === "win32" ? slashed.toLowerCase() : slashed;
|
|
28183
|
+
}
|
|
28184
|
+
async function checkLargeRead(ctx) {
|
|
28185
|
+
const read = await readProjectTranscript(ctx.currentProject);
|
|
28186
|
+
const byCall = /* @__PURE__ */ new Map();
|
|
28187
|
+
const unkeyed = [];
|
|
28188
|
+
for (const ev of read.events) {
|
|
28189
|
+
if (!qualifies(ev)) continue;
|
|
28190
|
+
const hit = { ev, tokens: ev.outputTokens ?? 0, carried: turnsCarried(read, ev) };
|
|
28191
|
+
if (!ev.toolUseId) {
|
|
28192
|
+
unkeyed.push(hit);
|
|
28193
|
+
continue;
|
|
28194
|
+
}
|
|
28195
|
+
const prev = byCall.get(ev.toolUseId);
|
|
28196
|
+
if (!prev || hit.carried < prev.carried) byCall.set(ev.toolUseId, hit);
|
|
28197
|
+
}
|
|
28198
|
+
const hits = [...byCall.values(), ...unkeyed];
|
|
28199
|
+
if (hits.length === 0) return [];
|
|
28200
|
+
let totalTokens = 0;
|
|
28201
|
+
let carry = 0;
|
|
28202
|
+
const files = /* @__PURE__ */ new Map();
|
|
28203
|
+
for (const { ev, tokens, carried } of hits) {
|
|
28204
|
+
totalTokens += tokens;
|
|
28205
|
+
carry += tokens * carried;
|
|
28206
|
+
const key = fileKey(ev.text);
|
|
28207
|
+
const file2 = files.get(key) ?? { path: ev.text, reads: 0, tokens: 0 };
|
|
28208
|
+
file2.reads += 1;
|
|
28209
|
+
file2.tokens += tokens;
|
|
28210
|
+
if (ev.outputLines !== void 0) file2.lines = Math.max(file2.lines ?? 0, ev.outputLines);
|
|
28211
|
+
files.set(key, file2);
|
|
28212
|
+
}
|
|
28213
|
+
const top = [...files.values()].sort((a, b2) => b2.tokens - a.tokens || a.path.localeCompare(b2.path)).slice(0, TOP_FILES);
|
|
28214
|
+
const topLines = top.map((f) => {
|
|
28215
|
+
const reads = `${f.reads} read${f.reads === 1 ? "" : "s"}`;
|
|
28216
|
+
const lines = f.lines !== void 0 ? `, ${fmt(f.lines)} line${f.lines === 1 ? "" : "s"}` : "";
|
|
28217
|
+
return ` ${displayPath(f.path, ctx.currentProject)} -- ${reads}, ${fmt(f.tokens)} tokens${lines}`;
|
|
28218
|
+
});
|
|
28219
|
+
const count = hits.length;
|
|
28220
|
+
const detail = [
|
|
28221
|
+
`Largest files by tokens read whole:`,
|
|
28222
|
+
...topLines,
|
|
28223
|
+
`Carry = each Read's result tokens x the later turns of its session that re-sent it (to the session's end or its next /compact). An estimate: tokens are counted with a proxy tokenizer, and a result's first re-send is a cache write rather than a read.`
|
|
28224
|
+
];
|
|
28225
|
+
if (read.truncated) {
|
|
28226
|
+
detail.push(
|
|
28227
|
+
`Transcript read was capped (${read.filesRead} most recent transcripts, bounded line count): these figures cover only what was read, so the real totals are higher.`
|
|
28228
|
+
);
|
|
28229
|
+
}
|
|
28230
|
+
return [
|
|
28231
|
+
{
|
|
28232
|
+
severity: "info",
|
|
28233
|
+
check: "session-large-read",
|
|
28234
|
+
ruleId: "session-large-read/large-read",
|
|
28235
|
+
line: 0,
|
|
28236
|
+
message: `${count} whole-file Read${count === 1 ? "" : "s"} of ${fmt(LARGE_READ_TOKENS)}+ tokens (${fmt(totalTokens)} tokens); est. ${fmt(carry)} tokens of cache-read carry on later turns`,
|
|
28237
|
+
detail: detail.join("\n"),
|
|
28238
|
+
suggestion: "Before reading a large file whole, find the part you need with `grep -n` (or the Grep tool) and Read just that range with `offset`/`limit`. For a question that needs the whole file, delegate it to a subagent: its reads stay in its own context and only the answer comes back."
|
|
28239
|
+
}
|
|
28240
|
+
];
|
|
28241
|
+
}
|
|
28242
|
+
var LARGE_READ_TOKENS, TOP_FILES;
|
|
28243
|
+
var init_large_read = __esm({
|
|
28244
|
+
"src/core/checks/session/large-read.ts"() {
|
|
28245
|
+
"use strict";
|
|
28246
|
+
init_define_WEB_FIRST_SEGMENTS();
|
|
28247
|
+
init_transcript();
|
|
28248
|
+
LARGE_READ_TOKENS = 4e3;
|
|
28249
|
+
TOP_FILES = 3;
|
|
28250
|
+
}
|
|
28251
|
+
});
|
|
28252
|
+
|
|
28061
28253
|
// src/core/checks/ci-coverage.ts
|
|
28062
28254
|
import { readdir as readdir4, readFile as readFile4 } from "node:fs/promises";
|
|
28063
28255
|
import { join as join10 } from "node:path";
|
|
@@ -29108,7 +29300,7 @@ import { readFileSync as readFileSync8 } from "node:fs";
|
|
|
29108
29300
|
import { resolve as resolve15, dirname as dirname7 } from "node:path";
|
|
29109
29301
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
29110
29302
|
function loadVersion() {
|
|
29111
|
-
if (true) return "0.
|
|
29303
|
+
if (true) return "0.25.0";
|
|
29112
29304
|
try {
|
|
29113
29305
|
const __dir = dirname7(fileURLToPath2(import.meta.url));
|
|
29114
29306
|
const pkgPath = resolve15(__dir, "../package.json");
|
|
@@ -29357,6 +29549,8 @@ async function runAudit(projectRoot, activeChecks, options = {}) {
|
|
|
29357
29549
|
sessionPromises.push(checkDefaultBranchAccumulation(sessionCtx));
|
|
29358
29550
|
if (sessionChecksToRun.includes("session-unresolvable-sha"))
|
|
29359
29551
|
sessionPromises.push(checkUnresolvableSha(sessionCtx));
|
|
29552
|
+
if (sessionChecksToRun.includes("session-large-read"))
|
|
29553
|
+
sessionPromises.push(checkLargeRead(sessionCtx));
|
|
29360
29554
|
const sessionResults = await Promise.all(sessionPromises);
|
|
29361
29555
|
const sessionIssues = sessionResults.flat();
|
|
29362
29556
|
fileResults.push({
|
|
@@ -29562,6 +29756,7 @@ var init_audit = __esm({
|
|
|
29562
29756
|
init_unverified_gate_claimed_clean();
|
|
29563
29757
|
init_default_branch_accumulation();
|
|
29564
29758
|
init_unresolvable_sha();
|
|
29759
|
+
init_large_read();
|
|
29565
29760
|
init_ci_coverage();
|
|
29566
29761
|
init_ci_secrets();
|
|
29567
29762
|
init_content_secrets();
|
|
@@ -29607,7 +29802,8 @@ var init_audit = __esm({
|
|
|
29607
29802
|
"session-shared-temp-path",
|
|
29608
29803
|
"session-unverified-gate-claimed-clean",
|
|
29609
29804
|
"session-default-branch-accumulation",
|
|
29610
|
-
"session-unresolvable-sha"
|
|
29805
|
+
"session-unresolvable-sha",
|
|
29806
|
+
"session-large-read"
|
|
29611
29807
|
];
|
|
29612
29808
|
ALL_SKILL_CHECKS = [
|
|
29613
29809
|
"skill-frontmatter",
|
|
@@ -56870,49 +57066,49 @@ var require_fast_uri = __commonJS({
|
|
|
56870
57066
|
schemelessOptions.skipEscape = true;
|
|
56871
57067
|
return serialize(resolved, schemelessOptions);
|
|
56872
57068
|
}
|
|
56873
|
-
function resolveComponent(base,
|
|
57069
|
+
function resolveComponent(base, relative9, options, skipNormalization) {
|
|
56874
57070
|
const target = {};
|
|
56875
57071
|
if (!skipNormalization) {
|
|
56876
57072
|
base = parse5(serialize(base, options), options);
|
|
56877
|
-
|
|
57073
|
+
relative9 = parse5(serialize(relative9, options), options);
|
|
56878
57074
|
}
|
|
56879
57075
|
options = options || {};
|
|
56880
|
-
if (!options.tolerant &&
|
|
56881
|
-
target.scheme =
|
|
56882
|
-
target.userinfo =
|
|
56883
|
-
target.host =
|
|
56884
|
-
target.port =
|
|
56885
|
-
target.path = removeDotSegments(
|
|
56886
|
-
target.query =
|
|
57076
|
+
if (!options.tolerant && relative9.scheme) {
|
|
57077
|
+
target.scheme = relative9.scheme;
|
|
57078
|
+
target.userinfo = relative9.userinfo;
|
|
57079
|
+
target.host = relative9.host;
|
|
57080
|
+
target.port = relative9.port;
|
|
57081
|
+
target.path = removeDotSegments(relative9.path || "");
|
|
57082
|
+
target.query = relative9.query;
|
|
56887
57083
|
} else {
|
|
56888
|
-
if (
|
|
56889
|
-
target.userinfo =
|
|
56890
|
-
target.host =
|
|
56891
|
-
target.port =
|
|
56892
|
-
target.path = removeDotSegments(
|
|
56893
|
-
target.query =
|
|
57084
|
+
if (relative9.userinfo !== void 0 || relative9.host !== void 0 || relative9.port !== void 0) {
|
|
57085
|
+
target.userinfo = relative9.userinfo;
|
|
57086
|
+
target.host = relative9.host;
|
|
57087
|
+
target.port = relative9.port;
|
|
57088
|
+
target.path = removeDotSegments(relative9.path || "");
|
|
57089
|
+
target.query = relative9.query;
|
|
56894
57090
|
} else {
|
|
56895
|
-
if (!
|
|
57091
|
+
if (!relative9.path) {
|
|
56896
57092
|
target.path = base.path;
|
|
56897
|
-
if (
|
|
56898
|
-
target.query =
|
|
57093
|
+
if (relative9.query !== void 0) {
|
|
57094
|
+
target.query = relative9.query;
|
|
56899
57095
|
} else {
|
|
56900
57096
|
target.query = base.query;
|
|
56901
57097
|
}
|
|
56902
57098
|
} else {
|
|
56903
|
-
if (
|
|
56904
|
-
target.path = removeDotSegments(
|
|
57099
|
+
if (relative9.path[0] === "/") {
|
|
57100
|
+
target.path = removeDotSegments(relative9.path);
|
|
56905
57101
|
} else {
|
|
56906
57102
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
56907
|
-
target.path = "/" +
|
|
57103
|
+
target.path = "/" + relative9.path;
|
|
56908
57104
|
} else if (!base.path) {
|
|
56909
|
-
target.path =
|
|
57105
|
+
target.path = relative9.path;
|
|
56910
57106
|
} else {
|
|
56911
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
57107
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative9.path;
|
|
56912
57108
|
}
|
|
56913
57109
|
target.path = removeDotSegments(target.path);
|
|
56914
57110
|
}
|
|
56915
|
-
target.query =
|
|
57111
|
+
target.query = relative9.query;
|
|
56916
57112
|
}
|
|
56917
57113
|
target.userinfo = base.userinfo;
|
|
56918
57114
|
target.host = base.host;
|
|
@@ -56920,7 +57116,7 @@ var require_fast_uri = __commonJS({
|
|
|
56920
57116
|
}
|
|
56921
57117
|
target.scheme = base.scheme;
|
|
56922
57118
|
}
|
|
56923
|
-
target.fragment =
|
|
57119
|
+
target.fragment = relative9.fragment;
|
|
56924
57120
|
return target;
|
|
56925
57121
|
}
|
|
56926
57122
|
function equal(uriA, uriB, options) {
|
|
@@ -59407,11 +59603,11 @@ var require_format = __commonJS({
|
|
|
59407
59603
|
}
|
|
59408
59604
|
function getFormat(fmtDef) {
|
|
59409
59605
|
const code = fmtDef instanceof RegExp ? (0, codegen_1.regexpCode)(fmtDef) : opts.code.formats ? (0, codegen_1._)`${opts.code.formats}${(0, codegen_1.getProperty)(schema)}` : void 0;
|
|
59410
|
-
const
|
|
59606
|
+
const fmt2 = gen.scopeValue("formats", { key: schema, ref: fmtDef, code });
|
|
59411
59607
|
if (typeof fmtDef == "object" && !(fmtDef instanceof RegExp)) {
|
|
59412
|
-
return [fmtDef.type || "string", fmtDef.validate, (0, codegen_1._)`${
|
|
59608
|
+
return [fmtDef.type || "string", fmtDef.validate, (0, codegen_1._)`${fmt2}.validate`];
|
|
59413
59609
|
}
|
|
59414
|
-
return ["string", fmtDef,
|
|
59610
|
+
return ["string", fmtDef, fmt2];
|
|
59415
59611
|
}
|
|
59416
59612
|
function validCondition() {
|
|
59417
59613
|
if (typeof formatDef == "object" && !(formatDef instanceof RegExp) && formatDef.async) {
|
|
@@ -60081,8 +60277,8 @@ var require_limit = __commonJS({
|
|
|
60081
60277
|
ref: self2.formats,
|
|
60082
60278
|
code: opts.code.formats
|
|
60083
60279
|
});
|
|
60084
|
-
const
|
|
60085
|
-
cxt.fail$data((0, codegen_1.or)((0, codegen_1._)`typeof ${
|
|
60280
|
+
const fmt2 = gen.const("fmt", (0, codegen_1._)`${fmts}[${fCxt.schemaCode}]`);
|
|
60281
|
+
cxt.fail$data((0, codegen_1.or)((0, codegen_1._)`typeof ${fmt2} != "object"`, (0, codegen_1._)`${fmt2} instanceof RegExp`, (0, codegen_1._)`typeof ${fmt2}.compare != "function"`, compareCode(fmt2)));
|
|
60086
60282
|
}
|
|
60087
60283
|
function validateFormat() {
|
|
60088
60284
|
const format3 = fCxt.schema;
|
|
@@ -60092,15 +60288,15 @@ var require_limit = __commonJS({
|
|
|
60092
60288
|
if (typeof fmtDef != "object" || fmtDef instanceof RegExp || typeof fmtDef.compare != "function") {
|
|
60093
60289
|
throw new Error(`"${keyword}": format "${format3}" does not define "compare" function`);
|
|
60094
60290
|
}
|
|
60095
|
-
const
|
|
60291
|
+
const fmt2 = gen.scopeValue("formats", {
|
|
60096
60292
|
key: format3,
|
|
60097
60293
|
ref: fmtDef,
|
|
60098
60294
|
code: opts.code.formats ? (0, codegen_1._)`${opts.code.formats}${(0, codegen_1.getProperty)(format3)}` : void 0
|
|
60099
60295
|
});
|
|
60100
|
-
cxt.fail$data(compareCode(
|
|
60296
|
+
cxt.fail$data(compareCode(fmt2));
|
|
60101
60297
|
}
|
|
60102
|
-
function compareCode(
|
|
60103
|
-
return (0, codegen_1._)`${
|
|
60298
|
+
function compareCode(fmt2) {
|
|
60299
|
+
return (0, codegen_1._)`${fmt2}.compare(${data}, ${schemaCode}) ${KWDs[keyword].fail} 0`;
|
|
60104
60300
|
}
|
|
60105
60301
|
},
|
|
60106
60302
|
dependencies: ["format"]
|
|
@@ -62825,6 +63021,7 @@ var init_server4 = __esm({
|
|
|
62825
63021
|
init_tokens();
|
|
62826
63022
|
init_git();
|
|
62827
63023
|
init_paths();
|
|
63024
|
+
init_transcript();
|
|
62828
63025
|
init_version2();
|
|
62829
63026
|
contextCheckEnum = external_exports.enum(ALL_CHECKS);
|
|
62830
63027
|
mcpCheckEnum = external_exports.enum(ALL_MCP_CHECKS);
|
|
@@ -63077,7 +63274,7 @@ var init_server4 = __esm({
|
|
|
63077
63274
|
);
|
|
63078
63275
|
server.tool(
|
|
63079
63276
|
"ctxlint_session_audit",
|
|
63080
|
-
"Audit AI agent session data for cross-project consistency. Checks for missing GitHub secrets, diverged config files
|
|
63277
|
+
"Audit AI agent session data for cross-project consistency and session hazards. Checks for missing GitHub secrets, diverged config files and missing workflows across sibling repositories; stale, duplicate or overflowing memory entries; command loops; and, from Claude Code transcripts, shared temp paths, gates claimed clean after failing, edits piling up on the default branch, unresolvable commit SHAs in memory, and large whole-file Reads re-sent as context on later turns.",
|
|
63081
63278
|
{
|
|
63082
63279
|
projectPath: external_exports.string().optional().describe("Path to the project root. Defaults to current working directory."),
|
|
63083
63280
|
checks: external_exports.array(sessionCheckEnum).optional().describe("Specific session checks to run (default: all session-* checks).")
|
|
@@ -63110,6 +63307,7 @@ var init_server4 = __esm({
|
|
|
63110
63307
|
resetGit();
|
|
63111
63308
|
resetPathsCache();
|
|
63112
63309
|
resetPackageJsonCache();
|
|
63310
|
+
clearTranscriptCache();
|
|
63113
63311
|
}
|
|
63114
63312
|
}
|
|
63115
63313
|
);
|
|
@@ -70128,6 +70326,13 @@ function buildRuleDescriptors() {
|
|
|
70128
70326
|
},
|
|
70129
70327
|
helpUri: "https://github.com/yawlabs/ctxlint#what-it-checks"
|
|
70130
70328
|
},
|
|
70329
|
+
{
|
|
70330
|
+
id: "ctxlint/session-large-read",
|
|
70331
|
+
shortDescription: {
|
|
70332
|
+
text: "Whole-file Reads of large files re-sent as context on every later turn"
|
|
70333
|
+
},
|
|
70334
|
+
helpUri: "https://github.com/yawlabs/ctxlint#what-it-checks"
|
|
70335
|
+
},
|
|
70131
70336
|
{
|
|
70132
70337
|
id: "ctxlint/skill-frontmatter",
|
|
70133
70338
|
shortDescription: { text: "Skill/agent definition missing required frontmatter" },
|
|
@@ -70362,6 +70567,7 @@ Fixed ${applied.totalFixes} issue${applied.totalFixes !== 1 ? "s" : ""} in ${app
|
|
|
70362
70567
|
resetGit();
|
|
70363
70568
|
resetPathsCache();
|
|
70364
70569
|
resetPackageJsonCache();
|
|
70570
|
+
clearTranscriptCache();
|
|
70365
70571
|
}
|
|
70366
70572
|
if (opts.watch) {
|
|
70367
70573
|
const chalk2 = (await Promise.resolve().then(() => (init_source(), source_exports))).default;
|
|
@@ -70458,6 +70664,7 @@ Fixed ${applied.totalFixes} issue${applied.totalFixes !== 1 ? "s" : ""} in ${app
|
|
|
70458
70664
|
resetPathsCache();
|
|
70459
70665
|
resetPackageJsonCache();
|
|
70460
70666
|
clearFileCache();
|
|
70667
|
+
clearTranscriptCache();
|
|
70461
70668
|
}
|
|
70462
70669
|
console.log(chalk2.dim("\nWatching for changes... (Ctrl+C to stop)\n"));
|
|
70463
70670
|
}, 300);
|
|
@@ -70651,6 +70858,7 @@ var init_cli = __esm({
|
|
|
70651
70858
|
init_ora();
|
|
70652
70859
|
init_paths();
|
|
70653
70860
|
init_cache();
|
|
70861
|
+
init_transcript();
|
|
70654
70862
|
init_reporter();
|
|
70655
70863
|
init_fixer();
|
|
70656
70864
|
init_tokens();
|
package/package.json
CHANGED