pqcheck 0.16.18 → 0.16.19
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 +1 -1
- package/bin/cipherwake-statusline.js +46 -0
- package/bin/pqcheck.js +43 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
[](https://www.npmjs.com/package/pqcheck)
|
|
9
9
|
[](./LICENSE)
|
|
10
10
|
|
|
11
|
-
> **Latest: v0.16.
|
|
11
|
+
> **Latest: v0.16.19** — `pqcheck setup` now COMPOSES with an existing Claude Code `statusLine.command` (e.g., PinnedAI's) via a new `--prepend=<cmd>` flag on `cipherwake-statusline`. Both tools' badges render in the single statusLine slot. Previously, Cipherwake politely skipped if any prior statusLine existed — which meant you'd only ever see one tool's badge. Now: composed wrap with 5s timeout + graceful degradation on prepend failure + idempotent re-runs. [Full changelog →](./CHANGELOG.md)
|
|
12
12
|
|
|
13
13
|
## Two ways to use it
|
|
14
14
|
|
|
@@ -21,10 +21,56 @@
|
|
|
21
21
|
import { readFileSync, existsSync } from "node:fs";
|
|
22
22
|
import { join, dirname } from "node:path";
|
|
23
23
|
import { homedir } from "node:os";
|
|
24
|
+
import { execSync } from "node:child_process";
|
|
24
25
|
|
|
25
26
|
const GLOBAL_STATE_FILE = join(homedir(), ".config", "cipherwake", "last-scan.json");
|
|
26
27
|
const STALE_THRESHOLD_HOURS = 24;
|
|
27
28
|
|
|
29
|
+
// v0.16.19 — `--prepend=<command>` flag for statusLine composition. Claude
|
|
30
|
+
// Code's `statusLine.command` only supports ONE command, which means two
|
|
31
|
+
// tools (e.g. Cipherwake + PinnedAI) both writing their own statusLine
|
|
32
|
+
// silently clobber each other depending on install order. When a customer
|
|
33
|
+
// runs both, they only see whichever installed last. With --prepend, the
|
|
34
|
+
// Cipherwake binary runs the other tool's command first, joins its output
|
|
35
|
+
// with a separator, and renders Cipherwake's own line after. Result:
|
|
36
|
+
// `[pinned output] · ◆ Cipherwake · domain ✓ PASS · 5m ago` — both
|
|
37
|
+
// surfaces visible in the single statusLine slot.
|
|
38
|
+
//
|
|
39
|
+
// pqcheck setup detects an existing statusLine.command at install time
|
|
40
|
+
// and writes the wrapper form automatically:
|
|
41
|
+
// "command": "npx --package=pqcheck@latest cipherwake-statusline --prepend='<prior-command>'"
|
|
42
|
+
//
|
|
43
|
+
// If the prior command errors (or the tool was uninstalled), this binary
|
|
44
|
+
// swallows the failure and just renders Cipherwake's part — never causes
|
|
45
|
+
// the whole statusLine to break.
|
|
46
|
+
const PREPEND_SEPARATOR = " · ";
|
|
47
|
+
const prependArg = process.argv.find((a) => a.startsWith("--prepend="));
|
|
48
|
+
if (prependArg) {
|
|
49
|
+
const prependCmd = prependArg.slice("--prepend=".length);
|
|
50
|
+
if (prependCmd) {
|
|
51
|
+
try {
|
|
52
|
+
// 5s soft timeout — statusLine rendering must stay snappy. If the
|
|
53
|
+
// other tool hangs, we cut it off and continue with Cipherwake's part.
|
|
54
|
+
// stdio: ignore on stderr so a noisy prior tool doesn't pollute the
|
|
55
|
+
// bar; we want only its rendered stdout output.
|
|
56
|
+
const out = execSync(prependCmd, {
|
|
57
|
+
encoding: "utf8",
|
|
58
|
+
timeout: 5_000,
|
|
59
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
60
|
+
env: process.env,
|
|
61
|
+
}).trim();
|
|
62
|
+
if (out) {
|
|
63
|
+
process.stdout.write(out);
|
|
64
|
+
process.stdout.write(PREPEND_SEPARATOR);
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
// Prepend command failed (uninstalled, timeout, errored). Skip
|
|
68
|
+
// silently — never break the whole statusLine because of a
|
|
69
|
+
// composition partner.
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
28
74
|
// v0.16.6 — project-aware state lookup. Walk up from CWD looking for a
|
|
29
75
|
// repo-local `.cipherwake/last-scan.json`. This way each project shows
|
|
30
76
|
// its own last scan, and switching projects doesn't bleed the previous
|
package/bin/pqcheck.js
CHANGED
|
@@ -6317,19 +6317,54 @@ async function runSetupCommand(args) {
|
|
|
6317
6317
|
settings = JSON.parse(raw);
|
|
6318
6318
|
existed = true;
|
|
6319
6319
|
} catch { /* will create */ }
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6320
|
+
// v0.16.19 — statusLine composition. Previous behavior was: if any
|
|
6321
|
+
// statusLine.command already existed, SKIP. That was safe (never
|
|
6322
|
+
// clobbered other tools) but invisible — a user with PinnedAI's
|
|
6323
|
+
// statusline installed would never see Cipherwake's after running
|
|
6324
|
+
// `pqcheck setup`. Now: detect the prior command and wrap it via
|
|
6325
|
+
// `cipherwake-statusline --prepend=<prior>` so both render in the
|
|
6326
|
+
// single statusLine slot. The prepend logic in cipherwake-statusline.js
|
|
6327
|
+
// swallows prepend-command failures silently, so this composition
|
|
6328
|
+
// survives the user later uninstalling the partner tool.
|
|
6329
|
+
//
|
|
6330
|
+
// Skip the wrap when the existing command IS already our wrapper
|
|
6331
|
+
// (idempotent re-install — don't recursively nest).
|
|
6332
|
+
const CIPHERWAKE_CMD_PREFIX = "npx --package=pqcheck@latest cipherwake-statusline";
|
|
6333
|
+
const priorCmd = (existed && settings.statusLine && typeof settings.statusLine === "object")
|
|
6334
|
+
? String(settings.statusLine.command || "").trim()
|
|
6335
|
+
: "";
|
|
6336
|
+
const priorIsOurs = priorCmd.startsWith("npx --package=pqcheck") && priorCmd.includes("cipherwake-statusline");
|
|
6337
|
+
|
|
6338
|
+
if (priorIsOurs) {
|
|
6339
|
+
console.log(color("dim", ` ⊝ ${displayPath} statusLine already points at cipherwake-statusline — leaving alone`));
|
|
6340
|
+
installSummary.push({ component: "Claude Code statusLine", path: settingsPath, status: "skipped-already-ours" });
|
|
6325
6341
|
} else {
|
|
6326
6342
|
const backupPath = existed ? await backupSettingsJson(settingsPath) : null;
|
|
6327
6343
|
if (backupPath) console.log(color("dim", ` backup: ${backupPath}`));
|
|
6328
|
-
|
|
6344
|
+
let command;
|
|
6345
|
+
if (priorCmd) {
|
|
6346
|
+
// Compose: wrap the existing command via --prepend.
|
|
6347
|
+
// Single-quote the prior command + escape any single quotes
|
|
6348
|
+
// (rare in practice but defensive).
|
|
6349
|
+
const safe = priorCmd.replace(/'/g, `'\\''`);
|
|
6350
|
+
command = `${CIPHERWAKE_CMD_PREFIX} --prepend='${safe}'`;
|
|
6351
|
+
console.log(color("green", ` ✓ composed statusLine: existing command wrapped via --prepend → ${displayPath}`));
|
|
6352
|
+
console.log(color("dim", ` prior command: ${priorCmd.slice(0, 80)}${priorCmd.length > 80 ? "..." : ""}`));
|
|
6353
|
+
console.log(color("dim", ` both surfaces now render in the single statusLine slot`));
|
|
6354
|
+
} else {
|
|
6355
|
+
// Fresh install — no prior command to compose with.
|
|
6356
|
+
command = CIPHERWAKE_CMD_PREFIX;
|
|
6357
|
+
console.log(color("green", ` ✓ added statusLine config → ${displayPath}`));
|
|
6358
|
+
}
|
|
6359
|
+
settings.statusLine = { type: "command", command };
|
|
6329
6360
|
await fs.mkdir(path.dirname(settingsPath), { recursive: true });
|
|
6330
6361
|
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
6331
|
-
|
|
6332
|
-
|
|
6362
|
+
installSummary.push({
|
|
6363
|
+
component: "Claude Code statusLine",
|
|
6364
|
+
path: settingsPath,
|
|
6365
|
+
status: existed && priorCmd ? "installed-composed" : (existed ? "installed-updated" : "installed-created"),
|
|
6366
|
+
backup: backupPath,
|
|
6367
|
+
});
|
|
6333
6368
|
}
|
|
6334
6369
|
} catch (err) {
|
|
6335
6370
|
console.log(color("red", ` ✗ statusLine config install failed: ${err.message}`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pqcheck",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.19",
|
|
4
4
|
"description": "Deploy gate for AI-coded web apps. `pqcheck deploy-check --ai` returns ship_decision=pass|review|block for Claude Code / Cursor / Copilot / Aider to gate deploys before they ship. Anonymous, no signup, free for first use.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-coder",
|