@rmyndharis/aimhooman 0.1.7 → 0.2.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +156 -0
- package/README.md +2 -1
- package/bin/aimhooman.mjs +473 -241
- package/package.json +1 -1
- package/rules/paths.json +65 -16
- package/rules/secrets.json +11 -7
- package/src/exclude.mjs +14 -0
- package/src/githooks.mjs +89 -9
- package/src/gitx.mjs +78 -6
- package/src/hook.mjs +79 -4
- package/src/report.mjs +71 -3
- package/src/scan-session.mjs +77 -1
- package/src/scan.mjs +40 -7
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,162 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.0] - 2026-07-19
|
|
9
|
+
|
|
10
|
+
This release works through the findings of the cross-ecosystem field test
|
|
11
|
+
(8 upstream clones, 6 language loops, a local bare remote, and a private
|
|
12
|
+
GitHub sandbox). The headline: `allow` no longer says yes when it means no —
|
|
13
|
+
a path allow on a file whose content holds a secret is refused up front,
|
|
14
|
+
with the working escape hatch named in the same breath.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Tracked-tree scans (`audit`, `check --tracked`, `init --grandfather-secrets`)
|
|
19
|
+
no longer die with `spawnSync git EPIPE` on a partial clone of a repository
|
|
20
|
+
with submodule pins. A gitlink names a commit of another repository, so
|
|
21
|
+
asking `cat-file` about it triggered a promisor fetch that aborted the
|
|
22
|
+
whole metadata batch ("not our ref"). Gitlinks now skip the metadata read;
|
|
23
|
+
their type comes from the mode. Found by the OpenSSL field run, whose 11
|
|
24
|
+
submodule pins made the grandfather flag seed zero allows.
|
|
25
|
+
- `init --grandfather-secrets` now runs its one-shot tracked scan with the
|
|
26
|
+
total-byte budget raised to the env cap and the finding budget raised to
|
|
27
|
+
100,000. The commit-time defaults (64 MiB, 1,000 findings) silently missed
|
|
28
|
+
fixtures beyond them in exactly the large, fixture-heavy repositories the
|
|
29
|
+
flag exists for; the per-file budget and an explicit env override still
|
|
30
|
+
apply.
|
|
31
|
+
- `aimhooman allow <path>` on a file whose content matches a secret rule
|
|
32
|
+
(e.g. a private key inside an ordinary-looking filename) no longer reports
|
|
33
|
+
`allowed` while the commit stays blocked. The guard now runs the engine's
|
|
34
|
+
secret content rules over the file's bytes, refuses the allow, and points
|
|
35
|
+
at `--scope secret-path`. Files over the scan budget or unreadable skip
|
|
36
|
+
the check; the commit-time scanner still fails closed on those.
|
|
37
|
+
- The scan-incomplete summary now names what was skipped
|
|
38
|
+
(`skipped: size-limit=1 file`) instead of `(size-limit=1)`, which read as
|
|
39
|
+
a one-byte budget rather than a count of files.
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- `aimhooman init --grandfather-secrets`: after a successful init, scan the
|
|
44
|
+
tracked tree once and write a `--scope secret-path` allow for every path
|
|
45
|
+
already tracking secret-looking material (test certs, sample keys). New
|
|
46
|
+
secrets stay blocked; only paths found in that scan are allowed. A failed
|
|
47
|
+
or incomplete scan warns without failing the init.
|
|
48
|
+
- Provider-token findings name the provider in human output
|
|
49
|
+
(`A provider access token (GitHub) must not enter Git history.`), so the
|
|
50
|
+
developer knows which credential to revoke. The token itself stays
|
|
51
|
+
redacted; the JSON report is unchanged.
|
|
52
|
+
- Secret content rules now carry a remediation line naming the fixture
|
|
53
|
+
escape hatch: `aimhooman allow <path> --scope secret-path --reason
|
|
54
|
+
"test fixture"`.
|
|
55
|
+
- The pre-commit hook now names locally-ignored AI artifacts once per set
|
|
56
|
+
change (`3 AI artifact(s) present locally are kept out of commits: ...`).
|
|
57
|
+
The prevention layer keeps them out of `git status`, which also kept their
|
|
58
|
+
exclusion silent: a `git add .` never told the developer the chat log did
|
|
59
|
+
not make the commit. The worktree walk is pathspec-pruned to the managed
|
|
60
|
+
exclude patterns, so it costs ~15ms; informational only, it never changes
|
|
61
|
+
an exit code.
|
|
62
|
+
- The reference-transaction veto now notes that the rejected commit object
|
|
63
|
+
remains in the local object store — collected by `git gc --prune=now` when
|
|
64
|
+
nothing else references it — so a secret payload is not mistaken for gone.
|
|
65
|
+
|
|
66
|
+
### Changed
|
|
67
|
+
|
|
68
|
+
- Repeated findings of the same rule print the remediation once, then
|
|
69
|
+
`fix: as above for <rule id>`, instead of reprinting an identical fix
|
|
70
|
+
block for every hit.
|
|
71
|
+
- `init` output now prints `undo: aimhooman uninstall` and notes that known
|
|
72
|
+
AI artifacts are ignored locally (`git status --ignored` shows them).
|
|
73
|
+
|
|
74
|
+
### Performance
|
|
75
|
+
|
|
76
|
+
- `openRepo` resolves the repository in one `git rev-parse` call instead of
|
|
77
|
+
three; every hook spawn pays this, so it was the cheapest milliseconds on
|
|
78
|
+
the commit path. The common-dir answer is resolved against the invoking
|
|
79
|
+
cwd and canonicalized, preserving the previous spelling on symlinked
|
|
80
|
+
paths (macOS `/tmp`), and a path containing a newline falls back to one
|
|
81
|
+
flag per call.
|
|
82
|
+
- The reference-transaction dispatcher exits before the Node spawn for a
|
|
83
|
+
`prepared` transaction that moves neither a branch nor HEAD (ORIG_HEAD,
|
|
84
|
+
tags, remote-tracking refs). Such payloads carry nothing `refcheck`
|
|
85
|
+
scans — but the skip first proves the four dispatchers are still
|
|
86
|
+
installed, so a hook manager wiping them mid-operation is answered with
|
|
87
|
+
a stop, not silence. An ordinary commit's hook time drops by roughly a
|
|
88
|
+
third in the field measurement (982ms → 649ms).
|
|
89
|
+
- Installed Git hook shims export `NODE_COMPILE_CACHE` pointing at a
|
|
90
|
+
per-install directory under the state dir (removed by
|
|
91
|
+
`uninstall --purge-state`), shaving the module parse/compile cost off
|
|
92
|
+
each hook spawn. An unwritable cache dir degrades to the old cold start,
|
|
93
|
+
never to a hook failure.
|
|
94
|
+
|
|
95
|
+
## [0.1.8] - 2026-07-18
|
|
96
|
+
|
|
97
|
+
This release works through the findings of the real-world scenario report
|
|
98
|
+
(191 scenarios across 11 repos, 8 languages). The headline: a read-only
|
|
99
|
+
command copied from `gh`'s own docs no longer gets denied, and editing an
|
|
100
|
+
unrelated line in a file that carries a private-key header elsewhere no
|
|
101
|
+
longer blocks the commit.
|
|
102
|
+
|
|
103
|
+
### Fixed
|
|
104
|
+
|
|
105
|
+
- Read-only commands with unquoted braces (`gh api repos/{owner}/{repo}/pulls`,
|
|
106
|
+
`ls {owner}`, `cp x.{js,ts}`) are no longer denied as opaque commit-hiding
|
|
107
|
+
pipelines. Brace expansion is argument-level and cannot feed code into a pipe
|
|
108
|
+
sink; brace groups (`{ list; }`) and PowerShell script blocks remain opaque.
|
|
109
|
+
The opaque-deny message also no longer names a pipe when the command has none.
|
|
110
|
+
- Editing an unrelated line in a file that contains a private-key header
|
|
111
|
+
elsewhere (e.g. a PEM fixture inside a Go test string) no longer blocks the
|
|
112
|
+
commit. Content scanning is now narrowed to the changed hunks; a header added
|
|
113
|
+
in the diff still blocks, a header carried outside the diff stays silent.
|
|
114
|
+
Binary blobs keep their whole-blob secret scan.
|
|
115
|
+
- AWS's documented example secret access key (`wJalrXUtnFEMI/...EXAMPLEKEY`)
|
|
116
|
+
no longer blocks commits. Its access-key-ID pair was already excepted; the
|
|
117
|
+
secret-key half now is too. Real keys — including ones containing `EXAMPLEKEY`
|
|
118
|
+
as a substring — still block.
|
|
119
|
+
- `aimhooman <subcommand> --help` now prints usage and exits 0 instead of
|
|
120
|
+
erroring on the unknown `--help` option.
|
|
121
|
+
- The human finding report renders every remediation entry (a rule's second
|
|
122
|
+
line, e.g. "rotate the key if it was ever exposed", was silently dropped), and
|
|
123
|
+
its summary line agrees on number (`1 finding`, not `1 findings`). A scan
|
|
124
|
+
firing many findings (a vendored OpenSSL corpus can produce 99) now caps the
|
|
125
|
+
printed blocks at 20 and collapses the rest into one truncation line; the JSON
|
|
126
|
+
report stays uncapped.
|
|
127
|
+
- The `secret.private-key` message now states the match is by filename, not by
|
|
128
|
+
content, and offers renaming the file when the name is coincidental.
|
|
129
|
+
- A chained hook predecessor that resolves sibling scripts via `$(dirname "$0")`
|
|
130
|
+
— the dominant husky and vanilla `.githooks` pattern — no longer breaks after
|
|
131
|
+
`aimhooman init`. The dispatcher now sources the predecessor in a subshell,
|
|
132
|
+
which preserves the original `$0`. (Bash-only predecessors remain out of
|
|
133
|
+
scope.)
|
|
134
|
+
|
|
135
|
+
### Changed
|
|
136
|
+
|
|
137
|
+
- **Breaking:** an untracked `core.hooksPath` inside the worktree (a freshly
|
|
138
|
+
created `.husky` before its first commit, a team-local `.team-hooks`) is now
|
|
139
|
+
treated as repository content and refuses to receive a dispatcher — the next
|
|
140
|
+
`git add` would otherwise stage the dispatcher's machine-local absolute CLI,
|
|
141
|
+
Node, and PATH into history. Add the path to `.gitignore` or
|
|
142
|
+
`.git/info/exclude` to keep it local; the refusal message names this and
|
|
143
|
+
points at `aimhooman uninstall`. A `.git/hooks/` path and a tracked `.husky`
|
|
144
|
+
are unaffected.
|
|
145
|
+
- `aimhooman review` advisories now persist per path across edits on the
|
|
146
|
+
`clean` and `compliance` profiles, so editing a reviewed agent-instruction
|
|
147
|
+
file (CLAUDE.md, AGENTS.md, `.github/copilot-instructions.md`) no longer
|
|
148
|
+
re-surfaces the review message on every edit. The `strict` profile keeps the
|
|
149
|
+
exact-blob binding unchanged; reviewed deletions (tombstones) keep it in every
|
|
150
|
+
profile.
|
|
151
|
+
- The `aimhooman init` refusal message names the two remedies (unset
|
|
152
|
+
`core.hooksPath`, or exclude the worktree path) and points at
|
|
153
|
+
`aimhooman uninstall`, so a refused init is no longer a dead end.
|
|
154
|
+
|
|
155
|
+
### Performance
|
|
156
|
+
|
|
157
|
+
- A commit no longer pays a duplicate tree scan in `commit-msg` for the staged
|
|
158
|
+
tree that `pre-commit` just verified. `pre-commit` records the staged tree sha
|
|
159
|
+
after a clean, complete scan; `commit-msg` skips its ~170 ms tree scan when the
|
|
160
|
+
sha matches. The marker is self-invalidating (any index mutation changes the
|
|
161
|
+
sha) and a missing/stale/mismatched marker falls back to the full scan, so
|
|
162
|
+
this is purely an optimization. Net ~150 ms saved per commit.
|
|
163
|
+
|
|
8
164
|
## [0.1.7] - 2026-07-18
|
|
9
165
|
|
|
10
166
|
### Fixed
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
11
11
|
<img src="https://img.shields.io/github/actions/workflow/status/rmyndharis/aimhooman/test.yml?branch=main&label=CI" alt="CI">
|
|
12
|
-
<img src="https://img.shields.io/badge/version-v0.
|
|
12
|
+
<img src="https://img.shields.io/badge/version-v0.2.0-blue" alt="v0.2.0">
|
|
13
13
|
<img src="https://img.shields.io/badge/node-%E2%89%A522.8-339933?logo=node.js&logoColor=white" alt="Node 22.8+">
|
|
14
14
|
<img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="Zero dependencies">
|
|
15
15
|
<img src="https://img.shields.io/badge/license-MIT-111111" alt="MIT">
|
|
@@ -130,6 +130,7 @@ Guard a repository:
|
|
|
130
130
|
|
|
131
131
|
```sh
|
|
132
132
|
aimhooman init # git hooks + local excludes; normally no worktree files
|
|
133
|
+
aimhooman init --grandfather-secrets # also allow --scope secret-path for every secret already tracked (fixtures); new secrets stay blocked
|
|
133
134
|
aimhooman status
|
|
134
135
|
aimhooman uninstall # restore hooks/excludes; keep local policy state
|
|
135
136
|
aimhooman uninstall --purge-state # also delete common Git-directory state
|