🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@quilt-dev/cli

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@quilt-dev/cli - npm Package Compare versions

Comparing version
0.5.0
to
0.5.1
+62
dist/blame.js
import { readAuthorship } from "./authorship.js";
import { buildModel } from "./engine.js";
import { latestPromptBefore, locateTranscript } from "./transcripts.js";
function matchingEvent(events, path, line, actor) {
for (let i = events.length - 1; i >= 0; i--) {
const event = events[i];
if (event.path !== path || event.actor !== actor)
continue;
if (line.type === "add") {
if (line.key && event.addedKeys?.includes(line.key))
return event;
if (!event.addedKeys && event.added.includes(line.text))
return event;
}
else if (line.type === "del") {
if (line.key && event.removedKeys?.includes(line.key))
return event;
if (!event.removedKeys && event.removed.includes(line.text))
return event;
}
}
return null;
}
/**
* Diff HEAD to the worktree and retain the engine's ownership call per line.
* Transcript reads happen only when this function is called by the review API.
*/
export function fileBlame(store, relPath, transcriptOptions = {}) {
const file = buildModel(store, null, { ledgerOverlay: true }).files.find((candidate) => candidate.path === relPath);
if (!file)
return null;
if (file.binary)
return { path: file.path, isNew: file.isNew, isDeleted: file.isDeleted, binary: true, lines: [] };
const events = readAuthorship(store);
const transcriptCache = new Map();
const lines = file.hunks.flatMap((hunk) => hunk.lines.map((line) => {
const provenance = line.actors.map((actor) => {
const event = matchingEvent(events, file.path, line, actor);
if (!transcriptCache.has(actor)) {
transcriptCache.set(actor, locateTranscript(actor, store.paths.repoRoot, transcriptOptions));
}
const transcript = transcriptCache.get(actor) ?? null;
const prompt = event && transcript ? latestPromptBefore(transcript.prompts, event.ts) : null;
return {
actor,
editTs: event?.ts ?? null,
provider: transcript?.provider ?? null,
sessionId: transcript?.sessionId ?? null,
promptTs: prompt?.ts ?? null,
prompt: prompt?.prompt ?? null,
inferred: prompt !== null,
};
});
return {
...line,
actor: line.actors[0] ?? null,
lineNumber: line.type === "del" ? line.oldLineNumber : line.newLineNumber,
provenance,
};
}));
return { path: file.path, isNew: file.isNew, isDeleted: file.isDeleted, binary: false, lines };
}
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { homedir } from "node:os";
import { basename, join, resolve, sep } from "node:path";
function jsonLines(path) {
try {
return readFileSync(path, "utf8")
.split("\n")
.filter((line) => line.trim())
.flatMap((line) => {
try {
return [JSON.parse(line)];
}
catch {
return [];
}
});
}
catch {
return [];
}
}
function filesUnder(root, accept) {
if (!existsSync(root))
return [];
const out = [];
const walk = (dir) => {
let entries;
try {
entries = readdirSync(dir, { withFileTypes: true });
}
catch {
return;
}
for (const entry of entries) {
const path = join(dir, entry.name);
if (entry.isDirectory())
walk(path);
else if (entry.isFile() && accept(path))
out.push(path);
}
};
walk(root);
return out;
}
function actorParts(actorId) {
const match = /^(claude|codex)-(.+)$/.exec(actorId);
if (!match)
return null;
return { provider: match[1], prefix: match[2] };
}
function insideRepo(cwd, repoRoot) {
if (typeof cwd !== "string")
return false;
const root = resolve(repoRoot);
const at = resolve(cwd);
return at === root || at.startsWith(root + sep) || root.startsWith(at + sep);
}
function claudeText(content) {
if (typeof content === "string")
return content.trim() || null;
if (!Array.isArray(content))
return null;
const text = content
.filter((part) => !!part && typeof part === "object")
.filter((part) => part.type === "text" && typeof part.text === "string")
.map((part) => String(part.text).trim())
.filter(Boolean)
.join("\n");
return text || null;
}
function claudeMatch(prefix, repoRoot, root) {
const encodedRepo = resolve(repoRoot).replace(/[^a-zA-Z0-9]/g, "-");
const projectRoot = join(root, encodedRepo);
const searchRoot = existsSync(projectRoot) ? projectRoot : root;
const candidates = filesUnder(searchRoot, (path) => path.endsWith(".jsonl") && basename(path).startsWith(prefix));
for (const path of candidates) {
const rows = jsonLines(path);
const sessionId = rows.find((row) => typeof row.sessionId === "string")?.sessionId;
if (typeof sessionId !== "string" || !sessionId.startsWith(prefix))
continue;
if (!rows.some((row) => insideRepo(row.cwd, repoRoot)))
continue;
const prompts = rows.flatMap((row) => {
if (row.type !== "user" || row.message?.role !== "user" || typeof row.timestamp !== "string")
return [];
const prompt = claudeText(row.message.content);
return prompt ? [{ ts: row.timestamp, prompt }] : [];
});
return { provider: "claude", sessionId, prompts };
}
return null;
}
function rolloutMeta(path) {
const rows = jsonLines(path);
const meta = rows.find((row) => row.type === "session_meta")?.payload;
if (!meta || typeof meta.id !== "string" || typeof meta.cwd !== "string")
return null;
const prompts = rows.flatMap((row) => {
if (row.type !== "event_msg" || row.payload?.type !== "user_message")
return [];
if (typeof row.timestamp !== "string" || typeof row.payload.message !== "string")
return [];
const prompt = row.payload.message.trim();
return prompt ? [{ ts: row.timestamp, prompt }] : [];
});
return { id: meta.id, cwd: meta.cwd, prompts };
}
function codexMatch(prefix, repoRoot, root) {
const sessionsDir = join(root, "sessions");
let match = null;
for (const path of filesUnder(sessionsDir, (p) => p.endsWith(".jsonl") && basename(p).startsWith("rollout-"))) {
if (!basename(path).includes(prefix))
continue;
const meta = rolloutMeta(path);
if (meta?.id.startsWith(prefix) && insideRepo(meta.cwd, repoRoot)) {
match = { id: meta.id, prompts: meta.prompts };
break;
}
}
if (!match)
return null;
const history = jsonLines(join(root, "history.jsonl"));
const primary = history.flatMap((row) => {
if (row.session_id !== match.id || typeof row.ts !== "number" || typeof row.text !== "string")
return [];
const prompt = row.text.trim();
return prompt ? [{ ts: new Date(row.ts * 1000).toISOString(), prompt }] : [];
});
return { provider: "codex", sessionId: match.id, prompts: primary.length ? primary : match.prompts };
}
/** Locate the local transcript for an auto-derived Quilt actor. Read-only. */
export function locateTranscript(actorId, repoRoot, options = {}) {
const parts = actorParts(actorId);
if (!parts)
return null;
if (parts.provider === "claude") {
const root = options.claudeDir ?? process.env.QUILT_CLAUDE_DIR ?? join(homedir(), ".claude", "projects");
return claudeMatch(parts.prefix, repoRoot, root);
}
const root = options.codexDir ?? process.env.QUILT_CODEX_DIR ?? join(homedir(), ".codex");
return codexMatch(parts.prefix, repoRoot, root);
}
/** Latest user prompt at or before an edit, which is a time-based inference. */
export function latestPromptBefore(prompts, editTs) {
const limit = Date.parse(editTs);
if (!Number.isFinite(limit))
return null;
let best = null;
for (const prompt of prompts) {
const at = Date.parse(prompt.ts);
if (!Number.isFinite(at) || at > limit)
continue;
if (!best || at > Date.parse(best.ts))
best = prompt;
}
return best;
}
+44
-4

@@ -554,2 +554,5 @@ import { lstatSync, readFileSync } from "node:fs";

let conflicted = false;
const lines = [];
let oldLine = hunk.oldStart;
let newLine = hunk.newStart;
// A fresh keyer per hunk, started at the hunk's line offsets. Called on every

@@ -560,4 +563,37 @@ // op (incl. eq/trivial) so the keys line up with what reconcile recorded.

const key = keyOf(op);
if (op.type === "eq")
const opOldLine = op.type === "add" ? null : oldLine;
const opNewLine = op.type === "del" ? null : newLine;
if (op.type !== "add")
oldLine++;
if (op.type !== "del")
newLine++;
if (op.type === "eq") {
lines.push({
type: op.type,
text: op.text,
key,
oldLineNumber: opOldLine,
newLineNumber: opNewLine,
actors: [],
conflicted: false,
unowned: false,
});
continue;
}
const map = op.type === "add" ? file?.added : file?.removed;
const owner = map?.[key];
const lineActors = new Set(owner ? [owner] : []);
const contenders = fileConflicts[key] ?? [];
for (const actor of contenders)
lineActors.add(actor);
lines.push({
type: op.type,
text: op.text,
key,
oldLineNumber: opOldLine,
newLineNumber: opNewLine,
actors: [...lineActors],
conflicted: contenders.length > 0,
unowned: lineActors.size === 0,
});
// Trivial lines (braces, blanks) are neither owned nor counted as

@@ -567,4 +603,2 @@ // unattributed — they ride along with the hunk's substantive changes.

continue;
const map = op.type === "add" ? file?.added : file?.removed;
const owner = map?.[key];
if (owner) {

@@ -609,2 +643,8 @@ owners.add(owner);

unownedLines = 0;
for (const line of lines) {
if (line.type !== "eq" && line.unowned) {
line.actors = [holder];
line.unowned = false;
}
}
}

@@ -625,3 +665,3 @@ else {

: undefined;
return { hunk, ownership: ownership_, actors, conflicted, overlap, linesByActor, unownedLines };
return { hunk, ownership: ownership_, actors, conflicted, overlap, linesByActor, unownedLines, lines };
}

@@ -628,0 +668,0 @@ /**

@@ -5,3 +5,5 @@ import { createServer } from "node:http";

import { fleetSnapshot } from "./fleet.js";
import { fileBlame } from "./blame.js";
import { shortHead } from "./git.js";
import { repoRelative } from "./paths.js";
import { initSymbols } from "./symbols.js";

@@ -41,3 +43,4 @@ import { VERSION } from "./version.js";

}
const url = (req.url ?? "/").split("?")[0];
const parsedUrl = new URL(req.url ?? "/", "http://127.0.0.1");
const url = parsedUrl.pathname;
if (url === "/") {

@@ -67,2 +70,26 @@ res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });

}
if (url === "/api/blame") {
const requested = parsedUrl.searchParams.get("path");
const relPath = requested ? repoRelative(store.paths.repoRoot, requested) : null;
if (!relPath || relPath !== requested) {
res.writeHead(400, { "content-type": "application/json", "cache-control": "no-store" });
res.end(JSON.stringify({ error: "path must be a normalized file inside the repository" }));
return;
}
try {
const blame = fileBlame(store, relPath);
if (!blame) {
res.writeHead(404, { "content-type": "application/json", "cache-control": "no-store" });
res.end(JSON.stringify({ error: "file has no uncommitted changes" }));
return;
}
res.writeHead(200, { "content-type": "application/json", "cache-control": "no-store" });
res.end(JSON.stringify(blame));
}
catch (err) {
res.writeHead(500, { "content-type": "application/json", "cache-control": "no-store" });
res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
}
return;
}
res.writeHead(404, { "content-type": "text/plain" });

@@ -175,2 +202,25 @@ res.end("not found\n");

.un { color: var(--faint); font-size: 11.5px; }
.review-toggle { appearance: none; border: 0; background: none; color: var(--text); padding: 0; cursor: pointer;
font: inherit; font-family: var(--mono); text-align: left; }
.review-toggle::before { content: "▸"; color: var(--faint); display: inline-block; width: 15px; }
.review-toggle.open::before { content: "▾"; }
.review-cell { padding: 0 10px 12px; background: color-mix(in srgb, var(--bg) 38%, var(--panel)); }
.review { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.review-state { padding: 14px; color: var(--dim); font-size: 12px; }
.diff-line { display: grid; grid-template-columns: 42px 42px 18px minmax(0, 1fr) auto; align-items: start;
min-height: 25px; border-top: 1px solid color-mix(in srgb, var(--border) 65%, transparent); font-family: var(--mono); font-size: 11.5px; }
.diff-line:first-child { border-top: 0; }
.diff-line.add { background: color-mix(in srgb, var(--green) 7%, transparent); }
.diff-line.del { background: color-mix(in srgb, var(--red) 7%, transparent); }
.diff-line.conflict { box-shadow: inset 3px 0 var(--red); }
.ln { color: var(--faint); text-align: right; padding: 4px 7px 4px 2px; user-select: none; }
.sign { color: var(--faint); padding: 4px 3px; }
.code { white-space: pre-wrap; overflow-wrap: anywhere; padding: 4px 8px 4px 2px; }
.line-meta { padding: 2px 6px; max-width: 360px; text-align: right; }
.prompt { display: inline-block; text-align: left; margin-left: 4px; vertical-align: top; }
.prompt summary { color: var(--cyan); cursor: pointer; list-style: none; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 10.5px; }
.prompt summary::-webkit-details-marker { display: none; }
.prompt pre { white-space: pre-wrap; overflow-wrap: anywhere; max-width: 340px; max-height: 180px; overflow: auto;
color: var(--text); background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 8px; margin: 4px 0; }
.review-notes { padding: 9px 11px; color: var(--faint); font-size: 10.5px; border-top: 1px solid var(--border); }

@@ -208,2 +258,5 @@ .kv { font-family: var(--mono); font-size: 12.5px; }

var PALETTE = ["#e06c75","#e5a06b","#e3c46b","#8fc46f","#56c2a8","#5aa9e6","#8a7fe8","#d074c4"];
var OPEN_REVIEWS = Object.create(null);
var OPEN_PROMPTS = Object.create(null);
var REVIEW_CACHE = Object.create(null);
function colorFor(id) {

@@ -256,2 +309,52 @@ var h = 0;

function renderReviewData(d, panel) {
panel.replaceChildren();
if (d.binary) {
panel.appendChild(el("div", "review-state", "Binary file: line review is unavailable."));
return;
}
d.lines.forEach(function (line, lineIndex) {
var meta = el("div", "line-meta");
if (line.actors.length) line.actors.forEach(function (actor) { meta.appendChild(chip(actor)); });
else if (line.type !== "eq") meta.appendChild(el("span", "un", "unattributed"));
if (line.conflicted) meta.appendChild(badge("contended", "conflict"));
line.provenance.forEach(function (p, provenanceIndex) {
if (!p.prompt) return;
var details = el("details", "prompt");
var promptKey = d.path + ":" + lineIndex + ":" + provenanceIndex;
details.open = !!OPEN_PROMPTS[promptKey];
details.addEventListener("toggle", function () { OPEN_PROMPTS[promptKey] = details.open; });
details.appendChild(el("summary", null, "prompt"));
details.appendChild(el("pre", null, p.prompt));
meta.appendChild(details);
});
var kind = line.type === "add" ? "add" : line.type === "del" ? "del" : "eq";
var sign = line.type === "add" ? "+" : line.type === "del" ? "−" : " ";
panel.appendChild(el("div", "diff-line " + kind + (line.conflicted ? " conflict" : ""),
el("span", "ln", line.oldLineNumber == null ? "" : String(line.oldLineNumber)),
el("span", "ln", line.newLineNumber == null ? "" : String(line.newLineNumber)),
el("span", "sign", sign), el("span", "code", line.text), meta));
});
panel.appendChild(el("div", "review-notes",
"Actor means a Quilt session or subagent, not necessarily a person or a single prompt. Prompt matches are inferred by time. " +
"Local prompts are read only when this panel opens and never leave this server. Claude Code and Codex transcripts are supported; other actors remain per-agent only. Unattributed lines can be legitimate."));
}
function loadReview(path, panel) {
if (REVIEW_CACHE[path]) {
renderReviewData(REVIEW_CACHE[path], panel);
return;
}
panel.replaceChildren(el("div", "review-state", "Loading local provenance…"));
fetch("/api/blame?path=" + encodeURIComponent(path)).then(function (r) {
if (!r.ok) throw new Error("http " + r.status);
return r.json();
}).then(function (d) {
REVIEW_CACHE[path] = d;
if (OPEN_REVIEWS[path]) renderReviewData(d, panel);
}).catch(function () {
panel.replaceChildren(el("div", "review-state", "Could not load this review."));
});
}
function render(d) {

@@ -345,3 +448,22 @@ document.getElementById("repo").textContent = "· " + d.repo;

if (f.binary) badges.appendChild(badge("binary", "binary"));
table.appendChild(el("tr", null, el("td", "path", f.path), authors, badges));
var toggle = el("button", "review-toggle" + (OPEN_REVIEWS[f.path] ? " open" : ""), f.path);
toggle.type = "button";
toggle.setAttribute("aria-expanded", OPEN_REVIEWS[f.path] ? "true" : "false");
var fileRow = el("tr", null, el("td", "path", toggle), authors, badges);
table.appendChild(fileRow);
var reviewCell = el("td", "review-cell");
reviewCell.colSpan = 3;
var reviewPanel = el("div", "review");
reviewCell.appendChild(reviewPanel);
var reviewRow = el("tr", null, reviewCell);
reviewRow.hidden = !OPEN_REVIEWS[f.path];
table.appendChild(reviewRow);
toggle.addEventListener("click", function () {
OPEN_REVIEWS[f.path] = !OPEN_REVIEWS[f.path];
reviewRow.hidden = !OPEN_REVIEWS[f.path];
toggle.classList.toggle("open", OPEN_REVIEWS[f.path]);
toggle.setAttribute("aria-expanded", OPEN_REVIEWS[f.path] ? "true" : "false");
if (OPEN_REVIEWS[f.path]) loadReview(f.path, reviewPanel);
});
if (OPEN_REVIEWS[f.path]) loadReview(f.path, reviewPanel);
});

@@ -348,0 +470,0 @@ var wrap = el("div", "card", table);

+1
-1
{
"name": "@quilt-dev/cli",
"version": "0.5.0",
"version": "0.5.1",
"mcpName": "io.github.wkoverfield/quilt",

@@ -5,0 +5,0 @@ "description": "Actor-owned patches for Git. Same repo. Many agents. Clean commits.",

// Sanity-check granted symbol claims against the file's actual symbols, so a
// typo'd target (`utils.js#formatPirce`) doesn't silently reserve nothing —
// the claimant walks away believing the real function is protected when no
// edit-time check will ever match it.
//
// Warnings, not denials: claiming a symbol you are ABOUT to add is a
// legitimate move (reserve the name before writing the function), so a missing
// symbol can't be an error. The warning tells the actor what Quilt can see and
// suggests a near-miss when one exists.
import { existsSync, readFileSync } from "node:fs";
import { safeAbs } from "./authorship.js";
import { canParse, parseSymbols } from "./symbols.js";
/**
* Warnings for granted symbol claims whose symbol isn't in the file. Quiet for
* whole-file claims, denied claims, files that don't exist yet (creating a file
* is exactly when you'd pre-claim its symbols), and languages Quilt can't parse
* (no symbol list to check against — the claim still works whole-file-wise).
*/
export function verifyClaimTargets(store, results) {
const warnings = [];
for (const r of results) {
if (!r.granted || !r.symbol)
continue;
const abs = safeAbs(store.paths.repoRoot, r.path);
if (!abs || !existsSync(abs) || !canParse(r.path))
continue;
let names;
try {
names = parseSymbols(r.path, readFileSync(abs, "utf8")).map((s) => s.name);
}
catch {
continue; // unreadable/unparseable — nothing to check against
}
if (names.includes(r.symbol))
continue;
const near = closest(r.symbol, names);
warnings.push({
target: `${r.path}#${r.symbol}`,
message: `symbol "${r.symbol}" not found in ${r.path}` +
(near ? ` — did you mean "${near}"?` : "") +
` (claim granted anyway — fine if you're about to add it)`,
});
}
return warnings;
}
/** The nearest existing symbol within a small edit distance, or null. */
function closest(target, names) {
let best = null;
let bestDist = 3; // only suggest genuinely-close names (distance <= 2)
for (const n of names) {
const d = editDistance(target.toLowerCase(), n.toLowerCase(), bestDist);
if (d < bestDist) {
bestDist = d;
best = n;
}
}
return best;
}
/** Levenshtein distance, capped: returns `cap` when the true distance is >= cap. */
function editDistance(a, b, cap) {
if (Math.abs(a.length - b.length) >= cap)
return cap;
let prev = Array.from({ length: b.length + 1 }, (_, i) => i);
for (let i = 1; i <= a.length; i++) {
const cur = [i];
let rowMin = i;
for (let j = 1; j <= b.length; j++) {
const d = Math.min((prev[j] ?? cap) + 1, (cur[j - 1] ?? cap) + 1, (prev[j - 1] ?? cap) + (a[i - 1] === b[j - 1] ? 0 : 1));
cur[j] = d;
rowMin = Math.min(rowMin, d);
}
if (rowMin >= cap)
return cap;
prev = cur;
}
return Math.min(prev[b.length] ?? cap, cap);
}

Sorry, the diff of this file is too big to display