@earntori/cli 0.2.20 → 0.2.21
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/index.js +43 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { readdirSync, realpathSync } from "node:fs";
|
|
|
4
4
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, appendFileSync, unlinkSync } from "node:fs";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { join, resolve, relative, isAbsolute, dirname } from "node:path";
|
|
7
|
-
import { execSync } from "node:child_process";
|
|
7
|
+
import { execSync, execFileSync } from "node:child_process";
|
|
8
8
|
import { createHash, createPublicKey, verify as edVerify } from "node:crypto";
|
|
9
9
|
const CONFIG_DIR = join(homedir(), ".tori");
|
|
10
10
|
const CONFIG = join(CONFIG_DIR, "config.json");
|
|
@@ -408,6 +408,35 @@ function formatRun(r, n) {
|
|
|
408
408
|
}
|
|
409
409
|
const dbg = (m) => { if (process.env.TORI_DEBUG)
|
|
410
410
|
console.error(`[tori ${new Date().toISOString().slice(11, 23)}] ${m}`); };
|
|
411
|
+
/** Spec rev 101 (fits in phase A3; extends rev 90): the lines of `path` that differ from the last commit, as
|
|
412
|
+
* line numbers in the working copy. "all" when the file has no committed version, and when git cannot answer
|
|
413
|
+
* (the behaviour before rev 101). */
|
|
414
|
+
const changedLinesCache = new Map();
|
|
415
|
+
function changedLines(path) {
|
|
416
|
+
const hit = changedLinesCache.get(path);
|
|
417
|
+
if (hit)
|
|
418
|
+
return hit;
|
|
419
|
+
let v = "all";
|
|
420
|
+
try {
|
|
421
|
+
const git = (a) => execFileSync("git", a, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], maxBuffer: 16 * 1024 * 1024 });
|
|
422
|
+
if (git(["ls-tree", "--name-only", "HEAD", "--", path]).trim()) {
|
|
423
|
+
const diff = git(["diff", "--no-color", "--no-ext-diff", "--no-textconv", "-U0", "HEAD", "--", path]);
|
|
424
|
+
const s = new Set();
|
|
425
|
+
let hunks = 0;
|
|
426
|
+
for (const m of diff.matchAll(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm)) {
|
|
427
|
+
hunks++;
|
|
428
|
+
const start = Number(m[1]), n = m[2] === undefined ? 1 : Number(m[2]);
|
|
429
|
+
for (let i = 0; i < n; i++)
|
|
430
|
+
s.add(start + i);
|
|
431
|
+
}
|
|
432
|
+
if (hunks > 0 || !diff.trim())
|
|
433
|
+
v = s; // a diff with no readable hunks stays "all"
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
catch { }
|
|
437
|
+
changedLinesCache.set(path, v);
|
|
438
|
+
return v;
|
|
439
|
+
}
|
|
411
440
|
async function check() {
|
|
412
441
|
dbg("check: start");
|
|
413
442
|
if (has("reminder")) {
|
|
@@ -472,7 +501,12 @@ async function check() {
|
|
|
472
501
|
die(e.message);
|
|
473
502
|
}
|
|
474
503
|
const text = formatRun(r, files.length);
|
|
475
|
-
|
|
504
|
+
// Spec rev 101: in hook mode a turn is held only by findings on lines it changed. A finding with no line number
|
|
505
|
+
// holds, since it cannot be placed. Findings on other lines stay open on the record and are counted as older.
|
|
506
|
+
const held = hook ? r.findings.filter((f) => { if (!f.line)
|
|
507
|
+
return true; const c = changedLines(f.path); return c === "all" || c.has(f.line); }) : r.findings;
|
|
508
|
+
const older = r.findings.length - held.length;
|
|
509
|
+
const highs = held.filter((f) => f.severity === "high").length, meds = held.filter((f) => f.severity === "medium").length, lows = held.length - highs - meds;
|
|
476
510
|
if (hook) {
|
|
477
511
|
if (r.clean)
|
|
478
512
|
return;
|
|
@@ -480,9 +514,13 @@ async function check() {
|
|
|
480
514
|
console.log(`Tori: ${r.findings.length} finding(s) still open \u2014 run \`tori check\` to see them.`);
|
|
481
515
|
return;
|
|
482
516
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
517
|
+
const olderNote = older ? `Tori: ${older} older finding(s) open on lines this turn did not change \u2014 recorded, not blocking. Run \`tori check\` to see them.` : "";
|
|
518
|
+
if (highs === 0) {
|
|
519
|
+
if (olderNote)
|
|
520
|
+
console.log(olderNote);
|
|
521
|
+
return;
|
|
522
|
+
} // only high on a changed line blocks; medium/low are recorded and shown in status and at session start
|
|
523
|
+
console.error(formatRun({ ...r, findings: held }, files.length) + `\n\n${highs} high (blocking)${meds ? `, ${meds} medium` : ""}${lows ? `, ${lows} low` : ""} — medium and low are recorded and do not block.` + (olderNote ? `\n${olderNote}` : ""));
|
|
486
524
|
process.exit(2); // exit 2 = block the stop; stderr goes to the agent
|
|
487
525
|
}
|
|
488
526
|
out(r, text);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earntori/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.21",
|
|
4
4
|
"description": "Tori CLI — holds your coding agent to a standard: checks before it calls a task done, each finding with its fix, on a signed record you can verify offline.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|