{"repo":"NousResearch/hermes-agent","public_id":"38529","display_label":"Installer marker files dirtying Git checkouts","summary":"These issues and PRs address installer- and bootstrap-created marker files (.install_method, .hermes-bootstrap-complete) that unintentionally dirty Git working directories, causing repeated autostash loops during updates. Fixes involve gitignoring the files and/or stopping their creation inside Git checkouts.","subsystem":"hermes_cli","counts":{"members":9,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":2,"merged_prs":2,"attempt_prs":5},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":39707},"resolution":{"state":"resolved","by":"pr-39707,pr-67364"},"freshness":{"state":"verified","last_verified_at":"2026-07-22T18:40:45+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_PARTIAL","link_density":0.20444444444444443},"fix_edges":[{"issue_number":38529,"pr_number":39707,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true},{"issue_number":66189,"pr_number":67364,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true}],"members":[{"kind":"issue","number":38529,"title":"hermes update repeatedly autostashes Desktop bootstrap marker .hermes-bootstrap-complete","url":null,"state":"closed"},{"kind":"issue","number":66189,"title":"[Bug]: Installer-created .install_method dirties Git checkouts","url":null,"state":"closed"},{"kind":"pr","number":38550,"title":"fix(cli): gitignore Desktop bootstrap marker so hermes update stops autostashing it","url":null,"state":"closed","close_reason":{"category":"silent_close","implication":"active"},"merged":false},{"kind":"pr","number":38555,"title":"fix(cli): ignore Desktop bootstrap marker to fix update stash loops","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#38550","number":38550},{"kind":"pr","value":"#38529","number":38529},{"kind":"pr","value":"#38542","number":38542},{"kind":"pr","value":"#38529","number":38529}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":39707,"title":"fix(cli): gitignore Desktop bootstrap marker so hermes update stops autostashing it","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":[".gitignore","scripts/release.py","tests/hermes_cli/test_update_autostash.py"],"fix_hunks":[{"file":".gitignore","hunks":["@@ -108,6 +108,12 @@ docs/superpowers/*\n # logs, and per-session caches are never artifacts of the codebase.\n .hermes/\n \n+# Desktop/bootstrap install marker written into the managed checkout root by the\n+# bootstrap installer. It is Hermes-managed runtime state, never a code change —\n+# ignore it so `hermes update`'s `git stash push --include-untracked` does not\n+# treat it as a local edit and autostash it on every run (#38529).\n+.hermes-bootstrap-complete\n+\n # Tool Search live-test harness output — non-deterministic model transcripts,\n # regenerated by scripts/tool_search_livetest.py. Never an artifact of the repo.\n scripts/out/"]},{"file":"scripts/release.py","hunks":["@@ -45,6 +45,7 @@\n \n # Auto-extracted from noreply emails + manual overrides\n AUTHOR_MAP = {\n+    \"[redacted:email]\": \"harjothkhara\",\n     \"[redacted:email]\": \"HeLLGURD\",\n     \"[redacted:email]\": \"dirtyren\",\n     \"[redacted:email]\": \"zhaoleibd\","]},{"file":"tests/hermes_cli/test_update_autostash.py","hunks":["@@ -819,3 +819,50 @@ def test_cmd_update_skips_stash_restore_when_reset_fails(monkeypatch, tmp_path,\n \n     out = capsys.readouterr().out\n     assert \"preserved in stash\" in out\n+\n+\n+def test_bootstrap_marker_not_autostashed_by_update(tmp_path):\n+    \"\"\"#38529: the Desktop bootstrap marker must be git-ignored so that\n+    ``hermes update``'s ``git stash push --include-untracked`` does not sweep it\n+    into an autostash on every run.\n+\n+    Behavioral + hermetic: build a throwaway repo that adopts the project's real\n+    ``.gitignore`` (the contract under test), drop the marker, and confirm the\n+    same stash invocation the updater uses leaves it untouched.\n+    \"\"\"\n+    import shutil\n+    import subprocess\n+\n+    if shutil.which(\"git\") is None:\n+        pytest.skip(\"git not available\")\n+\n+    repo_gitignore = Path(hermes_main.__file__).resolve().parents[1] / \".gitignore\"\n+\n+    def git(*args):\n+        return subprocess.run(\n+            [\"git\", *args], cwd=tmp_path, capture_output=True, text=True, check=True\n+        )\n+\n+    git(\"init\", \"-q\")\n+    git(\"config\", \"user.email\", \"[redacted:email]\")\n+    git(\"config\", \"user.name\", \"t\")\n+    (tmp_path / \".gitignore\").write_text(repo_gitignore.read_text())\n+    (tmp_path / \"tracked.txt\").write_text(\"x\\n\")\n+    git(\"add\", \"-A\")\n+    git(\"commit\", \"-qm\", \"init\")\n+\n+    marker = tmp_path / \".hermes-bootstrap-complete\"\n+    marker.write_text(\"\")\n+\n+    # Exact flags used by hermes update (hermes_cli/main.py).\n+    git(\"stash\", \"push\", \"--include-untracked\", \"-m\", \"hermes-update-autostash\")\n+\n+    assert marker.exists(), (\n+        \".hermes-bootstrap-complete was swept into the update autostash — it must \"\n+        \"be listed in .gitignore so `git stash -u` skips it (#38529).\"\n+    )\n+    # It must not even register as a dirty/untracked change.\n+    status = subprocess.run(\n+        [\"git\", \"status\", \"--porcelain\"], cwd=tmp_path, capture_output=True, text=True\n+    ).stdout\n+    assert \".hermes-bootstrap-complete\" not in status\n"]}]},{"kind":"pr","number":66216,"title":"fix: ignore installer-created .install_method runtime stamp (#66189)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#54855","number":54855}],"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":66322,"title":"fix(cli): stop creating .install_method in Git checkout (#66189)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"211edd5e08d5","number":0},{"kind":"commit","value":"48d8483250f5","number":0},{"kind":"pr","value":"#66189","number":66189},{"kind":"pr","value":"#66322","number":66322},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#66216","number":66216},{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#66322","number":66322},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#66723","number":66723},{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#66189","number":66189},{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#66216","number":66216},{"kind":"pr","value":"#66322","number":66322},{"kind":"pr","value":"#66723","number":66723},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#66322","number":66322},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#66216","number":66216},{"kind":"pr","value":"#66723","number":66723},{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#66322","number":66322},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#66216","number":66216},{"kind":"pr","value":"#66723","number":66723},{"kind":"pr","value":"#66216","number":66216},{"kind":"pr","value":"#66723","number":66723},{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#67364","number":67364},{"kind":"pr","value":"#374151","number":374151},{"kind":"pr","value":"#66189","number":66189},{"kind":"pr","value":"#54855","number":54855},{"kind":"pr","value":"#66216","number":66216},{"kind":"pr","value":"#66322","number":66322},{"kind":"pr","value":"#66723","number":66723},{"kind":"pr","value":"#67364","number":67364}],"category":"partial_fix","implication":"needs_llm"},"merged":false},{"kind":"pr","number":66723,"title":"chore(gitignore): ignore .install_method installer marker (#66189)","url":null,"state":"closed","close_reason":{"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":67364,"title":"chore(gitignore): ignore installer .install_method stamp (salvage of #54855)","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":[".gitignore","tests/hermes_cli/test_update_autostash.py"]}],"trust":{"default_tier":"verified","includes_suggested":false}}