@hasna/hooks 0.10.8 → 0.11.0

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.
@@ -365,13 +365,13 @@ function segmentOperation(segment: string): Operation {
365
365
  const trimmed = segment.trim();
366
366
  if (!trimmed) return "read";
367
367
 
368
- if (/(?:^|\s)(?:rm|rmdir|unlink|shred|trash|rmtree|del)(?:\s|$)/.test(trimmed)) return "delete";
368
+ if (/(?:^|\s)\\?(?:[^\s;&|<>()]*\/)?(?:rm|rmdir|unlink|shred|trash|rmtree|del)(?:\s|$)/.test(trimmed)) return "delete";
369
369
  if (/\bgit\b/.test(trimmed)) {
370
370
  if (/\bgit\b[^;&|]*\b(?:clean|rm)\b/.test(trimmed)) return "delete";
371
371
  if (/\bgit\b[^;&|]*\b(?:clone|init)\b/.test(trimmed)) return "write";
372
372
  return "read";
373
373
  }
374
- if (/(?:^|\s)(?:mkdir|mkfile|touch|mv|cp|ln|tee|install|dd)(?:\s|$)/.test(trimmed)) return "write";
374
+ if (/(?:^|\s)\\?(?:[^\s;&|<>()]*\/)?(?:mkdir|mkfile|touch|mv|cp|ln|tee|install|dd)(?:\s|$)/.test(trimmed)) return "write";
375
375
  if (/\b(?:curl|wget)\b/.test(trimmed)) {
376
376
  if (WRITE_FLAGS.test(trimmed)) return "write";
377
377
  return "read";
@@ -586,8 +586,17 @@ export function bashTargets(command: string, home: string, cwd: string): PathTar
586
586
  // Operands after the command word. Options end at `--` or, as BSD
587
587
  // getopt does, at the first operand: every later word is an operand
588
588
  // even when it starts with `-`.
589
+ // A delete tool's subcommand word is not an operand: `trash put <path>`
590
+ // and `git [-C dir] rm|clean ...` act on the words after it.
591
+ let operandStart = 1;
592
+ const tool = (words[0]?.text ?? "").split("/").pop();
593
+ if (tool === "trash" && ["put", "rm", "delete", "remove"].includes(words[1]?.text ?? "")) operandStart = 2;
594
+ if (tool === "git") {
595
+ const sub = words.findIndex((word, index) => index > 0 && (word.text === "rm" || word.text === "clean"));
596
+ if (sub > 0) operandStart = sub + 1;
597
+ }
589
598
  let endOfOptions = false;
590
- const nonFlag = words.slice(1).flatMap((word) => {
599
+ const nonFlag = words.slice(operandStart).flatMap((word) => {
591
600
  if (!endOfOptions && word.text === "--") {
592
601
  endOfOptions = true;
593
602
  return [];
@@ -599,7 +608,7 @@ export function bashTargets(command: string, home: string, cwd: string): PathTar
599
608
  // mv changes its sources too, so every mv operand counts as a write.
600
609
  const everyOperand =
601
610
  stage.op === "delete" ||
602
- /(?:^|\s)(?:mkdir|mkfile|touch|tee|truncate|install|mv)(?:\s|$)/.test(stage.commandPart) ||
611
+ /(?:^|\s)\\?(?:[^\s;&|<>()]*\/)?(?:mkdir|mkfile|touch|tee|truncate|install|mv)(?:\s|$)/.test(stage.commandPart) ||
603
612
  (/(?:^|\s)sed(?:\s|$)/.test(stage.commandPart) && /(?:^|\s)(?:-i\S*|--in-place\S*)(?:\s|$)/.test(stage.commandPart));
604
613
  const operandTargets: Array<{ operand: string; op: Operation }> = [];
605
614
  if (everyOperand) {
@@ -0,0 +1,31 @@
1
+ import { handleReadinessSessionStart, isReadinessProvider, readinessSessionStartOutput } from "../src/native-readiness";
2
+
3
+ // This dedicated bundle never loads the generic Hooks registry or credentials.
4
+ // The native command verifies its bytes before evaluating this CommonJS entry.
5
+ async function main() {
6
+ const provider = process.argv[2];
7
+ if (!isReadinessProvider(provider)) {
8
+ process.stderr.write("Trash readiness needs attention (unsupported provider).\n");
9
+ process.exitCode = 1; return;
10
+ }
11
+ const invalid = () => readinessSessionStartOutput({ schema: "hasna.hooks.trash-readiness-result/v1",
12
+ provider, ready: false, code: "input_invalid", nativeAdoptionVerified: false });
13
+ try {
14
+ const input = await new Promise<Buffer>((accept, reject) => {
15
+ const chunks: Buffer[] = []; let size = 0;
16
+ const finish = (error?: Error) => {
17
+ clearTimeout(timer); process.stdin.pause(); process.stdin.removeAllListeners("data");
18
+ process.stdin.removeAllListeners("end"); process.stdin.removeAllListeners("error");
19
+ error ? reject(error) : accept(Buffer.concat(chunks));
20
+ };
21
+ const timer = setTimeout(() => finish(new Error()), 1000);
22
+ process.stdin.on("data", chunk => {
23
+ const bytes = Buffer.from(chunk); size += bytes.length;
24
+ if (size > 65_536) finish(new Error()); else chunks.push(bytes);
25
+ });
26
+ process.stdin.once("end", () => finish()); process.stdin.once("error", () => finish(new Error()));
27
+ });
28
+ process.stdout.write(JSON.stringify(await handleReadinessSessionStart(provider, JSON.parse(input.toString("utf8")))) + "\n");
29
+ } catch { process.stdout.write(JSON.stringify(invalid()) + "\n"); }
30
+ }
31
+ void main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/hooks",
3
- "version": "0.10.8",
3
+ "version": "0.11.0",
4
4
  "description": "Open source hooks library for AI coding agents - Install safety, quality, and automation hooks with a single command",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,6 +24,10 @@
24
24
  "./native-safety": {
25
25
  "types": "./dist/native-safety.d.ts",
26
26
  "import": "./dist/native-safety.js"
27
+ },
28
+ "./native-readiness": {
29
+ "types": "./dist/native-readiness.d.ts",
30
+ "import": "./dist/native-readiness.js"
27
31
  }
28
32
  },
29
33
  "main": "./dist/index.js",
@@ -41,7 +45,8 @@
41
45
  "postinstall": "node scripts/ensure-profiles-dir.mjs",
42
46
  "scan:artifact": "bun scripts/artifact-scan.ts",
43
47
  "prepack": "bun run build && bun run scan:artifact",
44
- "build:native-safety": "bun build ./hooks/native-safety-entry.ts --outdir ./bin --target bun --define import.meta.main=false && bun build ./src/native-safety.ts --outdir ./dist --target bun"
48
+ "build:native-safety": "bun build ./hooks/native-safety-entry.ts --outdir ./bin --target bun --define import.meta.main=false && bun build ./src/native-safety.ts --outdir ./dist --target bun && bun run build:native-readiness",
49
+ "build:native-readiness": "bun build ./hooks/native-readiness-entry.ts --outdir ./bin --target node --format=cjs && bun build ./src/native-readiness.ts --outdir ./dist --target bun"
45
50
  },
46
51
  "keywords": [
47
52
  "claude-code",