MCPcopy Create free account
hub / github.com/github/spec-kit / setup

Method setup

src/specify_cli/integrations/kimi/__init__.py:85–128  ·  view source on GitHub ↗

Install skills with optional legacy migration.

(
        self,
        project_root: Path,
        manifest: IntegrationManifest,
        parsed_options: dict[str, Any] | None = None,
        **opts: Any,
    )

Source from the content-addressed store, hash-verified

83 ]
84
85 def setup(
86 self,
87 project_root: Path,
88 manifest: IntegrationManifest,
89 parsed_options: dict[str, Any] | None = None,
90 **opts: Any,
91 ) -> list[Path]:
92 """Install skills with optional legacy migration."""
93 parsed_options = parsed_options or {}
94
95 # Refuse a symlinked destination before any writes occur. base
96 # setup() only rejects a destination that *escapes* project_root
97 # after resolve(), so an in-tree symlinked ``.kimi-code`` /
98 # ``.kimi-code/skills`` (e.g. ``-> .``) would still pass that check
99 # and misdirect the SKILL.md writes into an unintended in-tree
100 # location (e.g. ``./skills/``). Reject any symlinked destination
101 # component up front so this never happens.
102 new_skills_dir = self.skills_dest(project_root)
103 if _has_symlinked_component(new_skills_dir, project_root):
104 raise ValueError(
105 f"Skills destination {new_skills_dir} contains a symlinked "
106 f"path component; refusing to install into it."
107 )
108
109 # Run base setup first so new-path targets (speckit-*) exist,
110 # then migrate/clean legacy dirs without risking user content loss.
111 created = super().setup(
112 project_root, manifest, parsed_options=parsed_options, **opts
113 )
114
115 if parsed_options.get("migrate_legacy", False):
116 old_skills_dir = project_root / ".kimi" / "skills"
117 # Validate both endpoints. base setup() already rejects a
118 # destination that *escapes* the project root, but an in-tree
119 # symlinked ``.kimi-code``/``.kimi-code/skills`` (e.g. ``-> .``)
120 # would still misdirect the move; ``_is_safe_legacy_dir`` rejects
121 # any symlinked component, giving the destination the same
122 # protection as the source.
123 if _is_safe_legacy_dir(old_skills_dir, project_root) and (
124 _is_safe_legacy_dir(new_skills_dir, project_root)
125 ):
126 _migrate_legacy_kimi_skills_dir(old_skills_dir, new_skills_dir)
127
128 return created
129
130 def teardown(
131 self,

Callers

nothing calls this directly

Calls 5

_has_symlinked_componentFunction · 0.85
_is_safe_legacy_dirFunction · 0.85
skills_destMethod · 0.80
getMethod · 0.45

Tested by

no test coverage detected