@rmyndharis/aimhooman 0.1.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.
Files changed (54) hide show
  1. package/.agents/rules/aimhooman.md +53 -0
  2. package/.claude-plugin/marketplace.json +23 -0
  3. package/.claude-plugin/plugin.json +9 -0
  4. package/.clinerules/aimhooman.md +53 -0
  5. package/.codex-plugin/plugin.json +37 -0
  6. package/.cursor/rules/aimhooman.mdc +59 -0
  7. package/.gemini/settings.json +7 -0
  8. package/.github/copilot-instructions.md +53 -0
  9. package/.github/hooks/aimhooman.json +22 -0
  10. package/.kiro/steering/aimhooman.md +53 -0
  11. package/.windsurf/rules/aimhooman.md +57 -0
  12. package/AGENTS.md +53 -0
  13. package/CHANGELOG.md +153 -0
  14. package/CODE_OF_CONDUCT.md +128 -0
  15. package/CONTRIBUTING.md +144 -0
  16. package/GEMINI.md +53 -0
  17. package/LICENSE +21 -0
  18. package/README.md +472 -0
  19. package/SECURITY.md +74 -0
  20. package/bin/aimhooman.mjs +1589 -0
  21. package/docs/design/agent-portability.md +73 -0
  22. package/docs/design/frictionless-enforcement.md +135 -0
  23. package/docs/hosts.json +164 -0
  24. package/docs/logo/aimhooman-logo.png +0 -0
  25. package/docs/logo/aimhooman.png +0 -0
  26. package/hooks/hooks.json +29 -0
  27. package/package.json +77 -0
  28. package/rules/attribution.json +142 -0
  29. package/rules/markers.json +88 -0
  30. package/rules/paths.json +407 -0
  31. package/rules/secrets.json +90 -0
  32. package/schemas/overrides.schema.json +134 -0
  33. package/schemas/project-policy.schema.json +12 -0
  34. package/schemas/rule-pack.schema.json +126 -0
  35. package/schemas/scan-report.schema.json +165 -0
  36. package/skills/aimhooman/SKILL.md +65 -0
  37. package/src/args.mjs +72 -0
  38. package/src/atomic-write.mjs +285 -0
  39. package/src/codex-manifest.mjs +65 -0
  40. package/src/exclude.mjs +125 -0
  41. package/src/git-environment.mjs +5 -0
  42. package/src/git-path.mjs +5 -0
  43. package/src/githooks.mjs +813 -0
  44. package/src/gitx.mjs +721 -0
  45. package/src/history-scan.mjs +295 -0
  46. package/src/hook.mjs +2602 -0
  47. package/src/policy-resolver.mjs +200 -0
  48. package/src/report.mjs +63 -0
  49. package/src/rules.mjs +509 -0
  50. package/src/ruleset-text.mjs +29 -0
  51. package/src/scan-session.mjs +152 -0
  52. package/src/scan-target.mjs +697 -0
  53. package/src/scan.mjs +325 -0
  54. package/src/state.mjs +360 -0
package/README.md ADDED
@@ -0,0 +1,472 @@
1
+ <div align="center">
2
+
3
+ <img src="docs/logo/aimhooman-logo.png" alt="aimhooman - AI works. Hoomans ship." width="120">
4
+ </div>
5
+
6
+ <h1 align="center">AI’m Hooman</h1>
7
+
8
+ <p align="center">"beep boop ... ai'm hooman"</p>
9
+
10
+ <p align="center">
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.1.0-blue" alt="v0.1.0">
13
+ <img src="https://img.shields.io/badge/node-%E2%89%A522.8-339933?logo=node.js&logoColor=white" alt="Node 22.8+">
14
+ <img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="Zero dependencies">
15
+ <img src="https://img.shields.io/badge/license-MIT-111111" alt="MIT">
16
+ <img src="https://img.shields.io/npm/dm/@rmyndharis/aimhooman?label=downloads" alt="Downloads">
17
+ <img src="https://img.shields.io/github/stars/rmyndharis/aimhooman?style=social" alt="GitHub Stars">
18
+ </p>
19
+
20
+ <p align="center">aimhooman: <i>AI works. Hoomans ship.</i></p>
21
+
22
+ <b>aimhooman</b> is a vendor-neutral guard that keeps AI coding agents from leaving their
23
+ fingerprints in your Git history: session files that were never meant to be
24
+ committed, secrets, and unwanted AI attribution in commit messages. Its host adapters
25
+ and Git hooks catch known cases before a commit and make review decisions visible.
26
+ <br/>
27
+
28
+ > **Human-owned, not human-washed.** aimhooman removes tooling residue and sets
29
+ > human ownership. It does not fake authorship or strip disclosure your policy
30
+ > requires.
31
+
32
+ ## TL;DR
33
+
34
+ Keep AI session files, secrets, and stray `Co-authored-by:` lines out of your Git
35
+ history — without a per-tool ignore list and without faking who wrote the code.
36
+
37
+ ```sh
38
+ npm install -g @rmyndharis/aimhooman
39
+ aimhooman init # git hooks + local excludes; normally no worktree files
40
+ git commit -m "ship it" # guarded automatically
41
+ ```
42
+
43
+ Repair-first by default. Any block that cannot be repaired, or any incomplete
44
+ scan, stops before the branch ref changes. Zero runtime dependencies. Runs on
45
+ Node 22.8+.
46
+
47
+ Want it inside Claude Code, Codex, Copilot, Cursor, and friends? See
48
+ [Use it in your AI coding tool](#use-it-in-your-ai-coding-tool).
49
+
50
+ ## The problem
51
+
52
+ <p align="center">
53
+ <img src="docs/logo/aimhooman.png" alt="aimhooman - AI works. Hoomans ship." width="720">
54
+ </p>
55
+ Your AI agent works in your repo and quietly leaves state behind: `.claude/session.json`,
56
+ chat history, caches, and `Co-authored-by:` an AI. One `git add -A` later, it is in
57
+ your history. Ignore lists are per-tool and never complete, and a local git hook is
58
+ one `--no-verify` away from being skipped.
59
+
60
+
61
+ ## How it works
62
+
63
+ One detection core, many enforcement surfaces. On the default profile, the ordinary
64
+ commit path repairs hygiene findings when it can. `commit-msg` checks the pinned
65
+ would-be tree, and the final ref boundary independently scans every commit introduced
66
+ to `HEAD` or a branch. Any remaining block or incomplete scan stops. `strict` blocks
67
+ instead of repairing.
68
+
69
+ ```mermaid
70
+ flowchart TD
71
+ SESS([Session start]) -. once .-> EXCL["Auto-exclude known<br/>AI artifacts in .git/info/exclude"]
72
+ AGENT([Agent calls a tool]) -. proactive .-> ADV["PreToolUse parses the command,<br/>resolves repo/policy, and checks bypass risk"]
73
+ RUN([You run the CLI]) -. on demand .-> CLI["check · fix · explain"]
74
+
75
+ COMMIT([Ordinary git commit or merge]) --> PRE["pre-commit / pre-merge-commit<br/>run predecessor, resolve staged policy,<br/>scan exact index"]
76
+ DIRECT([Sequencer or direct ref path<br/>cherry-pick · rebase · fetch · worktree · update-ref]) --> REF
77
+ PRE -->|clean: safe repair| MSG["commit-msg snapshots would-be tree,<br/>runs predecessor, then checks<br/>the message and pinned full tree"]
78
+ PRE -->|strict violation, incomplete scan,<br/>or failed repair| BLOCK([Operation stops])
79
+ MSG -->|message and tree accepted| REF["reference-transaction prepared<br/>full-scans every introduced commit"]
80
+ MSG -->|unsafe or unrepairable| BLOCK
81
+ REF -->|accepted| SHIP([Ref update commits])
82
+ REF -->|violation or incomplete scan| BLOCK
83
+
84
+ classDef entry fill:#f8fafc,stroke:#94a3b8,color:#0f172a,stroke-width:1.5px
85
+ classDef hook fill:#eef2ff,stroke:#6366f1,color:#312e81,stroke-width:2px
86
+ classDef ok fill:#ecfdf5,stroke:#10b981,color:#064e3b,stroke-width:1.5px
87
+ classDef stop fill:#fef2f2,stroke:#ef4444,color:#7f1d1d,stroke-width:2px
88
+
89
+ class SESS,AGENT,RUN,COMMIT,DIRECT entry
90
+ class PRE,MSG,REF hook
91
+ class SHIP ok
92
+ class BLOCK stop
93
+ ```
94
+
95
+ - **Prevent:** on session start, known AI artifacts are written into `.git/info/exclude`
96
+ (local, never your `.gitignore`), so they never even show in `git status`.
97
+ - **Catch:** if one slips through, `pre-commit` unstages it and `commit-msg` removes
98
+ complete, exact high-confidence attribution lines. Broader candidates are reported
99
+ without editing the message. An unterminated exact final line stops unchanged because
100
+ a byte-safe repair cannot be proved.
101
+ - **Advise:** the plugin's `PreToolUse` reports paths before Git runs. It denies a
102
+ protected commit/ref operation on every profile when the hook JSON is empty,
103
+ invalid, or not an object, a required managed guard is missing, or hook/receiver
104
+ indirection makes the final ref check unprovable. An unknown executor argument
105
+ shape is denied on `strict`; `strict` also rejects uncertain execution and bypasses.
106
+ - **Block:** `strict` cancels ordinary commits instead of repairing them. On every
107
+ profile, the pinned-tree and final ref guards stop a commit that still contains a
108
+ block finding or cannot be checked completely.
109
+
110
+ ## By the numbers
111
+
112
+ | | |
113
+ | --- | --- |
114
+ | Enforcement | repair-first ordinary commits; fail-closed final ref check; strict hard-blocking |
115
+ | Policy profiles | 3 (clean, strict, compliance) |
116
+ | Runtime dependencies | 0 (runs on Node, ships as source) |
117
+ | Worktree files added by `init` | Normally 0; an existing worktree-relative `core.hooksPath` stays in use |
118
+
119
+ ## Install
120
+
121
+ Node 22.8+ and Git 2.28+, zero runtime dependencies, ships as source. Git 2.28
122
+ is required for the prepared-phase reference transaction guard that checks
123
+ cherry-pick, revert, rebase, `git am`, and other ref-producing flows.
124
+
125
+ ```sh
126
+ npm install -g @rmyndharis/aimhooman
127
+ ```
128
+
129
+ Guard a repository:
130
+
131
+ ```sh
132
+ aimhooman init # git hooks + local excludes; normally no worktree files
133
+ aimhooman status
134
+ aimhooman uninstall # restore hooks/excludes; keep local policy state
135
+ aimhooman uninstall --purge-state # also delete common Git-directory state
136
+ ```
137
+
138
+ For commits you make at the terminal (outside your AI tool), one global setup guards
139
+ eligible non-bare repositories that do not override `core.hooksPath` locally:
140
+
141
+ ```sh
142
+ aimhooman init --global --yes # advanced: change core.hooksPath after confirmation
143
+ aimhooman uninstall --global # unset it
144
+ ```
145
+
146
+ Global `core.hooksPath` changes Git behavior for repositories that inherit it and can
147
+ replace their default hook directory. A local or worktree-scoped override takes
148
+ precedence. Bare repositories are outside the worktree/index policy boundary and the
149
+ global dispatchers leave them unchanged. `status` shows both local and global values.
150
+ Prefer repository `init` unless the global ordering is understood.
151
+
152
+ When `core.hooksPath` is set, Git reads hooks only from that effective directory and
153
+ ignores `.git/hooks`. Repository `init` installs and chains predecessors only when
154
+ that directory is absent or is proven to be owned by the repository. It refuses to
155
+ modify a global, shared, or external hook directory. In that case, integrate
156
+ aimhooman into the existing hook manager or remove the override before retrying.
157
+
158
+ Repository `init` installs `pre-commit`, `pre-merge-commit`, `commit-msg`, and
159
+ `reference-transaction`, and preserves an existing hook as a predecessor. For
160
+ `commit-msg`, aimhooman pins the would-be tree before the predecessor runs, so a later
161
+ index change cannot select a weaker policy. The prepared reference transaction is the
162
+ last local check for cherry-pick, revert, rebase, `git am`, fetch/worktree branch
163
+ creation, and direct branch-ref updates. Every profile stops if a predecessor removes
164
+ a required guard; the first running dispatcher that detects the loss aborts the
165
+ operation.
166
+
167
+ ## Use it in your AI coding tool
168
+
169
+ Claude Code runs the installed plugin hook in each session. Codex runs it only after
170
+ the user trusts the hook with `/hooks`, and the Copilot repository hook runs only when
171
+ `aimhooman` is available on `PATH`. None of those host hooks replaces the Git-boundary
172
+ guard: install that guard with `aimhooman init` (or the global setup). Instruction-tier
173
+ hosts only load the ruleset until the Git guard is installed.
174
+
175
+ Claude Code:
176
+
177
+ ```
178
+ /plugin marketplace add rmyndharis/aimhooman
179
+ /plugin install aimhooman@aimhooman
180
+ ```
181
+
182
+ Codex:
183
+
184
+ ```text
185
+ codex plugin marketplace add rmyndharis/aimhooman
186
+ # start Codex, open /plugins, select the aimhooman marketplace,
187
+ # install aimhooman, enable it, then start a new session
188
+ /hooks
189
+ # review and trust the aimhooman SessionStart and PreToolUse hooks
190
+ ```
191
+
192
+ Codex CLI 0.144.3 or newer is the supported baseline, last checked on
193
+ 2026-07-15. Until `/hooks` shows the plugin hooks as trusted, Codex skips them.
194
+ Run `aimhooman status` and `aimhooman doctor` after `aimhooman init`; the Git
195
+ hooks are the final commit boundary because PreToolUse does not see every shell
196
+ execution path.
197
+
198
+ GitHub Copilot CLI:
199
+
200
+ ```sh
201
+ npm install -g @rmyndharis/aimhooman
202
+ ```
203
+
204
+ The Copilot repository hook (`.github/hooks/aimhooman.json`) calls the `aimhooman`
205
+ binary from PATH; it is advisory until you install the Git guard with
206
+ `aimhooman init`. The npm install does not add host files to a repository
207
+ automatically.
208
+
209
+ Cursor, Cline, Windsurf, Kiro, Gemini, and Antigravity use the instruction files
210
+ listed below. Other agents can use `AGENTS.md` or the packaged skill after their
211
+ own instruction-loading contract is checked. Full matrix:
212
+ [docs/design/agent-portability.md](docs/design/agent-portability.md).
213
+
214
+ | Host | File |
215
+ | --- | --- |
216
+ | Claude Code / Codex | `.claude-plugin/` / `.codex-plugin/` + `hooks/hooks.json` |
217
+ | GitHub Copilot | `.github/hooks/aimhooman.json`, `.github/copilot-instructions.md` |
218
+ | Cursor | `.cursor/rules/aimhooman.mdc` |
219
+ | Cline | `.clinerules/aimhooman.md` |
220
+ | Windsurf | `.windsurf/rules/aimhooman.md` |
221
+ | Kiro | `.kiro/steering/aimhooman.md` |
222
+ | Gemini CLI / Code Assist | `.gemini/settings.json`, `GEMINI.md` |
223
+ | Google Antigravity | `.agents/rules/aimhooman.md` (set the rule to Always On) |
224
+ | Any agent | `AGENTS.md` or `skills/aimhooman/SKILL.md` |
225
+
226
+ Instruction-tier files are templates in this source repository: copy the adapter you
227
+ need into the target project. Installing the npm CLI does not modify host instruction
228
+ files automatically.
229
+
230
+ ## What it catches
231
+
232
+ - **AI session/state artifacts**: examples include `.claude/session*.json`,
233
+ `.claude/history*`, `.claude/projects/`, `.codex/sessions/`, `.codex/logs/`,
234
+ `.copilot/`, `.cursor/chats/`, `.aider.*`, `.specstory/`,
235
+ `.continue/sessions/`, `.playwright-mcp/`, `.remember/`, `.superpowers/`, and
236
+ `.agent/`. [`rules/paths.json`](rules/paths.json) is the complete catalog.
237
+ - **Secrets**: a real `.env` (not `.env.example`), private-key content,
238
+ `.aws/credentials`, service-account private keys, recognized AWS secret/session
239
+ assignments, and provider token prefixes for GitHub, GitLab, npm, and Slack.
240
+ Public certificates are allowed.
241
+ - **AI attribution** in commit messages: known AI `Co-authored-by:` identities,
242
+ exact "Generated with/by ..." lines, and AI-service noreply attribution trailers.
243
+ - **AI markers** left in code: corner-cut tooling markers (ponytail/caveman/yagni-oneliner) and
244
+ AI authorship comments (e.g. "generated by copilot/claude/chatgpt") in the staged content.
245
+ - **Review-required** files: `.aimhooman.json`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`,
246
+ `.github/copilot-instructions.md`.
247
+
248
+ The Antigravity instruction directory `.agents/` is distinct from local state under
249
+ `.agent/`.
250
+
251
+ ## Profiles
252
+
253
+ Set at init, e.g. `aimhooman init --profile strict`.
254
+
255
+ - **clean** (default): repair-first on the ordinary commit path — AI artifacts are excluded or
256
+ unstaged, and complete exact high-confidence attribution lines are removed. Instruction
257
+ files, code markers, and broader attribution candidates stay visible as reviews. A block
258
+ that remains after repair, a repair failure, or an incomplete scan stops the operation.
259
+ - **strict**: hard enforcement — violations cancel the commit (exit 10) until you allow them.
260
+ - **compliance**: repair-first like `clean`, but **keeps** any AI attribution your policy
261
+ requires (no stripping).
262
+
263
+ The bundled agent instructions set a stricter authoring rule: agents must not add AI
264
+ attribution in the first place. Profiles control what the mechanical scanner does if
265
+ that instruction is missed. A repository may adopt the same authoring rule while still
266
+ using `clean` for automatic repair, or commit a strict team profile when every match
267
+ must veto the commit.
268
+
269
+ ### Versioned team policy
270
+
271
+ Commit `.aimhooman.json` when every clone should use the same baseline:
272
+
273
+ ```json
274
+ {
275
+ "schema_version": 1,
276
+ "profile": "strict"
277
+ }
278
+ ```
279
+
280
+ The project policy takes precedence over the per-clone profile written by `init`.
281
+ An individual `check` may escalate to `--profile strict`, but cannot weaken or replace
282
+ the team profile. Malformed project policy fails closed with an actionable error;
283
+ personal allow/deny exceptions and local rule packs remain in the common Git directory
284
+ under `aimhooman/`.
285
+ Under `strict`, policy files and agent instructions produce review-required findings.
286
+ The product's `review` and `policy-review` commands record local, object-bound decisions;
287
+ an ordinary path allow cannot satisfy either finding.
288
+
289
+ This personal repository does not use GitHub approvals, required reviewers, or
290
+ `CODEOWNERS`. For a protected-path change, CI verifies the pinned repository and owner
291
+ login plus numeric IDs through the GitHub API, then inspects the exact workflow-run
292
+ attempt. GitHub must attribute both `actor` and `triggering_actor`, including their
293
+ numeric IDs, to that owner. CI then binds the
294
+ authorization to the exact head, transition commit, path, resulting blob and regular-file
295
+ mode, or deletion tombstone. A strict-policy migration also binds its old and new policy
296
+ objects. A different attempt, commit, path result, mode, or policy transition needs fresh
297
+ authorization. A non-owner change fails closed; there is no reviewer or `CODEOWNERS`
298
+ fallback. The owner account and its credentials are the trust root, so this is owner
299
+ authorization, not independent review.
300
+
301
+ ## Overrides
302
+
303
+ Every decision has a rule ID, so you can resolve a finding narrowly:
304
+
305
+ ```sh
306
+ aimhooman allow AGENTS.md --reason "shared team config" # stop flagging this path
307
+ aimhooman deny path/or/rule-id # always block it
308
+ aimhooman explain claude.session-state # why a rule fires
309
+ ```
310
+
311
+ Overrides live in the repository's common Git directory under
312
+ `aimhooman/overrides.json` (local, never committed), so linked worktrees share them.
313
+
314
+ Secrets are never silenced by a normal path allow — that is deliberate, so a local
315
+ override cannot hide a real leaked key. A file that legitimately contains secret-shaped
316
+ text (documentation that quotes a key header, a detection test fixture) needs an
317
+ explicit, auditable acknowledgment instead:
318
+
319
+ ```sh
320
+ aimhooman allow docs/key-format.md --scope secret-path --reason "documents the header"
321
+ ```
322
+
323
+ ```sh
324
+ aimhooman override list --json
325
+ aimhooman override remove AGENTS.md
326
+ aimhooman override reset --all
327
+ ```
328
+
329
+ ## Commands
330
+
331
+ ```
332
+ aimhooman init | status | check | audit | scan | explain | allow | deny | override | review | policy-review | fix | doctor | uninstall | version
333
+ ```
334
+
335
+ `check` accepts one Git target (`--staged`, `--tracked`, `--commit <rev>`, or
336
+ `--range <base>...<head>`), plus `--message <file>`, `--profile`, and `--json`.
337
+ Commit and range targets read commit messages from Git automatically. A range scans each
338
+ introduced commit, so a bad file added and deleted before the endpoint is still reported.
339
+ Use an all-zero object ID as the base when there is no prior commit; this includes the root
340
+ commit. Deleting an ordinary forbidden path is not itself a finding, while removing or
341
+ lowering a versioned strict project policy still needs a bound policy review.
342
+ `audit` and `scan` are aliases for a full tracked-index scan.
343
+ `init --global --yes` and `uninstall --global` manage the advanced terminal-Git guard;
344
+ `uninstall --global` cannot be combined with the local `--purge-state` option.
345
+ `fix` follows the active profile: clean writes an exact safe repair, compliance makes no
346
+ change, and strict previews unless `--apply` is supplied.
347
+
348
+ Machine reports use `schema_version: 1` and include target policy identity, completeness,
349
+ scan statistics, commit and object metadata. Schemas are published in [`schemas/`](schemas/).
350
+
351
+ Add your own per-repository detection with local rule packs in the common Git directory
352
+ under `aimhooman/rules/*.json`
353
+ (the structural schema is in [`schemas/rule-pack.schema.json`](schemas/rule-pack.schema.json);
354
+ local rules only add detection — they can't weaken
355
+ a built-in block). Within one rule, local content patterns are capped at 32 expressions,
356
+ 512 characters per expression, and 4,096 characters total. Path and exception scopes
357
+ share the same glob count, per-expression, and total limits. They use a flat subset: literals,
358
+ character classes, anchors, dot, escapes, and fixed `{n}` repeats. Groups, alternation,
359
+ lookaround, backreferences, and variable quantifiers are rejected. A local expression
360
+ does not run on a line longer than 16,384 characters; that skip is reported and makes the
361
+ scan incomplete. Path rules are case-sensitive by default. Set
362
+ `match.path_case` to `"insensitive"` only for a security name whose meaning is
363
+ case-insensitive, such as `.env`; matching folds that rule's candidate and patterns but
364
+ does not change the Git path or override identity.
365
+
366
+ For an existing repository, start with `aimhooman audit --json`. If a residue path is
367
+ already tracked, remove it from the index with `git rm --cached <path>` and add an
368
+ appropriate ignore/exclude. If a secret was committed, rotate it first; history cleanup
369
+ is deliberately outside aimhooman's scope.
370
+
371
+ ## Exit codes
372
+
373
+ | Code | Meaning |
374
+ | --- | --- |
375
+ | 0 | clean, or non-blocking review |
376
+ | 10 | policy violation (block) |
377
+ | 11 | review-required on a non-clean profile |
378
+ | 20 | usage, configuration, or rule-pack error |
379
+ | 30 | Git or I/O error |
380
+ | 31 | scan incomplete because a content or output budget was reached |
381
+
382
+ ## FAQ
383
+
384
+ **Is this a way to hide AI use?** No. aimhooman removes operational residue and
385
+ establishes human ownership. It never changes author, committer, signature, or
386
+ timestamp, and the compliance profile keeps any disclosure your policy requires.
387
+
388
+ **Will it cancel my commits?** On the default `clean` profile, aimhooman first tries to
389
+ exclude or unstage hygiene artifacts and safely remove exact attribution lines. The
390
+ commit proceeds only if no block remains and every scan completes. A pre-existing
391
+ tracked block, failed unstage/repair, unterminated exact attribution, secret, or scan
392
+ budget failure stops the operation. `strict` cancels findings instead of repairing.
393
+
394
+ **Does it slow commits down?** The staged check runs locally with no network and reads
395
+ Git objects in batches. Text-oriented rules skip binary files, but byte-safe secret
396
+ signatures still run over their raw bytes. Size and total budgets are visible in
397
+ reports. Files over 2 MiB or a scan over 64 MiB make the scan incomplete; direct checks
398
+ and Git pre-commit guards stop on every profile instead of claiming that content was checked.
399
+
400
+ **Can the agent bypass it?** Any local tool can ultimately be bypassed by a user with
401
+ commit access. On every profile, the agent guard rejects empty, invalid, or non-object
402
+ hook JSON, unresolved Git subcommands/aliases, missing managed final guards, and hook
403
+ or receive-pack indirection around protected ref mutations. An unknown executor
404
+ argument shape is denied on `strict`; `strict` additionally rejects
405
+ `--no-verify` and uncertain commit execution. The Git hook remains the source of truth
406
+ for ordinary commits. Git hooks are not a sandbox: an editor or
407
+ another local program started during a commit has the same filesystem access and can
408
+ change a later hook. The strict agent guard rejects explicit editor overrides, commits
409
+ that would open an editor, and commits with an active foreign `prepare-commit-msg` hook.
410
+ It still cannot prove that every program already selected by local Git config is safe.
411
+ Commands assembled from files, encoded data, or network input may also be invisible to
412
+ its non-executing shell parser (POSIX shells — bash, sh, zsh, dash, ksh — and
413
+ `git.exe`; command nesting, pipelines, background jobs, and non-POSIX executors
414
+ such as PowerShell or fish are classified uncertain and, on `strict`, denied
415
+ with a retry instruction). Repository selection written in non-POSIX shell syntax
416
+ is denied before policy lookup on every profile. Guarded Git changes, including
417
+ `add`, commit, and ref updates, also reject shell-expanded targets, any leading-tilde
418
+ target, POSIX targets beginning with exactly `//`, and an explicit split
419
+ `--work-tree`; pass a literal expanded path or run the operation from that repository.
420
+ On Windows, use a native `C:/...` target: POSIX-root
421
+ targets such as `/c/...` and `/tmp`, drive-relative forms such as `C:repo`, and
422
+ incomplete UNC roots are denied because the parser cannot map them to one native
423
+ repository without running the command. Wrappers that can select another cwd or
424
+ filesystem namespace, including `sudo`, `chroot`, `find -execdir`, WSL, and sandbox
425
+ launchers, fail closed on every profile; retry as a direct Git command from the target
426
+ repository. Nested non-POSIX shells and shell launches that explicitly select login,
427
+ interactive, or startup-file behavior fail closed for the same reason. Treat local
428
+ executables and Git config as trusted. For team enforcement, scan the actual PR range
429
+ in CI (a normal CI checkout has no staged changes):
430
+
431
+ `pre-commit` and `commit-msg` do not cover every sequencer or ref movement. The managed
432
+ `reference-transaction` hook therefore checks introduced commits during Git's prepared
433
+ phase and can abort the local ref update. Git 2.54's earlier `preparing` callback is
434
+ accepted for compatibility and checks guard integrity; scanning remains in `prepared`,
435
+ after references are locked.
436
+ CI still scans the exact pushed or PR history:
437
+ local hooks do not govern another clone, server-side updates, or history created before
438
+ the guard was installed.
439
+ Bare repositories have no worktree/index boundary and are not supported by local commands.
440
+ A submodule is a separate repository with separate state and hooks; run `aimhooman init`
441
+ inside each submodule that needs local enforcement.
442
+
443
+ ```sh
444
+ git fetch origin main
445
+ aimhooman check --range origin/main...HEAD --profile strict
446
+ ```
447
+
448
+ On GitHub Actions, configure `actions/checkout` with `fetch-depth: 0` so the
449
+ triple-dot merge base is available.
450
+
451
+ ## Contributing
452
+
453
+ Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for how to add
454
+ rules and host adapters, the test setup, and the commit policy. Please note this
455
+ project has a [code of conduct](CODE_OF_CONDUCT.md); by participating you agree to
456
+ abide by it. To report a security issue, see [SECURITY.md](SECURITY.md).
457
+ Architecture notes live in [docs/design/](docs/design).
458
+
459
+ ## License
460
+
461
+ This project is licensed under the **MIT License** – free for personal and commercial use.
462
+
463
+ See [LICENSE](./LICENSE) for details.
464
+
465
+ ---
466
+
467
+ <br />
468
+ <br />
469
+
470
+ <p align="center">
471
+ Made with ❤️ by <a href="https://github.com/rmyndharis">Yudhi Armyndharis</a> &amp; aimhooman contributors
472
+ </p>
package/SECURITY.md ADDED
@@ -0,0 +1,74 @@
1
+ # Security Policy
2
+
3
+ aimhooman is itself a security-adjacent tool: it guards repositories against
4
+ AI-tool residue and secrets reaching Git history. This policy covers the
5
+ security of aimhooman itself.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Please **do not** open a public GitHub issue for security problems.
10
+
11
+ Email **yudhi@rmyndharis.com** with the subject `aimhooman security`. This is
12
+ the currently available private reporting route. Include:
13
+
14
+ - a description of the issue and its impact
15
+ - a minimal reproduction (a command or a small repo)
16
+ - the aimhooman version and Node version
17
+
18
+ We will acknowledge within 72 hours and aim for a fix or mitigation within
19
+ 30 days. Coordinated disclosure is preferred; credit is given on request.
20
+
21
+ ## Scope
22
+
23
+ **In scope:** the aimhooman codebase — the detection engine, the agent and git
24
+ hooks, the CLI, rule compilation (`globToRegExp`, `compileContent`), and the
25
+ shell-command parser that backs the agent PreToolUse guard (`parseGit` in
26
+ `src/hook.mjs`).
27
+
28
+ **Out of scope:** the contents of the built-in rule packs. False positives in
29
+ which paths are flagged are regular bugs (open a normal issue), not security
30
+ vulnerabilities. aimhooman is a hygiene guard, not a security-enforcement
31
+ mechanism against adversarial threats — a determined actor with commit access
32
+ can always defeat local tooling.
33
+
34
+ ## Supported versions
35
+
36
+ Before the first public release, security fixes land on `main`. After publication,
37
+ only the latest minor release will receive security fixes.
38
+
39
+ ## Security stance
40
+
41
+ - aimhooman **prevents leaks it has rules for**. It cannot catch novel AI-tool
42
+ artifacts with no rule, and it does not rewrite existing history.
43
+ - The default (`clean`) profile repairs ordinary hygiene findings when it can.
44
+ Invalid local rule packs are skipped with a warning, but corrupt override state,
45
+ incomplete staged-content scans, and unreadable Git targets stop every profile.
46
+ If any blocked path cannot be unstaged or safely repaired, the operation stops.
47
+ The pinned-tree and final-ref guards also stop a remaining or pre-existing tracked
48
+ block. `strict` vetoes instead of attempting clean/compliance repairs and also
49
+ stops review decisions.
50
+ - Local hooks are not a security boundary. Team CI should scan an explicit Git
51
+ range (`aimhooman check --range <base>...<head> --profile strict`), not the
52
+ normally empty staged index of a CI checkout. Ensure the checkout contains
53
+ the merge base (`fetch-depth: 0` on GitHub Actions).
54
+ - A committed `.aimhooman.json` provides the versioned team profile. Invalid
55
+ project policy fails closed; per-clone allow/deny entries remain local and
56
+ should be governed by team process where compliance requires it.
57
+ - This is a personal, owner-only repository with no GitHub approval, required
58
+ reviewer, or `CODEOWNERS` gate. For protected-path changes, CI resolves the
59
+ pinned repository and owner through the GitHub API and fetches the exact
60
+ workflow-run attempt. GitHub must attribute both the actor and triggering actor
61
+ to the owner's login and numeric ID. The resulting decision is bound to the exact head,
62
+ transition commit, path, blob and regular-file mode, or deletion tombstone; a
63
+ policy migration also binds its old and new objects. Non-owner changes fail
64
+ closed with no reviewer fallback. The owner is the trust root, not an independent
65
+ reviewer. These checks verify GitHub attribution, not an interactive human action,
66
+ and cannot defend against malicious or compromised owner credentials.
67
+ - The release pipeline pins actions to immutable commit SHAs and publishes with npm
68
+ build provenance. Pushing a `v*` tag runs the workflow: it installs dependencies,
69
+ runs the test suite, then publishes to npm authenticated by the `NPM_TOKEN` secret
70
+ (use a granular, publish-only, package-scoped npm token with 2FA enabled; rotate it
71
+ regularly). Protect `v*` tags so only the owner can create them and tag update or
72
+ deletion is blocked. Do not publish or move dist-tags manually while a release job
73
+ is pending or running. The npm package is not claimed as available until the release
74
+ workflow completes.