@fringetools/cli 0.1.1 → 0.1.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/README.md CHANGED
@@ -27,7 +27,7 @@ Prefer a permanent command? `npm install -D @fringetools/cli`, then `npx fringe
27
27
  | `fringe check --hook` | One-line `fringe/hook.v1` JSON for CI / pre-commit. Exits `1` on errors. Claude Code does **not** feed this back — use `--claude-hook` for agents. Wins over `--json`. |
28
28
  | `fringe check --update-baseline` | Accept today's findings into `fringe.baseline.json` (commit it). Exit `0`. |
29
29
  | `fringe check --record [--manifest <path>]` | Also append this run to `.fringe/ledger.jsonl`, optionally merging an agent flow manifest. |
30
- | `fringe init [path]` | Add the Claude Code hook and install the three skills. Safe to re-run; refuses to touch an invalid `settings.json`. |
30
+ | `fringe init [path]` | Add the Claude Code hook and install the five skills. Safe to re-run; refuses to touch an invalid `settings.json`. |
31
31
  | `fringe open [path] [--port <n>]` | Serve the ledger as a plain HTML page on `127.0.0.1:4173` (loopback only). Ctrl+C to stop. |
32
32
  | `fringe --help` · `--version` | Usage / version. |
33
33
 
@@ -101,7 +101,7 @@ After each edit the hook runs; with errors it returns, for example:
101
101
 
102
102
  This was verified end to end with real agent runs: the agent receives the findings and fixes them (see [docs/architecture.md](../../docs/architecture.md)). Why `--claude-hook` and not `--hook`: Claude Code only passes a hook's output to the agent as `decision`/`reason` JSON on exit 0 (or stderr on exit 2); the CI contract `--hook` exits 1 and is ignored.
103
103
 
104
- **Skills** — `fringe init` installs three into `.claude/skills/` (sources in [skill/](skill/)): `fringe` (below), `fringe-review` ("review this page": runs the checker and reports ranked, plain-English findings with fixes; invoke as `/fringe-review`) and `fringe-audit` (whole-repo plan: top rules and files, a suggested fix order, offers `--update-baseline`; `/fringe-audit`). Reviews run `fringe check`, so Claude Code will ask you to approve that command once (or allow `Bash(fringe:*)` / `Bash(npx:*)`).
104
+ **Skills** — `fringe init` installs five into `.claude/skills/` (sources in [skill/](skill/), one folder each); the Claude Code plugin ships the same folders, namespaced `/fringe:…`: `fringe` (below), `fringe-review` ("review this page": ranked, plain-English findings with fixes), `fringe-audit` (whole-repo plan: top rules and files, a fix order, offers `--update-baseline`), `fringe-debt` (lists `fringe-ignore` suppressions and the baseline) and `fringe-help` (quick reference). Invoke as `/fringe-review` etc. Reviews run `fringe check`, so Claude Code will ask you to approve that command once (or allow `Bash(fringe:*)` / `Bash(npx:*)`).
105
105
 
106
106
  **The main skill** (`.claude/skills/fringe/SKILL.md`) teaches the agent the ladder: *Flow* (cut what users don't need, with evidence in `.fringe/manifest.json`) → *Edges* (fix every hook finding, never silence a rule to get green) → *Polish* (tokens, scales, no AI look), then record the run. It is plain Markdown, so any agent platform that reads `AGENTS.md`/skill files can use it as-is.
107
107
 
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "./chunk-W23H5MXS.js";
4
+ } from "./chunk-MOTRTP2I.js";
5
5
 
6
6
  // src/bin.ts
7
7
  process.exitCode = await runCli(process.argv.slice(2));
@@ -4,7 +4,7 @@ import { readFileSync as readFileSync8 } from "fs";
4
4
  import { resolve } from "path";
5
5
 
6
6
  // src/version.ts
7
- var VERSION = "0.1.0";
7
+ var VERSION = "0.1.3";
8
8
 
9
9
  // src/check.ts
10
10
  import { readFileSync as readFileSync5 } from "fs";
@@ -293,7 +293,11 @@ var fr206 = {
293
293
  severity: "error",
294
294
  check: (ctx) => {
295
295
  const out = [];
296
- for (const e of ctx.elems.filter((el) => ["div", "span"].includes(el.tag) && (el.attrs.onClick ?? el.attrs.onclick) !== void 0 && el.attrs.role === void 0 && (el.attrs.tabIndex ?? el.attrs.tabindex) === void 0)) {
296
+ const isBackdrop = (i) => {
297
+ const next = ctx.elems[i + 1], me = ctx.elems[i];
298
+ return !!next && next.parentTag === me.tag && next.loc.line >= me.loc.line && (/^(alert)?dialog$/.test(next.attrs.role ?? "") || next.attrs["aria-modal"] === "true");
299
+ };
300
+ for (const e of ctx.elems.filter((el, i) => ["div", "span"].includes(el.tag) && (el.attrs.onClick ?? el.attrs.onclick) !== void 0 && el.attrs.role === void 0 && (el.attrs.tabIndex ?? el.attrs.tabindex) === void 0 && !isBackdrop(i))) {
297
301
  out.push({ rule: "FR-206", severity: "error", message: `onClick on non-interactive <${e.tag}>`, hint: `use a <button>/<a> or add role and tabIndex`, loc: e.loc, wcag: "2.1.1" });
298
302
  }
299
303
  return out;
@@ -1186,12 +1190,11 @@ function startBoard(root, port) {
1186
1190
  }
1187
1191
 
1188
1192
  // src/init.ts
1189
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync7, writeFileSync as writeFileSync2, copyFileSync } from "fs";
1193
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync7, readdirSync as readdirSync3, writeFileSync as writeFileSync2, copyFileSync } from "fs";
1190
1194
  import { dirname, join as join7 } from "path";
1191
1195
  import { fileURLToPath } from "url";
1192
1196
  var HOOK = "npx -y @fringetools/cli check --claude-hook";
1193
- var SKILLS = { fringe: "SKILL.md", "fringe-review": "review.md", "fringe-audit": "audit.md" };
1194
- var skillSrc = (file) => fileURLToPath(new URL(`../skill/${file}`, import.meta.url));
1197
+ var SKILL_DIR = fileURLToPath(new URL("../skill/", import.meta.url));
1195
1198
  function initProject(root) {
1196
1199
  const done = [];
1197
1200
  const settingsPath = join7(root, ".claude", "settings.json");
@@ -1211,12 +1214,12 @@ function initProject(root) {
1211
1214
  writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + "\n");
1212
1215
  done.push(`hook added to ${settingsPath}`);
1213
1216
  }
1214
- for (const [name, file] of Object.entries(SKILLS)) {
1217
+ for (const name of readdirSync3(SKILL_DIR)) {
1215
1218
  const skillPath = join7(root, ".claude", "skills", name, "SKILL.md");
1216
1219
  if (existsSync2(skillPath)) done.push(`skill ${name} already present`);
1217
1220
  else {
1218
1221
  mkdirSync2(dirname(skillPath), { recursive: true });
1219
- copyFileSync(skillSrc(file), skillPath);
1222
+ copyFileSync(join7(SKILL_DIR, name, "SKILL.md"), skillPath);
1220
1223
  done.push(`skill ${name} installed`);
1221
1224
  }
1222
1225
  }
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runCli
3
- } from "./chunk-W23H5MXS.js";
3
+ } from "./chunk-MOTRTP2I.js";
4
4
  export {
5
5
  runCli
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fringetools/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: fringe-debt
3
+ description: Use when the user asks what Fringe findings have been silenced or deferred ("fringe debt", "what did we suppress", "what's in the baseline", /fringe-debt). One-shot report of suppressions and the baseline; changes nothing.
4
+ ---
5
+
6
+ # Fringe debt
7
+
8
+ Fringe has two ways to defer a finding: an inline `fringe-ignore` comment and the `fringe.baseline.json` file. This lists both so a deferral can't quietly become permanent.
9
+
10
+ Command: use `fringe` if it is on the PATH, otherwise `npx -y @fringetools/cli` in its place.
11
+
12
+ 1. **Inline suppressions.** `git grep --no-index --exclude-standard -nE 'fringe-ignore +FR-[0-9]+'`. One row per hit: `<file>:<line>, <rule> — <why, if the comment or nearby code says>`. Skip hits that are only prose mentioning the convention.
13
+ 2. **Baseline.** If `fringe.baseline.json` exists, count entries per rule (each entry is `rule|file|message`) and list the files with the most. If it is missing, say there is no baseline.
14
+ 3. **Today's picture.** Run `fringe check --json .` and report the current counts by severity next to the baseline total, so the user sees whether the debt is shrinking.
15
+ 4. Close with the single most valuable thing to pay down first (usually the rule with the most baselined entries that has a mechanical fix) and the command to shrink the baseline afterwards: `fringe check --update-baseline`.
16
+
17
+ Change nothing. Do not run `--update-baseline` unless the user asks.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: fringe-help
3
+ description: Use when the user asks what Fringe can do or how to use it ("fringe help", "what commands does fringe have", /fringe-help). Quick reference; changes nothing.
4
+ ---
5
+
6
+ # Fringe help
7
+
8
+ Fringe checks agent-written frontends for accessibility, state, dark-pattern and "AI look" problems, gates the hard failures, and keeps a local history.
9
+
10
+ **Skills**
11
+
12
+ | Skill | Use it to |
13
+ |---|---|
14
+ | `fringe` | The working rules: cut what users don't need, fix every hook finding, polish, record |
15
+ | `/fringe-review` | Review a page or component: ranked findings with plain-English fixes |
16
+ | `/fringe-audit` | Audit the whole repo: top rules and files, a fix order, offer a baseline |
17
+ | `/fringe-debt` | List silenced findings (`fringe-ignore`, baseline) |
18
+ | `/fringe-help` | This reference |
19
+
20
+ **Commands** (`fringe`, or `npx -y @fringetools/cli`)
21
+
22
+ | Command | What it does |
23
+ |---|---|
24
+ | `check [dir]` | Scan and print findings and the health score; exit 1 on any error |
25
+ | `check --json` / `--hook` / `--claude-hook` | Machine output; CI gate; agent feedback form |
26
+ | `check --update-baseline` | Accept today's findings; only new ones gate |
27
+ | `check --record [--manifest f]` | Append the run to `.fringe/ledger.jsonl` |
28
+ | `init` | Add the hook and install the skills |
29
+ | `open` | View the ledger at 127.0.0.1:4173 |
30
+
31
+ **Escape hatch:** `// fringe-ignore FR-203` on or above the line, for a real false positive only; every run reports `N suppressed`.
32
+
33
+ Full reference: https://github.com/skc-learn/fringe/blob/main/packages/cli/README.md
File without changes
File without changes
File without changes