vigiles 12.4.0 → 12.6.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.
- package/dist/core/bash-effects.d.ts +44 -0
- package/dist/core/bash-effects.js +303 -0
- package/dist/hook.d.ts +2 -0
- package/dist/hook.js +5 -1
- package/package.json +1 -1
|
@@ -50,4 +50,48 @@ export declare function isReadOnlyBash(command: string): boolean;
|
|
|
50
50
|
* native `Bash(git:*)` glob (issue #30519) and a hand-written `grep` both miss.
|
|
51
51
|
*/
|
|
52
52
|
export declare function leafCommands(command: string): string[][];
|
|
53
|
+
/** A single simple command, normalized to its operation form. */
|
|
54
|
+
export interface NormalizedLeaf {
|
|
55
|
+
/** Head normalized to its basename, backslash-stripped: `/bin/rm`→`rm`, `\rm`→`rm`. */
|
|
56
|
+
readonly head: string;
|
|
57
|
+
/** `[head, ...args]` — every word quote-unwrapped and $HOME/~-canonicalized. */
|
|
58
|
+
readonly argv: readonly string[];
|
|
59
|
+
/** The normalized args (argv without the head). */
|
|
60
|
+
readonly args: readonly string[];
|
|
61
|
+
/**
|
|
62
|
+
* Canonical flag tokens present on this leaf. Short clusters are split
|
|
63
|
+
* (`-rf`→`r`,`f`) and each flag is recorded in BOTH short and long form via the
|
|
64
|
+
* alias table, so a caller can test `--force`/`-f` or `--no-verify`/`-n`
|
|
65
|
+
* uniformly. Long values are split on `=` (`--index-url=x`→`index-url`).
|
|
66
|
+
*/
|
|
67
|
+
readonly flags: ReadonlySet<string>;
|
|
68
|
+
/** True iff ANY of `names` is present in {@link flags} (short or long). */
|
|
69
|
+
hasFlag(...names: readonly string[]): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Command-level env-assignments that apply to THIS leaf, keyed by variable
|
|
72
|
+
* name → static value (empty string for a naked `NAME=`). Populated from both
|
|
73
|
+
* the mvdan leading `CallExpr.Assigns` (`PIP_INDEX_URL=… pip install …`) AND
|
|
74
|
+
* the `NAME=value` words consumed by an `env` wrapper (`env NPM_CONFIG_REGISTRY=… npm i`).
|
|
75
|
+
*
|
|
76
|
+
* These carry supply-chain / behavior-altering configuration (`PIP_INDEX_URL`,
|
|
77
|
+
* `NPM_CONFIG_REGISTRY`, …) that an argv-only extractor never sees because the
|
|
78
|
+
* assignment is not an argv word. A dynamic RHS (command substitution, non-HOME
|
|
79
|
+
* parameter) is recorded with value `null` — present but unresolved. */
|
|
80
|
+
readonly assigns: ReadonlyMap<string, string | null>;
|
|
81
|
+
/** True iff a command-level assignment for ANY of `names` is present (resolved or not). */
|
|
82
|
+
hasAssign(...names: readonly string[]): boolean;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Extract every simple command as a {@link NormalizedLeaf} — the operation-level
|
|
86
|
+
* twin of {@link leafCommands}. Same AST-backed structural coverage (a leaf nested
|
|
87
|
+
* in a pipeline / `&&` / subshell is still found), but each word is quote-unwrapped
|
|
88
|
+
* and $HOME-canonicalized, the head is reduced to its backslash-stripped basename,
|
|
89
|
+
* and flags are expanded to short+long canonical forms. A matcher built on this
|
|
90
|
+
* compares against the OPERATION rather than the surface tokens, so it is robust
|
|
91
|
+
* to quoting, interpreter path, backslash escaping, flag aliasing, and $HOME/~.
|
|
92
|
+
*
|
|
93
|
+
* Purely additive: reuses the same mvdan-sh parse, changes nothing above. Parse
|
|
94
|
+
* failure → []. A leaf with a dynamic head is skipped (can't be normalized).
|
|
95
|
+
*/
|
|
96
|
+
export declare function leafCommandsNormalized(command: string): NormalizedLeaf[];
|
|
53
97
|
//# sourceMappingURL=bash-effects.d.ts.map
|
|
@@ -27,6 +27,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
27
27
|
exports.classifyBashCommand = classifyBashCommand;
|
|
28
28
|
exports.isReadOnlyBash = isReadOnlyBash;
|
|
29
29
|
exports.leafCommands = leafCommands;
|
|
30
|
+
exports.leafCommandsNormalized = leafCommandsNormalized;
|
|
30
31
|
// mvdan-sh is a CJS package (GopherJS build) with no bundled TypeScript types.
|
|
31
32
|
// The project compiles to CommonJS (Node16, no "type":"module"), so plain
|
|
32
33
|
// require() works and is the idiomatic pattern here (see linters.ts).
|
|
@@ -433,4 +434,306 @@ function leafCommands(command) {
|
|
|
433
434
|
});
|
|
434
435
|
return out;
|
|
435
436
|
}
|
|
437
|
+
/**
|
|
438
|
+
* Known short↔long flag aliases. Deliberately small and operation-relevant:
|
|
439
|
+
* a caller always gates on the head (e.g. only treats `index-url` as supply-chain
|
|
440
|
+
* when the head is `pip`), so recording both forms unconditionally is safe.
|
|
441
|
+
*/
|
|
442
|
+
const SHORT_TO_LONG = {
|
|
443
|
+
f: "force",
|
|
444
|
+
n: "no-verify",
|
|
445
|
+
r: "recursive",
|
|
446
|
+
i: "index-url",
|
|
447
|
+
};
|
|
448
|
+
const LONG_TO_SHORT = {
|
|
449
|
+
force: "f",
|
|
450
|
+
"no-verify": "n",
|
|
451
|
+
recursive: "r",
|
|
452
|
+
"index-url": "i",
|
|
453
|
+
};
|
|
454
|
+
/**
|
|
455
|
+
* Reconstruct a Word's static text, unwrapping single/double quotes and
|
|
456
|
+
* canonicalizing `$HOME`/`${HOME}` to `~`. Returns null if the word contains a
|
|
457
|
+
* truly dynamic segment (command substitution, arithmetic, a non-HOME parameter)
|
|
458
|
+
* — such a word can't be soundly reduced to a literal operation token.
|
|
459
|
+
*/
|
|
460
|
+
function normalizeParts(parts) {
|
|
461
|
+
if (!parts)
|
|
462
|
+
return null;
|
|
463
|
+
let out = "";
|
|
464
|
+
for (const p of parts) {
|
|
465
|
+
const t = sh.syntax.NodeType(p);
|
|
466
|
+
if (t === "Lit" || t === "SglQuoted") {
|
|
467
|
+
out += p.Value ?? "";
|
|
468
|
+
}
|
|
469
|
+
else if (t === "DblQuoted") {
|
|
470
|
+
const inner = normalizeParts(p.Parts);
|
|
471
|
+
if (inner === null)
|
|
472
|
+
return null;
|
|
473
|
+
out += inner;
|
|
474
|
+
}
|
|
475
|
+
else if (t === "ParamExp") {
|
|
476
|
+
// Canonicalize the home directory; any other parameter is dynamic.
|
|
477
|
+
if (p.Param?.Value === "HOME")
|
|
478
|
+
out += "~";
|
|
479
|
+
else
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
return null; // CmdSubst / ArithmExp / ProcSubst / … → dynamic
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return out;
|
|
487
|
+
}
|
|
488
|
+
/** Normalize a command head to its basename, stripping one leading backslash. */
|
|
489
|
+
function normalizeHead(raw) {
|
|
490
|
+
const unescaped = raw.startsWith("\\") ? raw.slice(1) : raw;
|
|
491
|
+
const slash = unescaped.lastIndexOf("/");
|
|
492
|
+
return slash >= 0 ? unescaped.slice(slash + 1) : unescaped;
|
|
493
|
+
}
|
|
494
|
+
/** Build the canonical flag set for a leaf's args (short-cluster + alias expansion). */
|
|
495
|
+
function buildFlags(args) {
|
|
496
|
+
const flags = new Set();
|
|
497
|
+
const add = (name) => {
|
|
498
|
+
if (!name)
|
|
499
|
+
return;
|
|
500
|
+
flags.add(name);
|
|
501
|
+
if (name.length === 1 && SHORT_TO_LONG[name])
|
|
502
|
+
flags.add(SHORT_TO_LONG[name]);
|
|
503
|
+
const short = LONG_TO_SHORT[name];
|
|
504
|
+
if (short)
|
|
505
|
+
flags.add(short);
|
|
506
|
+
};
|
|
507
|
+
for (const a of args) {
|
|
508
|
+
if (a.startsWith("--")) {
|
|
509
|
+
add(a.slice(2).split("=")[0] ?? "");
|
|
510
|
+
}
|
|
511
|
+
else if (a.length > 1 && a[0] === "-") {
|
|
512
|
+
for (const ch of a.slice(1)) {
|
|
513
|
+
if (/[a-zA-Z]/.test(ch))
|
|
514
|
+
add(ch);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return flags;
|
|
519
|
+
}
|
|
520
|
+
// ---------------------------------------------------------------------------
|
|
521
|
+
// Command-wrapper stripping.
|
|
522
|
+
//
|
|
523
|
+
// A wrapper is a command whose JOB is to run ANOTHER command: `env FOO=bar CMD`,
|
|
524
|
+
// `command CMD`, `sudo CMD`, `nice -n5 CMD`, `timeout 5 CMD`, `xargs CMD`,
|
|
525
|
+
// `nohup CMD`. Because the normalized leaf keys on the leaf HEAD, a wrapper head
|
|
526
|
+
// hides the real operation — `env GIT_SSH= git push --force` and `command rm -rf /`
|
|
527
|
+
// look like `env`/`command` leaves, so a head-keyed matcher never sees the
|
|
528
|
+
// `git push --force` / `rm -rf /` it must block. We resolve THROUGH the wrapper:
|
|
529
|
+
// skip the wrapper's own options (and their values) and any `NAME=value` words it
|
|
530
|
+
// consumes, then treat the next word as the real command head (recursing so
|
|
531
|
+
// `sudo timeout 5 rm -rf /` unwraps fully). A wrapper with no following command
|
|
532
|
+
// (bare `env`, `env -i`) is preserved as-is, so the env-dump predicate still fires.
|
|
533
|
+
// ---------------------------------------------------------------------------
|
|
534
|
+
const WRAPPER_HEADS = new Set([
|
|
535
|
+
"env",
|
|
536
|
+
"command",
|
|
537
|
+
"nice",
|
|
538
|
+
"timeout",
|
|
539
|
+
"sudo",
|
|
540
|
+
"xargs",
|
|
541
|
+
"nohup",
|
|
542
|
+
]);
|
|
543
|
+
/**
|
|
544
|
+
* Per-wrapper short/long options that consume a SEPARATE following token as their
|
|
545
|
+
* value (so the value is not mistaken for the wrapped command). Attached forms
|
|
546
|
+
* (`-n5`, `--kill-after=5`) are single tokens and need no entry.
|
|
547
|
+
*/
|
|
548
|
+
const WRAPPER_VALUE_OPTS = {
|
|
549
|
+
env: new Set(["-u", "--unset", "-C", "--chdir", "-S", "--split-string"]),
|
|
550
|
+
command: new Set(),
|
|
551
|
+
nice: new Set(["-n", "--adjustment"]),
|
|
552
|
+
timeout: new Set(["-s", "--signal", "-k", "--kill-after"]),
|
|
553
|
+
sudo: new Set([
|
|
554
|
+
"-u",
|
|
555
|
+
"--user",
|
|
556
|
+
"-g",
|
|
557
|
+
"--group",
|
|
558
|
+
"-p",
|
|
559
|
+
"--prompt",
|
|
560
|
+
"-C",
|
|
561
|
+
"--close-from",
|
|
562
|
+
"-h",
|
|
563
|
+
"--host",
|
|
564
|
+
"-r",
|
|
565
|
+
"--role",
|
|
566
|
+
"-t",
|
|
567
|
+
"--type",
|
|
568
|
+
"-U",
|
|
569
|
+
"--other-user",
|
|
570
|
+
"-R",
|
|
571
|
+
"--chroot",
|
|
572
|
+
"-D",
|
|
573
|
+
"--chdir",
|
|
574
|
+
]),
|
|
575
|
+
xargs: new Set([
|
|
576
|
+
"-I",
|
|
577
|
+
"-i",
|
|
578
|
+
"--replace",
|
|
579
|
+
"-n",
|
|
580
|
+
"--max-args",
|
|
581
|
+
"-P",
|
|
582
|
+
"--max-procs",
|
|
583
|
+
"-d",
|
|
584
|
+
"--delimiter",
|
|
585
|
+
"-E",
|
|
586
|
+
"-e",
|
|
587
|
+
"--eof",
|
|
588
|
+
"-s",
|
|
589
|
+
"--max-chars",
|
|
590
|
+
"-L",
|
|
591
|
+
"-l",
|
|
592
|
+
"--max-lines",
|
|
593
|
+
"-a",
|
|
594
|
+
"--arg-file",
|
|
595
|
+
]),
|
|
596
|
+
nohup: new Set(),
|
|
597
|
+
};
|
|
598
|
+
/** Count of leading NON-option positionals a wrapper consumes before the command (timeout DURATION). */
|
|
599
|
+
const WRAPPER_SKIP_POSITIONALS = {
|
|
600
|
+
timeout: 1,
|
|
601
|
+
};
|
|
602
|
+
/** True iff a normalized word is a `NAME=value` env-assignment (used by `env`). */
|
|
603
|
+
function isAssignmentWord(word) {
|
|
604
|
+
return /^[A-Za-z_][A-Za-z0-9_]*=/.test(word);
|
|
605
|
+
}
|
|
606
|
+
/** Split a `NAME=value` word into its name and value. */
|
|
607
|
+
function splitAssignmentWord(word) {
|
|
608
|
+
const eq = word.indexOf("=");
|
|
609
|
+
return [word.slice(0, eq), word.slice(eq + 1)];
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Resolve a wrapped command through one or more wrapper layers. Given a leaf's
|
|
613
|
+
* full normalized argv (`[head, ...args]`), returns the effective argv of the
|
|
614
|
+
* REAL command plus any `NAME=value` words an `env` wrapper consumed (so the
|
|
615
|
+
* caller can fold them into the leaf's assignment map). If the head is not a
|
|
616
|
+
* wrapper, or the wrapper has no following command, the argv is returned
|
|
617
|
+
* unchanged with an empty assignment set.
|
|
618
|
+
*/
|
|
619
|
+
function stripWrappers(argv) {
|
|
620
|
+
const envAssigns = new Map();
|
|
621
|
+
let cur = argv;
|
|
622
|
+
for (let guard = 0; guard < 8; guard++) {
|
|
623
|
+
const head = cur[0];
|
|
624
|
+
if (head === undefined || !WRAPPER_HEADS.has(head))
|
|
625
|
+
break;
|
|
626
|
+
const valueOpts = WRAPPER_VALUE_OPTS[head] ?? new Set();
|
|
627
|
+
let positionalsToSkip = WRAPPER_SKIP_POSITIONALS[head] ?? 0;
|
|
628
|
+
let i = 1; // start after the wrapper head
|
|
629
|
+
let ended = false;
|
|
630
|
+
for (; i < cur.length; i++) {
|
|
631
|
+
const a = cur[i];
|
|
632
|
+
if (a === undefined)
|
|
633
|
+
break;
|
|
634
|
+
if (a === "--") {
|
|
635
|
+
i++;
|
|
636
|
+
ended = true;
|
|
637
|
+
break;
|
|
638
|
+
}
|
|
639
|
+
if (a.length > 1 && a.startsWith("-")) {
|
|
640
|
+
if (valueOpts.has(a))
|
|
641
|
+
i++; // skip this option's separate value too
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
if (head === "env" && isAssignmentWord(a)) {
|
|
645
|
+
const [name, value] = splitAssignmentWord(a);
|
|
646
|
+
envAssigns.set(name, value);
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
if (positionalsToSkip > 0) {
|
|
650
|
+
positionalsToSkip--;
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
break; // cur[i] is the real command head
|
|
654
|
+
}
|
|
655
|
+
void ended;
|
|
656
|
+
if (i >= cur.length)
|
|
657
|
+
break; // wrapper with no following command → keep as-is
|
|
658
|
+
const next = cur.slice(i);
|
|
659
|
+
if (next.length === cur.length)
|
|
660
|
+
break; // no progress → stop
|
|
661
|
+
cur = next;
|
|
662
|
+
}
|
|
663
|
+
return { argv: cur, envAssigns };
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Extract every simple command as a {@link NormalizedLeaf} — the operation-level
|
|
667
|
+
* twin of {@link leafCommands}. Same AST-backed structural coverage (a leaf nested
|
|
668
|
+
* in a pipeline / `&&` / subshell is still found), but each word is quote-unwrapped
|
|
669
|
+
* and $HOME-canonicalized, the head is reduced to its backslash-stripped basename,
|
|
670
|
+
* and flags are expanded to short+long canonical forms. A matcher built on this
|
|
671
|
+
* compares against the OPERATION rather than the surface tokens, so it is robust
|
|
672
|
+
* to quoting, interpreter path, backslash escaping, flag aliasing, and $HOME/~.
|
|
673
|
+
*
|
|
674
|
+
* Purely additive: reuses the same mvdan-sh parse, changes nothing above. Parse
|
|
675
|
+
* failure → []. A leaf with a dynamic head is skipped (can't be normalized).
|
|
676
|
+
*/
|
|
677
|
+
function leafCommandsNormalized(command) {
|
|
678
|
+
let file;
|
|
679
|
+
try {
|
|
680
|
+
file = sh.syntax.NewParser().Parse(command, "cmd.sh");
|
|
681
|
+
}
|
|
682
|
+
catch {
|
|
683
|
+
return [];
|
|
684
|
+
}
|
|
685
|
+
const out = [];
|
|
686
|
+
sh.syntax.Walk(file, (node) => {
|
|
687
|
+
const leaf = normalizeCallExpr(node);
|
|
688
|
+
if (leaf)
|
|
689
|
+
out.push(leaf);
|
|
690
|
+
return true;
|
|
691
|
+
});
|
|
692
|
+
return out;
|
|
693
|
+
}
|
|
694
|
+
/** Collect a CallExpr's leading `NAME=value` env-assignments into a name→value map. */
|
|
695
|
+
function collectAssigns(node) {
|
|
696
|
+
const assigns = new Map();
|
|
697
|
+
for (const a of node.Assigns ?? []) {
|
|
698
|
+
const name = a.Name?.Value;
|
|
699
|
+
if (!name)
|
|
700
|
+
continue;
|
|
701
|
+
// A naked `NAME=` has no Value word → empty string; a dynamic RHS → null.
|
|
702
|
+
const value = a.Value ? normalizeParts(a.Value.Parts) : "";
|
|
703
|
+
assigns.set(name, value);
|
|
704
|
+
}
|
|
705
|
+
return assigns;
|
|
706
|
+
}
|
|
707
|
+
/** Normalize a single CallExpr node to a {@link NormalizedLeaf}, or null if it isn't one / has a dynamic head. */
|
|
708
|
+
function normalizeCallExpr(node) {
|
|
709
|
+
if (sh.syntax.NodeType(node) !== "CallExpr" || !node.Args?.length)
|
|
710
|
+
return null;
|
|
711
|
+
const headRaw = normalizeParts(node.Args[0]?.Parts);
|
|
712
|
+
if (headRaw === null)
|
|
713
|
+
return null; // dynamic head → not normalizable
|
|
714
|
+
const rawHead = normalizeHead(headRaw);
|
|
715
|
+
const rawArgs = node.Args.slice(1)
|
|
716
|
+
.map((w) => normalizeParts(w.Parts))
|
|
717
|
+
.filter((w) => w !== null);
|
|
718
|
+
// Resolve through any command-wrapper (`env`/`command`/`sudo`/`timeout`/…) so
|
|
719
|
+
// the leaf reflects the REAL operation, not the wrapper head.
|
|
720
|
+
const stripped = stripWrappers([rawHead, ...rawArgs]);
|
|
721
|
+
const head = normalizeHead(stripped.argv[0] ?? rawHead);
|
|
722
|
+
const args = stripped.argv.slice(1);
|
|
723
|
+
// Command-level assignments: mvdan leading `CallExpr.Assigns` plus any
|
|
724
|
+
// `NAME=value` words an `env` wrapper consumed on the way to the real command.
|
|
725
|
+
const assigns = collectAssigns(node);
|
|
726
|
+
for (const [k, v] of stripped.envAssigns)
|
|
727
|
+
assigns.set(k, v);
|
|
728
|
+
const flags = buildFlags(args);
|
|
729
|
+
return {
|
|
730
|
+
head,
|
|
731
|
+
argv: [head, ...args],
|
|
732
|
+
args,
|
|
733
|
+
flags,
|
|
734
|
+
hasFlag: (...names) => names.some((n) => flags.has(n)),
|
|
735
|
+
assigns,
|
|
736
|
+
hasAssign: (...names) => names.some((n) => assigns.has(n)),
|
|
737
|
+
};
|
|
738
|
+
}
|
|
436
739
|
//# sourceMappingURL=bash-effects.js.map
|
package/dist/hook.d.ts
CHANGED
|
@@ -49,4 +49,6 @@ export { defineHook, defineFileGate, definePromptGate, defineStopGate, tool, too
|
|
|
49
49
|
export type { Decision, HookMode, GateAction, CommandView, PathView, ResponseView, BashToolEvent, FileToolEvent, PromptEvent, StopEvent, ReactEvent, SessionEvent, HookProgram, FileGateHook, PromptGateHook, StopGateHook, InjectHook, ReactHook, AnyHook, DispatchKind, Injection, Reaction, RunReaction, CompiledHookProgram, CompileHookOptions, RawHookEvent, HookProgramOutcome, } from "./core/hook-program.js";
|
|
50
50
|
export { provide, dangerously, defineProvider, provider, } from "./core/hook-providers.js";
|
|
51
51
|
export type { ProviderName, ProviderResults, HookCtx, NeedSpec, InlineProvider, RegisteredProvider, RegisteredRef, ProviderRegistry, } from "./core/hook-providers.js";
|
|
52
|
+
export { leafCommandsNormalized } from "./core/bash-effects.js";
|
|
53
|
+
export type { NormalizedLeaf } from "./core/bash-effects.js";
|
|
52
54
|
//# sourceMappingURL=hook.d.ts.map
|
package/dist/hook.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.provider = exports.defineProvider = exports.dangerously = exports.provide = exports.HookCompileError = exports.verifyHookStamp = exports.stampHook = exports.checkHookImports = exports.compileHookProgram = exports.hookNeeds = exports.hookRouting = exports.dispatchKind = exports.decisionExitCode = exports.runHookProgram = exports.runReact = exports.runInject = exports.decideStopGate = exports.decidePromptGate = exports.decideFileGate = exports.decideProgram = exports.responseView = exports.nothing = exports.notice = exports.run = exports.defineReact = exports.inject = exports.defineInject = exports.hookMode = exports.gateAction = exports.pathView = exports.commandView = exports.ask = exports.deny = exports.allow = exports.tools = exports.tool = exports.defineStopGate = exports.definePromptGate = exports.defineFileGate = exports.defineHook = void 0;
|
|
3
|
+
exports.leafCommandsNormalized = exports.provider = exports.defineProvider = exports.dangerously = exports.provide = exports.HookCompileError = exports.verifyHookStamp = exports.stampHook = exports.checkHookImports = exports.compileHookProgram = exports.hookNeeds = exports.hookRouting = exports.dispatchKind = exports.decisionExitCode = exports.runHookProgram = exports.runReact = exports.runInject = exports.decideStopGate = exports.decidePromptGate = exports.decideFileGate = exports.decideProgram = exports.responseView = exports.nothing = exports.notice = exports.run = exports.defineReact = exports.inject = exports.defineInject = exports.hookMode = exports.gateAction = exports.pathView = exports.commandView = exports.ask = exports.deny = exports.allow = exports.tools = exports.tool = exports.defineStopGate = exports.definePromptGate = exports.defineFileGate = exports.defineHook = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* `vigiles/hook` — the **closed vocabulary** for authoring a compiled hook.
|
|
6
6
|
*
|
|
@@ -95,4 +95,8 @@ Object.defineProperty(exports, "provide", { enumerable: true, get: function () {
|
|
|
95
95
|
Object.defineProperty(exports, "dangerously", { enumerable: true, get: function () { return hook_providers_js_1.dangerously; } });
|
|
96
96
|
Object.defineProperty(exports, "defineProvider", { enumerable: true, get: function () { return hook_providers_js_1.defineProvider; } });
|
|
97
97
|
Object.defineProperty(exports, "provider", { enumerable: true, get: function () { return hook_providers_js_1.provider; } });
|
|
98
|
+
// Operation-normalized leaf extraction — the robust matching primitive a
|
|
99
|
+
// hardened guard is built on (see examples/harness/safe-bash-guard-v2.mjs).
|
|
100
|
+
var bash_effects_js_1 = require("./core/bash-effects.js");
|
|
101
|
+
Object.defineProperty(exports, "leafCommandsNormalized", { enumerable: true, get: function () { return bash_effects_js_1.leafCommandsNormalized; } });
|
|
98
102
|
//# sourceMappingURL=hook.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vigiles",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.6.0",
|
|
4
4
|
"description": "Lint & test the harness your AI agent runs on — verify the references in your CLAUDE.md / AGENTS.md and test that your hooks and skills actually work.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|