@rmyndharis/aimhooman 0.1.3 → 0.1.4

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.
@@ -9,7 +9,7 @@
9
9
  "name": "aimhooman",
10
10
  "source": "./",
11
11
  "description": "Keeps AI session files, secrets, and unwanted attribution out at the agent and Git boundary.",
12
- "version": "0.1.3",
12
+ "version": "0.1.4",
13
13
  "license": "MIT",
14
14
  "keywords": [
15
15
  "git",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aimhooman",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "AI works. Hoomans ship. Keeps AI session files, secrets, and unwanted attribution out at the agent and Git boundary.",
5
5
  "author": {
6
6
  "name": "aimhooman"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aimhooman",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "AI works. Hoomans ship. Keeps AI session files, secrets, and unwanted attribution out at the agent and Git boundary.",
5
5
  "author": {
6
6
  "name": "aimhooman maintainers",
package/CHANGELOG.md CHANGED
@@ -5,6 +5,25 @@ 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.1.4] - 2026-07-18
9
+
10
+ ### Fixed
11
+
12
+ - Uninstall no longer leaves aimhooman artifacts in `.git`. Every atomic write takes a
13
+ lock whose `<lock>.queue` directory was created but never removed — the release path
14
+ only unlinked its own candidate file — and `--purge-state` cleared just the state
15
+ directory. So `.git` kept the queue directories and the `COMMIT_EDITMSG.aimhooman-bak`
16
+ attribution backup while the command printed "state purged". Uninstall now sweeps this
17
+ residue once the lifecycle lock releases; `rmdirSync` removes only an empty directory,
18
+ so a concurrent contender's queue is never touched, and the lifecycle queue is removable
19
+ precisely because its own lock has already released. A plain uninstall keeps policy
20
+ state and drops the operational residue; `--purge-state` leaves no aimhooman fingerprints.
21
+ - A bare AWS access key ID is now detected. `secret.aws-key-content` fired only when an
22
+ `aws_secret_access_key` or `aws_session_token` name sat beside the value, so an
23
+ `AKIA…`/`ASIA…` access key ID committed on its own passed clean. The rule now matches the
24
+ access-key-ID prefixes directly — the fixed-prefix, highest-confidence AWS indicator. The
25
+ 16-character body and word boundaries keep short lookalikes such as `AKIA123` from matching.
26
+
8
27
  ## [0.1.3] - 2026-07-18
9
28
 
10
29
  ### 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.1.3-blue" alt="v0.1.3">
12
+ <img src="https://img.shields.io/badge/version-v0.1.4-blue" alt="v0.1.4">
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">
package/bin/aimhooman.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { execFileSync } from 'node:child_process';
3
- import { chmodSync, lstatSync, readFileSync, rmSync } from 'node:fs';
3
+ import { chmodSync, lstatSync, readFileSync, rmdirSync, rmSync } from 'node:fs';
4
4
  import { join } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { GIT_TIMEOUT_MS } from '../src/git-environment.mjs';
@@ -20,7 +20,7 @@ import {
20
20
  } from '../src/gitx.mjs';
21
21
  import { loadConfig, loadOverrides, loadProjectPolicy, normalizeOverrideTarget, saveConfig, saveOverrides } from '../src/state.mjs';
22
22
  import { applyExclude, inspectExclude, patternsForRules, removeExclude } from '../src/exclude.mjs';
23
- import { hookDiagnostics, installHooks, installGlobalHooks, uninstallGlobalHooks, globalHooksDir, installedHooks, remainingDispatchers, uninstallHooks, unrestoredChainedBackups } from '../src/githooks.mjs';
23
+ import { effectiveHooksDir, hookDiagnostics, installHooks, installGlobalHooks, uninstallGlobalHooks, globalHooksDir, installedHooks, remainingDispatchers, uninstallHooks, unrestoredChainedBackups } from '../src/githooks.mjs';
24
24
  import { ArgumentError, parseArguments } from '../src/args.mjs';
25
25
  import { engineForPolicy, scanGitTarget, scanMessage } from '../src/scan-target.mjs';
26
26
  import { resolvePolicy } from '../src/policy-resolver.mjs';
@@ -1615,7 +1615,8 @@ function cmdUninstall(args) {
1615
1615
  console.error('aimhooman: not a git repository');
1616
1616
  return 30;
1617
1617
  }
1618
- return withLock(join(repo.commonDir, 'aimhooman-lifecycle.lock'), () => {
1618
+ const lifecycleLock = join(repo.commonDir, 'aimhooman-lifecycle.lock');
1619
+ const exitStatus = withLock(lifecycleLock, () => {
1619
1620
  const rep = uninstallHooks(repo);
1620
1621
  // The irreversible work is already done above, and the report is still
1621
1622
  // below. A throw from here unwound past all of it, so a damaged marker was
@@ -1683,6 +1684,22 @@ function cmdUninstall(args) {
1683
1684
  // the uninstall is genuinely incomplete and 30 is the honest answer.
1684
1685
  return remaining.length || rep.failures?.length || unrestored.length || excludeFailure ? 30 : 0;
1685
1686
  }, LIFECYCLE_LOCK_OPTIONS);
1687
+ // Sweep the operational residue the guard authored in .git, so uninstall leaves
1688
+ // no aimhooman fingerprints behind — the same tooling residue this tool exists
1689
+ // to remove. rmdirSync deletes only an empty directory, so a live contender's
1690
+ // queue is never touched; the lifecycle queue becomes removable only now, after
1691
+ // its own lock above has released.
1692
+ for (const queue of [
1693
+ `${lifecycleLock}.queue`,
1694
+ `${repo.excludeFile}.aimhooman.lock.queue`,
1695
+ join(effectiveHooksDir(repo), '.aimhooman-hooks.lock.queue'),
1696
+ ]) {
1697
+ try { rmdirSync(queue); } catch { /* held by another aimhooman, or already gone */ }
1698
+ }
1699
+ // A one-commit-ago attribution backup that git's next COMMIT_EDITMSG makes stale.
1700
+ try { rmSync(join(repo.commonDir, 'COMMIT_EDITMSG.aimhooman-bak'), { force: true }); }
1701
+ catch { /* nothing to remove */ }
1702
+ return exitStatus;
1686
1703
  }
1687
1704
 
1688
1705
  function usage() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmyndharis/aimhooman",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "AI works. Hoomans ship. Keep AI session files, secrets, and attribution out of your commits.",
5
5
  "homepage": "https://github.com/rmyndharis/aimhooman#readme",
6
6
  "repository": {
@@ -45,14 +45,15 @@
45
45
  },
46
46
  {
47
47
  "id": "secret.aws-key-content",
48
- "version": 1,
48
+ "version": 2,
49
49
  "provider": "aws",
50
50
  "category": "secret",
51
51
  "confidence": "high",
52
52
  "kind": "code",
53
53
  "match": {
54
54
  "content": [
55
- "(?i)\\baws_(?:secret_access_key|session_token)\\b\\s*[:=]\\s*[\\\"']?[A-Za-z0-9/+=]{32,}(?![A-Za-z0-9/+=])"
55
+ "(?i)\\baws_(?:secret_access_key|session_token)\\b\\s*[:=]\\s*[\\\"']?[A-Za-z0-9/+=]{32,}(?![A-Za-z0-9/+=])",
56
+ "\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b"
56
57
  ]
57
58
  },
58
59
  "actions": {
package/src/githooks.mjs CHANGED
@@ -124,7 +124,7 @@ function canonicalPath(path) {
124
124
 
125
125
  // Ask Git for the path it actually uses. In a linked worktree this resolves to
126
126
  // the common repository hooks directory, not <gitDir>/hooks.
127
- function effectiveHooksDir(repo) {
127
+ export function effectiveHooksDir(repo) {
128
128
  try {
129
129
  return execFileSync(
130
130
  'git',