{"record":{"id":"081a7eac541b063c","repo":"github/spec-kit","slug":"manifest-project-root-manifest-project-root-do-081a7e","errorCode":null,"errorMessage":"manifest.project_root ({manifest.project_root}) does not match project_root ({project_root_resolved})","messagePattern":"manifest\\.project_root \\((.+?)\\) does not match project_root \\((.+?)\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/integrations/hermes/__init__.py","lineNumber":100,"sourceCode":"    ) -> list[Path]:\n        \"\"\"Install command templates as global Hermes skills.\n\n        Writes each skill directly to\n        ``~/.hermes/skills/speckit-<name>/SKILL.md`` where Hermes\n        discovers them at runtime.  No project-local SKILL.md copies are\n        created — the global directory is the single source of truth.\n        A project-local marker (``.hermes/skills/`` empty) is created\n        so extension commands (e.g. git) can detect Hermes as an active\n        integration.\n        \"\"\"\n        templates = self.list_command_templates()\n        if not templates:\n            return []\n\n        # Safety check: verify manifest project_root matches (standard pattern)\n        project_root_resolved = project_root.resolve()\n        if manifest.project_root != project_root_resolved:\n            raise ValueError(\n                f\"manifest.project_root ({manifest.project_root}) does not match \"\n                f\"project_root ({project_root_resolved})\"\n            )\n\n        script_type = opts.get(\"script_type\", \"sh\")\n        arg_placeholder = (\n            self.registrar_config.get(\"args\", \"$ARGUMENTS\")\n            if self.registrar_config\n            else \"$ARGUMENTS\"\n        )\n\n        global_skills_dir = self._hermes_home_skills_dir()\n        global_skills_dir.mkdir(parents=True, exist_ok=True)\n\n        created: list[Path] = []\n\n        for src_file in templates:\n            raw = src_file.read_text(encoding=\"utf-8\")","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/integrations/hermes/__init__.py#L82-L118","documentation":"Raised by HermesIntegration.setup() (src/specify_cli/integrations/hermes/__init__.py:100) when the manifest's recorded project_root does not equal the resolved project_root argument. Hermes installs into a global skills directory but still creates a project-local marker, so it performs the same standard manifest/root binding check as other integrations before writing anything.","triggerScenarios":"HermesIntegration().setup(project_root, manifest) where manifest.project_root differs from project_root.resolve() — different directory, another project's manifest, or an unresolved/symlinked spelling of the same directory.","commonSituations":"Reusing a manifest created before changing directories; /tmp vs /private/tmp symlink differences on macOS; automated harnesses mixing tmp_path and its resolved form.","solutions":["Create the manifest with project_root.resolve() and pass the identical resolved root to setup().","Create a fresh manifest per project; never reuse across roots.","Prefer 'specify init --integration hermes', which wires the manifest correctly."],"exampleFix":"# before\nmanifest = IntegrationManifest(project_root=Path(\"~/proj\").expanduser())\nHermesIntegration().setup(Path(\"/Users/u/proj\"), manifest)\n\n# after\nroot = Path(\"/Users/u/proj\").resolve()\nmanifest = IntegrationManifest(project_root=root)\nHermesIntegration().setup(root, manifest)","handlingStrategy":"validation","validationCode":"root = project_root.resolve()\nif manifest.project_root != root:\n    manifest = IntegrationManifest(project_root=root)","typeGuard":null,"tryCatchPattern":"try:\n    integration.setup(root, manifest)\nexcept ValueError as e:\n    if \"manifest.project_root\" in str(e):\n        manifest = IntegrationManifest(project_root=root.resolve())\n        integration.setup(root, manifest)\n    else:\n        raise","preventionTips":["Resolve project_root once and use it for both the manifest and setup().","Don't carry manifests across directory changes or projects.","Let 'specify init --integration hermes' manage manifest lifecycle."],"tags":["filesystem","paths","integration-setup","spec-kit","hermes"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}