jig-ui 0.18.2 → 0.18.3
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/CHANGELOG.md +20 -0
- package/dist/index.js +49 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.18.3 (2026-09-25)
|
|
4
|
+
|
|
5
|
+
Recording a decision no longer undoes the critiques written before it, and an
|
|
6
|
+
older probe file says it is older rather than forged.
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- **A decision recorded after a critique no longer undoes it.** On jig-site one
|
|
11
|
+
`/jig decide` session added eight decisions; every finished critique turned
|
|
12
|
+
"incomplete", and the gate stopped an unrelated spec session over records that
|
|
13
|
+
could not have judged them. `jig verdicts` now asks git: a decision whose
|
|
14
|
+
heading was added in a commit the critique's `decisions.json` commit does not
|
|
15
|
+
contain, or not committed yet, is left for the next critique and listed as
|
|
16
|
+
such. Without git, or while `decisions.json` has uncommitted changes (a
|
|
17
|
+
critique in progress), every decision is still required.
|
|
18
|
+
- **An older probe file is called older, not forged.** After a release changed
|
|
19
|
+
the probe's version, the old files read "not output of `jig probe` … do not
|
|
20
|
+
write it by hand", and an agent stopped work believing they were fabricated.
|
|
21
|
+
They now say which version took them and to record them again.
|
|
22
|
+
|
|
3
23
|
## 0.18.2 (2026-09-25)
|
|
4
24
|
|
|
5
25
|
Every release in this changelog now carries its date and a one-line summary,
|
package/dist/index.js
CHANGED
|
@@ -5673,8 +5673,9 @@ Could not write to ${wireTarget}: ${err.message}`);
|
|
|
5673
5673
|
}
|
|
5674
5674
|
|
|
5675
5675
|
// src/commands/verdicts.ts
|
|
5676
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
5676
5677
|
import { existsSync as existsSync23, readFileSync as readFileSync30 } from "fs";
|
|
5677
|
-
import { join as join37, resolve as resolve5 } from "path";
|
|
5678
|
+
import { join as join37, relative as relative4, resolve as resolve5 } from "path";
|
|
5678
5679
|
|
|
5679
5680
|
// src/rules/citations.ts
|
|
5680
5681
|
import { join as join29 } from "path";
|
|
@@ -6258,6 +6259,10 @@ function readProbes(projectRoot, dir, errors) {
|
|
|
6258
6259
|
for (const f of readdirSync13(dir).filter((n) => /^probe-\d+\.json$/.test(n)).sort()) {
|
|
6259
6260
|
try {
|
|
6260
6261
|
const p = JSON.parse(readFileSync27(join34(dir, f), "utf8"));
|
|
6262
|
+
if (typeof p.jigProbe === "number" && p.jigProbe < PROBE_VERSION && typeof p.width === "number") {
|
|
6263
|
+
errors.push(`${f} was taken by an older \`jig probe\` (version ${p.jigProbe}; this Jig reads version ${PROBE_VERSION}). Record it again with \`jig probe --run\`.`);
|
|
6264
|
+
continue;
|
|
6265
|
+
}
|
|
6261
6266
|
if (p.jigProbe !== PROBE_VERSION || typeof p.width !== "number") {
|
|
6262
6267
|
errors.push(`${f} is not output of \`jig probe\` (version ${PROBE_VERSION}). Re-run the probe; do not write it by hand.`);
|
|
6263
6268
|
continue;
|
|
@@ -6366,21 +6371,24 @@ function decisionsFile(projectRoot) {
|
|
|
6366
6371
|
return void 0;
|
|
6367
6372
|
}
|
|
6368
6373
|
function decisionNames(projectRoot) {
|
|
6374
|
+
return [...decisionHeadings(projectRoot).keys()];
|
|
6375
|
+
}
|
|
6376
|
+
function decisionHeadings(projectRoot) {
|
|
6377
|
+
const headings = /* @__PURE__ */ new Map();
|
|
6369
6378
|
const path = decisionsFile(projectRoot);
|
|
6370
|
-
if (!path) return
|
|
6379
|
+
if (!path) return headings;
|
|
6371
6380
|
let body;
|
|
6372
6381
|
try {
|
|
6373
6382
|
body = readFileSync28(join35(projectRoot, path), "utf8");
|
|
6374
6383
|
} catch {
|
|
6375
|
-
return
|
|
6384
|
+
return headings;
|
|
6376
6385
|
}
|
|
6377
|
-
const names = [];
|
|
6378
6386
|
for (const match of body.matchAll(HEADING3)) {
|
|
6379
6387
|
const name = match[2].replace(/[`*]/g, "").trim();
|
|
6380
6388
|
if (!name || NOT_A_DECISION.test(name)) continue;
|
|
6381
|
-
if (!
|
|
6389
|
+
if (!headings.has(name)) headings.set(name, match[0].trim());
|
|
6382
6390
|
}
|
|
6383
|
-
return
|
|
6391
|
+
return headings;
|
|
6384
6392
|
}
|
|
6385
6393
|
|
|
6386
6394
|
// src/check/spec-shape.ts
|
|
@@ -6583,11 +6591,41 @@ function checkDecisions(projectRoot, dir, errors) {
|
|
|
6583
6591
|
else if (ABSENCE.test(reason)) errors.push(`decisions.json: "${match}" \u2014 "${reason}" says the decision was not read.`);
|
|
6584
6592
|
if (v.verdict === "finding") findings++;
|
|
6585
6593
|
}
|
|
6586
|
-
const
|
|
6594
|
+
const unjudged = required.filter((r) => !seen.has(r));
|
|
6595
|
+
const since = decisionsSince(projectRoot, dir, unjudged);
|
|
6596
|
+
const missing = unjudged.filter((r) => !since.includes(r));
|
|
6597
|
+
const total = required.length - since.length;
|
|
6587
6598
|
if (missing.length) {
|
|
6588
|
-
errors.push(`decisions.json: ${missing.length} of ${
|
|
6599
|
+
errors.push(`decisions.json: ${missing.length} of ${total} decisions have no verdict: ${missing.join(", ")}.`);
|
|
6600
|
+
}
|
|
6601
|
+
return { state: missing.length ? "incomplete" : "ran", judged: total - missing.length, total, findings, ...since.length ? { since } : {} };
|
|
6602
|
+
}
|
|
6603
|
+
function decisionsSince(projectRoot, dir, unjudged) {
|
|
6604
|
+
if (unjudged.length === 0) return [];
|
|
6605
|
+
const path = decisionsFile(projectRoot);
|
|
6606
|
+
if (!path) return [];
|
|
6607
|
+
const git = (args) => execFileSync3("git", args, { cwd: projectRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
6608
|
+
try {
|
|
6609
|
+
const verdictFile = relative4(projectRoot, join37(dir, "decisions.json"));
|
|
6610
|
+
if (git(["status", "--porcelain", "--", verdictFile])) return [];
|
|
6611
|
+
const judgedIn = git(["log", "-1", "--format=%H", "--", verdictFile]);
|
|
6612
|
+
if (!judgedIn) return [];
|
|
6613
|
+
const headings = decisionHeadings(projectRoot);
|
|
6614
|
+
return unjudged.filter((name) => {
|
|
6615
|
+
const line = headings.get(name);
|
|
6616
|
+
if (!line) return false;
|
|
6617
|
+
const addedIn = git(["log", "--format=%H", "-S", line, "--", path]).split("\n").filter(Boolean).pop();
|
|
6618
|
+
if (!addedIn) return true;
|
|
6619
|
+
try {
|
|
6620
|
+
git(["merge-base", "--is-ancestor", addedIn, judgedIn]);
|
|
6621
|
+
return false;
|
|
6622
|
+
} catch {
|
|
6623
|
+
return true;
|
|
6624
|
+
}
|
|
6625
|
+
});
|
|
6626
|
+
} catch {
|
|
6627
|
+
return [];
|
|
6589
6628
|
}
|
|
6590
|
-
return { state: missing.length ? "incomplete" : "ran", judged: required.length - missing.length, total: required.length, findings };
|
|
6591
6629
|
}
|
|
6592
6630
|
function verifyVerdicts(opts) {
|
|
6593
6631
|
const root = opts.packageRoot ?? assetRoot();
|
|
@@ -7120,6 +7158,8 @@ program.command("verdicts").description("Verify a critique's verdict files and c
|
|
|
7120
7158
|
const result = verifyVerdicts({ projectRoot, surface });
|
|
7121
7159
|
for (const error of result.errors) console.error(` \u2717 ${error}`);
|
|
7122
7160
|
if (result.ok) console.log(` Every rule in both passes has a verdict.`);
|
|
7161
|
+
const since = result.decisions.since ?? [];
|
|
7162
|
+
if (since.length) console.log(` ${since.length} decision(s) recorded after this critique, for the next one to judge: ${since.join(", ")}.`);
|
|
7123
7163
|
console.log(` ${result.line}`);
|
|
7124
7164
|
process.exit(result.ok ? 0 : 1);
|
|
7125
7165
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jig-ui",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.3",
|
|
4
4
|
"description": "A design system for coding agents. 143 numbered UI rules, brand x mode design tokens, and an installer for Claude Code, Codex, Cursor and opencode.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|