jig-ui 0.17.0 → 0.17.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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.17.1
4
+
5
+ ### Fixed
6
+
7
+ - **The gate judges the critiques a session touched, not every critique.**
8
+ A spec for one page could not finish because another page's critique
9
+ predated 0.17.0, whose new rules that critique had never judged, and a
10
+ record the project had set aside still failed for screenshots it no longer
11
+ had. The gate now checks a critique with a file changed since the session
12
+ began, and the current spec's surface after `critique`. A folder whose name
13
+ starts with `_` is set aside and never judged. With no transcript, as when
14
+ the gate is run by hand, it checks every critique as before.
15
+
3
16
  ## 0.17.0
4
17
 
5
18
  Thirteen more tells of a generated page, ten of them caught by `check`, and a
package/dist/index.js CHANGED
@@ -6159,7 +6159,7 @@ async function ensureProbes(opts) {
6159
6159
  function critiquedSurfaces(projectRoot) {
6160
6160
  const root = join32(projectRoot, ".jig", "critique");
6161
6161
  if (!existsSync19(root)) return [];
6162
- return readdirSync12(root).filter((surface) => existsSync19(join32(root, surface, "screen.json")) || existsSync19(join32(root, surface, "code.json")));
6162
+ return readdirSync12(root).filter((surface) => !surface.startsWith("_") && (existsSync19(join32(root, surface, "screen.json")) || existsSync19(join32(root, surface, "code.json"))));
6163
6163
  }
6164
6164
 
6165
6165
  // src/probe/check.ts
@@ -6575,7 +6575,7 @@ function verifyVerdicts(opts) {
6575
6575
  }
6576
6576
 
6577
6577
  // src/commands/gate.ts
6578
- import { existsSync as existsSync24, mkdirSync as mkdirSync8, readdirSync as readdirSync15, readFileSync as readFileSync30, writeFileSync as writeFileSync7 } from "fs";
6578
+ import { existsSync as existsSync24, mkdirSync as mkdirSync8, readdirSync as readdirSync15, readFileSync as readFileSync30, statSync as statSync4, writeFileSync as writeFileSync7 } from "fs";
6579
6579
  import { createHash as createHash2 } from "crypto";
6580
6580
  import { join as join37 } from "path";
6581
6581
  var MAX_BLOCKS = 3;
@@ -6624,6 +6624,37 @@ function asksOwner(text) {
6624
6624
  return /\?(?=[\s)\]"'*_]|$)/.test(prose);
6625
6625
  }
6626
6626
  var ASKS_THE_OWNER = /* @__PURE__ */ new Set(["decide", "spec", "mockup"]);
6627
+ function sessionStart(transcriptPath) {
6628
+ if (!transcriptPath || !existsSync24(transcriptPath)) return void 0;
6629
+ try {
6630
+ for (const line of readFileSync30(transcriptPath, "utf8").split("\n")) {
6631
+ const m = /"timestamp"\s*:\s*"([^"]+)"/.exec(line);
6632
+ if (m) {
6633
+ const t = Date.parse(m[1]);
6634
+ if (!Number.isNaN(t)) return t;
6635
+ }
6636
+ }
6637
+ } catch {
6638
+ }
6639
+ return void 0;
6640
+ }
6641
+ function newestMtime(dir) {
6642
+ let newest = 0;
6643
+ for (const name of readdirSync15(dir, { withFileTypes: true })) {
6644
+ const path = join37(dir, name.name);
6645
+ newest = Math.max(newest, name.isDirectory() ? newestMtime(path) : statSync4(path).mtimeMs);
6646
+ }
6647
+ return newest;
6648
+ }
6649
+ function surfacesInPlay(root, command, transcriptPath) {
6650
+ const critiqueDir = join37(root, ".jig", "critique");
6651
+ if (!existsSync24(critiqueDir)) return [];
6652
+ const all = readdirSync15(critiqueDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("_") && !d.name.startsWith(".")).map((d) => d.name);
6653
+ const start = sessionStart(transcriptPath);
6654
+ if (start === void 0) return all;
6655
+ const current = command === "critique" ? /^\s*surface\s*:\s*(.+)$/im.exec(newestSpec(root)?.body.split(/^---\s*$/m)[1] ?? "")?.[1]?.trim().replace(/^["']|["']$/g, "") : void 0;
6656
+ return all.filter((s) => s === current || newestMtime(join37(critiqueDir, s)) >= start - 1e3);
6657
+ }
6627
6658
  function commandProblems(root, command) {
6628
6659
  const problems = [];
6629
6660
  const spec = newestSpec(root);
@@ -6715,7 +6746,7 @@ function gate(opts) {
6715
6746
  problems.push(...verdictGuard(root, command));
6716
6747
  const critiqueDir = join37(root, ".jig", "critique");
6717
6748
  if (existsSync24(critiqueDir)) {
6718
- for (const surface of readdirSync15(critiqueDir)) {
6749
+ for (const surface of surfacesInPlay(root, command, opts.input.transcript_path)) {
6719
6750
  const dir = join37(critiqueDir, surface);
6720
6751
  if (!existsSync24(join37(dir, "screen.json")) && !existsSync24(join37(dir, "code.json"))) continue;
6721
6752
  const v = verifyVerdicts({ projectRoot: root, surface });
@@ -6780,6 +6811,7 @@ function verdictGuard(root, command) {
6780
6811
  if (!existsSync24(critiqueDir)) return [];
6781
6812
  const problems = [];
6782
6813
  for (const surface of readdirSync15(critiqueDir)) {
6814
+ if (surface.startsWith("_")) continue;
6783
6815
  const dir = join37(critiqueDir, surface);
6784
6816
  const now = verdictChecksum(dir);
6785
6817
  if (!now) continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jig-ui",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
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",
@@ -1191,6 +1191,12 @@ blocking. It also refuses when a critique's verdict files changed after `critiqu
1191
1191
  wrote them, in a session that did not run `critique`: a fix is judged by the next
1192
1192
  review, never by the builder editing the last one.
1193
1193
 
1194
+ It judges the critiques this session touched: any with a file changed since the
1195
+ session began, and the current spec's surface when you ran `critique`. Another
1196
+ page's older critique does not hold you back. To set a critique aside for good,
1197
+ rename its folder with a leading underscore (`.jig/critique/_old-catalog`); the
1198
+ gate never judges it.
1199
+
1194
1200
  A warning you are sure is right as it stands, because the detector guessed and the
1195
1201
  guess is wrong here, is waived on its own line or the line above, in the file's
1196
1202
  comment syntax: `jig-allow <ID>: <why>`. The reason is what the user reads, so write