Merge pull request #3537 from open-gsd/feat/2873-cross-scope-shadowing
This commit is contained in:
@@ -1014,6 +1014,8 @@ rather than that its contents are correct. The advisory never changes health's
|
||||
pass/fail status, and stays silent when the stamp is absent or the project isn't
|
||||
a git repo — "unknown" is reported as unknown, not as fresh.
|
||||
|
||||
**Cross-scope install shadowing (`W028`).** When a runtime is installed at both `global` and `local` scope and the host's trigger-resolution rules make one scope's `/gsd-*` surface unreachable — the Claude Code case: personal skill always beats project command — health adds a WARNING-severity advisory naming the shadowed triggers, the winning scope, and the losing scope. It never changes health's pass/fail status and is never auto-fixable (there is no single correct scope to remove), so `--repair` never touches it. Identical to the same advisory GSD Core prints at install time. See [Interpret install-shadow warnings](how-to/interpret-install-shadow-warnings.md).
|
||||
|
||||
**`--repair` does not apply destructive fixes.** Resetting config.json
|
||||
(`resetConfig`) and regenerating STATE.md (`regenerateState`) are destructive
|
||||
— the former loses custom settings, the latter loses session history — so
|
||||
|
||||
@@ -381,6 +381,7 @@
|
||||
"health-diagnostic-rules/agent-install.cjs",
|
||||
"health-diagnostic-rules/config-validation.cjs",
|
||||
"health-diagnostic-rules/consistency.cjs",
|
||||
"health-diagnostic-rules/install-surface-shadowing.cjs",
|
||||
"health-diagnostic-rules/milestone-archive-hygiene.cjs",
|
||||
"health-diagnostic-rules/phase-structure.cjs",
|
||||
"health-diagnostic-rules/roadmap-disk-consistency.cjs",
|
||||
@@ -401,6 +402,7 @@
|
||||
"install-engine.cjs",
|
||||
"install-profiles.cjs",
|
||||
"install-scope.cjs",
|
||||
"install-shadow-report.cjs",
|
||||
"installed-surface-resolver.cjs",
|
||||
"installer-migration-authoring.cjs",
|
||||
"installer-migration-report.cjs",
|
||||
|
||||
@@ -519,7 +519,9 @@ Full listing: `gsd-core/bin/lib/*.cjs`.
|
||||
| `install-engine.cjs` | Runtime-artifact install engine — `installRuntimeArtifacts`/`uninstallRuntimeArtifacts`/`installOpencodeFamilySkills` + their helpers, extracted from `bin/install.js` (ADR-1239 Phase B, #1679); install.js imports them back and injects `getCommitAttribution` |
|
||||
| `install-profiles.cjs` | Install profile allowlist + skill staging for `--minimal` install (#2762); single source of truth for which `gsd-*` skills/agents land in runtime config dirs |
|
||||
| `install-scope.cjs` | Install Scope Module — `resolveScope({id,runtime,...})` resolves the `'global'\|'local'` install-scope axis into `{id, configHome, settingsFile, consentRequired, hostPrecedenceRank}`, composing `resolveConfigHomeFromDescriptor` (`runtime-homes.cjs`) rather than modifying it (#2870, ADR-2866) |
|
||||
| `installed-surface-resolver.cjs` | Installed Surface Resolver — `resolveInstalledSurfaces(runtime?, opts?)` probes both install scopes for a runtime (or every registered runtime, sorted, when omitted), reads each scope's manifest, and resolves the trigger surface across only the scopes actually installed on this machine, composing `resolveScope` and `resolveTriggerSurface` rather than re-deriving either (#2872, ADR-2866 Phase 3) |
|
||||
| `install-shadow-report.cjs` | Cross-Scope Shadow Report Module (#2873, epic #2866 Phase 4a) — read-only projection over `installed-surface-resolver.cjs`'s `resolveInstalledSurfaces`; `buildShadowReport(runtime, opts)` filters `resolveTriggerSurface`'s `shadowedBy` groups down to triggers whose underlying stem genuinely exists in BOTH scopes' own manifests (not merely the union), and `renderShadowReport` projects the typed IR into bounded, sanitized (`sanitizeForRender` strips ANSI/C0-C1/bidi overrides) operator-console lines; consumed by both the installer and the W028 health rule so install-time and `/gsd-health` report identically |
|
||||
| `health-diagnostic-rules/install-surface-shadowing.cjs` | Health-diagnostic rule: cross-scope trigger shadowing check (W028) — projects `install-shadow-report.cjs`'s `ShadowReport` as a WARNING-severity, ADVISE/`risk:NONE` diagnostic (never auto-fixable), reusing `agent-install.cjs`'s W010 runtime-resolution shape; degrades to `[]` (never throws) when nothing is installable to report (#2873, epic #2866 Phase 4a) |
|
||||
| `installed-surface-resolver.cjs` | Installed Surface Resolver — `resolveInstalledSurfaces(runtime?, opts?)` probes both install scopes for a runtime (or every registered runtime, sorted, when omitted), reads each scope's manifest, and resolves the trigger surface across only the scopes actually installed on this machine, composing `resolveScope` and `resolveTriggerSurface` rather than re-deriving either (#2872, ADR-2866 Phase 3); local-scope manifest read is `lstat`-guarded and refuses to follow a symlinked config dir or manifest, degrading that scope to `installed: false` rather than following (#2873) |
|
||||
| `installer-migration-authoring.cjs` | Installer migration authoring guardrails for record metadata, explicit scopes, ownership evidence, and runtime contract citations |
|
||||
| `installer-migration-report.cjs` | Installer migration report projection and blocked-action guard for install/update integration |
|
||||
| `installer-migrations.cjs` | Installer migration planning, artifact classification, install-state persistence, journaled apply, and rollback helpers |
|
||||
|
||||
@@ -37,6 +37,7 @@ Language versions: [English](README.md) · [Português (pt-BR)](pt-BR/README.md)
|
||||
- [Isolate work with workspaces](how-to/isolate-work-with-workspaces.md) — use workspaces to sandbox experimental or risky changes
|
||||
- [Debug a failed execution](how-to/debug-a-failed-execution.md) — diagnose and recover from broken or incomplete phase execution
|
||||
- [Interpret scope-conformance warnings](how-to/interpret-scope-conformance-warnings.md) — read the advisory the worktree-wave merge emits when a plan branch commits outside its declared scope
|
||||
- [Interpret install-shadow warnings](how-to/interpret-install-shadow-warnings.md) — read the advisory GSD Core emits when a `/gsd-*` trigger is installed at both scopes and one silently wins, and tell "nothing to report" apart from "could not look"
|
||||
- [Interpret `state validate` results](how-to/interpret-state-validate-results.md) — read the `scope` reason codes and tell "nothing to report" apart from "could not look"
|
||||
- [Spike and sketch](how-to/spike-and-sketch.md) — use `/gsd-spike` and `/gsd-sketch` for exploratory work before committing to a plan
|
||||
- [Design a UI phase](how-to/design-a-ui-phase.md) — use the UI phase loop for frontend and visual work
|
||||
|
||||
@@ -36,6 +36,8 @@ npx @opengsd/gsd-core@latest --claude --global
|
||||
|
||||
Skills land in `~/.claude/`. Commands appear as `/gsd-*` slash commands in your next Claude Code session. Restart Claude Code to pick them up.
|
||||
|
||||
**Installing at both `--global` and `--local`.** This is a supported configuration (different projects sometimes need different customizations), but Claude Code's own trigger-resolution rules — personal scope overrides project scope, and a skill overrides a same-named command — both point the same direction: the global skill always wins the `/gsd-<name>` trigger over the local command. GSD Core detects this and prints which scope is winning right after install completes (and surfaces the identical fact from `/gsd-health` as diagnostic `W028`); it is an advisory, not a failure — the install itself still succeeds. At **global** scope, the winning skill's workflow-spec reference resolves at runtime against your working directory first, so a project with its own `.claude/gsd-core/` still gets its own specs even though the global skill is what Claude Code invokes — see [Interpret install-shadow warnings](interpret-install-shadow-warnings.md) for what the warning means, how to read which scope wins, and the limits of that resolution (it does not extend to the skill's `references/`/`templates/` includes).
|
||||
|
||||
**Override the install directory:**
|
||||
|
||||
```bash
|
||||
|
||||
93
docs/how-to/interpret-install-shadow-warnings.md
Normal file
93
docs/how-to/interpret-install-shadow-warnings.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# How to interpret install-shadow warnings
|
||||
|
||||
**Goal:** Understand the advisory GSD Core prints when a `/gsd-*` trigger is installed at more than one scope and one scope silently wins, tell which scope actually wins, know what to do about it, and tell "nothing to report" apart from "could not look".
|
||||
|
||||
**Prerequisites:** GSD Core installed on a Claude Code (or other skills-capable) runtime at more than one scope on the same machine — most commonly `--claude --global` (writes personal skills to `~/.claude/`) followed or preceded by `--claude --local` in a project (writes project commands to `<repo>/.claude/`).
|
||||
|
||||
---
|
||||
|
||||
## What the warning means
|
||||
|
||||
Claude Code resolves a `/gsd-<name>` trigger through two rules, both documented by the host: **personal scope overrides project scope**, and **a skill overrides a command of the same name**. GSD's own Claude artifact layout installs global (personal) as **skills** and local (project) as **commands** — so when both scopes are installed, both rules point the same way, and the global skill wins every time. The project's own `.claude/gsd-core/` spec tree — the workflow and reference files the local command correctly points at — becomes unreachable through the trigger, with no error and no missing file. Nothing in the local install is broken; it is simply never invoked (issue #2218).
|
||||
|
||||
The warning is GSD Core's fix for the "with no error" half of that sentence — it does not change which scope wins (see [Known limits](#known-limits)). You will see it in two places, projecting the identical fact:
|
||||
|
||||
- **At install time**, printed once after the manifest write completes, whichever scope you install second (design: shadowing can only exist once both scopes exist, and the report is always downstream of a successful `writeManifest`, never upstream of a failed one).
|
||||
- **From `/gsd-health`**, as diagnostic code **`W028`**, severity `WARNING` — see [Health diagnostic codes](../COMMANDS.md#gsd-health) for where this fits alongside the rest of the `Wnnn`/`Ennn`/`Innn` space. `--json` health output carries the same structured fact.
|
||||
|
||||
A realistic install-time warning:
|
||||
|
||||
```
|
||||
2 triggers shadowed: the local commands surface is unreachable through those triggers — global skills wins instead.
|
||||
- gsd-execute-phase: local/commands shadowed by global/skills
|
||||
- gsd-plan-phase: local/commands shadowed by global/skills
|
||||
```
|
||||
|
||||
For a runtime whose global scope also installs **skills** (12 of the 19 supported runtimes install `skills` at both scopes), the wording is deliberately different, because nothing disappears — the loser is merely overridden, not orphaned:
|
||||
|
||||
```
|
||||
1 trigger shadowed: the local skills entry is overridden by global skills.
|
||||
```
|
||||
|
||||
A report with more than 5 shadowed triggers shows the first 5 and a `...and N more` line rather than every one — the same bounded-sample shape as the installer's existing leaked-path warning.
|
||||
|
||||
---
|
||||
|
||||
## How to tell which scope is winning
|
||||
|
||||
Read the first line of the report. It always names the losing side first (`the <scope> <kind> surface/entry`) and the winning side last (`<scope> <kind> wins instead` / `overridden by <scope> <kind>`). Each subsequent bullet repeats the same fact per trigger: `<trigger>: <shadowed scope>/<shadowed kind> shadowed by <winner scope>/<winner kind>`.
|
||||
|
||||
On Claude Code specifically, the winner is always `global/skills` when both scopes are installed — that is the mechanism described above, not a per-machine coin flip. If you need to confirm this for yourself independent of the warning: run `/gsd-<name>` and check which "Base directory for this skill" (or equivalent skill-injection marker) the host reports.
|
||||
|
||||
An optional `Note:` line after the trigger list means one scope's own manifest disagrees with the directory it was actually found in (for example, a manifest copied between machines, or an `--config-dir` install). This is surfaced, never silently absorbed — see the trailing `declared runtime "…" does not match this runtime` / `declared scope "…" does not match the probed <scope> scope` text.
|
||||
|
||||
---
|
||||
|
||||
## What to do about it
|
||||
|
||||
The warning never changes the install's exit code — a shadowed install is a warning, not a failure, and the install itself is not broken. Your options, in order of how much they cost:
|
||||
|
||||
1. **Do nothing, if the global spec tree is what you want everywhere.** This is a legitimate configuration.
|
||||
2. **On Claude Code, rely on the built-in resolution described in [Known limits](#known-limits)** — at global scope, the workflow spec `@`-include the winning skill carries is resolved by an explicit, imperative two-step lookup that prefers your project's own `.claude/gsd-core/workflows/<name>.md` over the global one, so the project you are standing in gets its own specs even though the global skill is what's invoked. This is automatic; there is nothing to configure. It applies only to the workflow-spec include — see the limits below for what it does *not* cover.
|
||||
3. **Uninstall one scope.** If you never intend to use per-project GSD customizations, uninstalling the local scope removes the ambiguity entirely. If you always want project-local behavior, uninstalling the global scope does the same from the other direction.
|
||||
4. **On a non-Claude, both-scopes-`skills` runtime**, the loser is overridden rather than orphaned, so reordering which install ran last (reinstalling the scope you want to win) resolves it directly — there is no separate spec-tree-reachability problem to reason about on those runtimes.
|
||||
|
||||
---
|
||||
|
||||
## When nothing is reported: "nothing to report" vs "could not look"
|
||||
|
||||
Absence of a shadow warning is not always proof that nothing is shadowed. GSD Core distinguishes two silent outcomes:
|
||||
|
||||
**Nothing to report (verified clean)** — the check ran and found no genuine cross-scope collision:
|
||||
|
||||
- Only one scope is installed for that runtime.
|
||||
- Both scopes resolve to the *same* config directory (for example, `--config-dir` pointed both installs at the same place) — this is one physical install, not two.
|
||||
- The runtime's global scope installs no trigger-bearing artifact kind at all (windsurf's global install is `agents`, which is never invoked by a `/gsd-<name>` trigger) — there is nothing for the local scope to collide with.
|
||||
- The other scope's manifest exists but declares zero files (an empty or partial install at that scope).
|
||||
|
||||
**Could not look (degraded, not verified)** — the check itself could not run, and its silence carries no claim either way:
|
||||
|
||||
- The runtime has no installable config directory to probe (`configHome.kind === 'none'`, currently only VS Code) — the resolver this check is built on cannot even ask the question, so it degrades to no report rather than crashing your install or your `/gsd-health` run.
|
||||
- The other scope's manifest exists on disk but could not be read (a permissions error) — that scope is treated as not-installed for this check, exactly as if it were absent.
|
||||
- The other scope's manifest is reached through a symlinked config directory or is itself a symlink — the check refuses to follow it and treats that scope as not-installed, the same degraded outcome as an unreadable manifest.
|
||||
|
||||
If you are not sure which case applies, re-run `/gsd-health` and read the diagnostic list directly rather than inferring from silence — `/gsd-health --json`'s absence of a `W028` entry combined with a runtime you know is VS Code, or a manifest you know you cannot read, tells you it is the second case, not the first.
|
||||
|
||||
---
|
||||
|
||||
## Known limits
|
||||
|
||||
- **Detection is manifest-based.** If you deleted `gsd-file-manifest.json` at a scope but kept the installed artifacts, that scope is reported as not-installed and cannot shadow (or be shadowed by) anything.
|
||||
- **The workflow-spec resolution (item 2 above) is instruction-following, not guaranteed inclusion.** A static `@`-include is pre-expanded by the host before the agent ever runs; this resolved reference instead costs the agent one file read, following an explicit instruction. That is a weaker guarantee than a real `@`-include — it is deliberately confined to one reference, in the Claude runtime, at global scope only, which is what keeps that weaker guarantee acceptable rather than something the whole install quietly depends on.
|
||||
- **It covers only the workflow-spec include.** The winning global skill's `references/` and `templates/` includes still point at the global tree. If you customize only a *reference* file locally (not a workflow), the global copy of that reference is still what loads — you reach your local references only by way of entering the local workflow spec, whose own internal includes are already baked to local-absolute paths.
|
||||
- **Non-Claude runtimes get detection only, never the spec-root resolution above.** The 12 both-scopes-`skills` runtimes have the same shadowing mechanic but identical artifact kinds on both sides, so no spec tree becomes unreachable the way it does for Claude Code.
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [Install on your runtime](install-on-your-runtime.md) — per-runtime install commands, including the Claude Code coexistence note
|
||||
- [Host Integration Capability Matrix](../reference/host-integration-capability-matrix.md) — trigger precedence and per-runtime axis reference
|
||||
- [Interpret scope-conformance warnings](interpret-scope-conformance-warnings.md) — the sibling advisory-warning guide for worktree-wave merges
|
||||
- [`/gsd-health`](../COMMANDS.md#gsd-health) — command reference, including the diagnostic-code table this warning's `W028` belongs to
|
||||
- [docs index](../README.md)
|
||||
@@ -814,6 +814,8 @@ GSD の保証付きでアドホックタスクを実行します。
|
||||
/gsd-health --context # コンテキスト使用率のトリアージ
|
||||
```
|
||||
|
||||
**スコープ間インストールのシャドーイング(`W028`)。** あるランタイムが `global` と `local` の両方のスコープにインストールされ、ホストのトリガー解決ルールによって一方のスコープの `/gsd-*` サーフェスが到達不能になっている場合——Claude Code のケース:個人スキルは常にプロジェクトコマンドより優先される——ヘルスチェックは、シャドーイングされたトリガー、勝者スコープ、敗者スコープを示す WARNING 重大度のアドバイザリを追加します。これはヘルスチェックの合否ステータスを変更することはなく、自動修正の対象にもなりません(削除すべき単一の正解スコープが存在しないため)。そのため `--repair` はこれに一切手を加えません。インストール時に GSD Core が表示するのと同一のアドバイザリです。
|
||||
|
||||
### `/gsd-cleanup`
|
||||
|
||||
完了したマイルストーンからの累積フェーズディレクトリをアーカイブし、アップストリームが削除されたローカルブランチを削除します。
|
||||
|
||||
@@ -36,6 +36,8 @@ npx @opengsd/gsd-core@latest --claude --global
|
||||
|
||||
スキルは `~/.claude/` に配置されます。次回の Claude Code セッションからコマンドが `/gsd-*` スラッシュコマンドとして表示されます。反映するには Claude Code を再起動してください。
|
||||
|
||||
**`--global` と `--local` の両方のスコープへのインストール。** これはサポートされている構成です(プロジェクトによって異なるカスタマイズが必要になることがあるため)が、Claude Code 自身のトリガー解決ルール——個人スコープがプロジェクトスコープより優先され、スキルは同名のコマンドより優先される——はどちらも同じ方向を指します。つまり、グローバルスキルは常にローカルコマンドより `/gsd-<name>` トリガーで勝ちます。GSD Core はこれを検出し、インストール完了直後にどちらのスコープが勝っているかを表示します(同じ事実は `/gsd-health` の診断コード `W028` としても表示されます)。これは警告であり失敗ではありません——インストール自体は成功します。**グローバル**スコープでは、勝者となったスキルのワークフロー仕様への参照は実行時にまず作業ディレクトリを基準に解決されるため、Claude Code が実際に呼び出すのはグローバルスキルであっても、独自の `.claude/gsd-core/` を持つプロジェクトは自分自身の仕様を取得できます。
|
||||
|
||||
**インストールディレクトリの上書き:**
|
||||
|
||||
```bash
|
||||
|
||||
@@ -820,6 +820,8 @@ GSD 보장을 통해 애드혹 작업을 실행합니다.
|
||||
/gsd-health --context # 컨텍스트 활용 트리아지
|
||||
```
|
||||
|
||||
**범위 간 설치 섀도잉(`W028`).** 런타임이 `global`과 `local` 두 범위 모두에 설치되어 있고, 호스트의 트리거 해석 규칙으로 인해 한 범위의 `/gsd-*` 표면에 도달할 수 없게 되는 경우 — Claude Code의 사례: 개인 스킬이 항상 프로젝트 명령을 이깁니다 — 상태 점검은 섀도잉된 트리거, 승리한 범위, 패배한 범위를 명시하는 WARNING 심각도 권고를 추가합니다. 이는 상태 점검의 통과/실패 상태를 절대 변경하지 않으며, 자동으로 수정되지도 않습니다(제거해야 할 단 하나의 올바른 범위가 존재하지 않기 때문입니다). 따라서 `--repair`는 이를 절대 건드리지 않습니다. 설치 시점에 GSD Core가 출력하는 것과 동일한 권고입니다.
|
||||
|
||||
### `/gsd-cleanup`
|
||||
|
||||
완료된 마일스톤에서 누적된 단계 디렉토리를 아카이브하고 업스트림이 삭제된 로컬 브랜치를 정리합니다.
|
||||
|
||||
@@ -36,6 +36,8 @@ npx @opengsd/gsd-core@latest --claude --global
|
||||
|
||||
스킬은 `~/.claude/`에 저장됩니다. 다음 Claude Code 세션에서 `/gsd-*` 슬래시 명령으로 명령이 나타납니다. Claude Code를 재시작하여 적용하세요.
|
||||
|
||||
**`--global`과 `--local` 두 범위 모두에 설치하는 경우.** 이는 지원되는 구성입니다(프로젝트마다 서로 다른 커스터마이징이 필요한 경우가 있기 때문입니다). 하지만 Claude Code 자체의 트리거 해석 규칙 — 개인 범위가 프로젝트 범위보다 우선하고, 스킬이 동일한 이름의 명령보다 우선함 — 은 모두 같은 방향을 가리킵니다: 전역 스킬이 항상 `/gsd-<name>` 트리거에서 로컬 명령을 이깁니다. GSD Core는 이를 감지하여 설치 완료 직후 어떤 범위가 우선하는지 출력합니다(동일한 사실이 `/gsd-health`의 진단 코드 `W028`로도 표시됩니다). 이는 경고일 뿐 실패가 아닙니다 — 설치 자체는 계속 성공합니다. **전역** 범위에서는, 승리한 스킬의 워크플로 스펙 참조가 실행 시점에 작업 디렉터리를 기준으로 우선 해석되므로, Claude Code가 실제로 호출하는 것이 전역 스킬이더라도 자체 `.claude/gsd-core/`를 가진 프로젝트는 여전히 자신의 스펙을 얻습니다.
|
||||
|
||||
**설치 디렉터리 재정의:**
|
||||
|
||||
```bash
|
||||
|
||||
@@ -817,6 +817,8 @@ v1.40.0, [#2792](https://github.com/open-gsd/gsd-core/issues/2792)).
|
||||
/gsd-health --context # Triagem de utilização de contexto
|
||||
```
|
||||
|
||||
**Sombreamento de instalação entre escopos (`W028`).** Quando um runtime é instalado em ambos os escopos `global` e `local` e as regras de resolução de gatilhos do host tornam a superfície `/gsd-*` de um dos escopos inalcançável — o caso do Claude Code: a skill pessoal sempre vence o comando de projeto — a checagem de integridade adiciona um aviso de severidade WARNING nomeando os gatilhos sombreados, o escopo vencedor e o escopo perdedor. Isso nunca altera o status de aprovação/reprovação e nunca é corrigido automaticamente (não existe um único escopo correto a remover), então `--repair` nunca o toca. É idêntico ao mesmo aviso que o GSD Core imprime no momento da instalação.
|
||||
|
||||
### `/gsd-cleanup`
|
||||
|
||||
Arquiva diretórios de fases acumulados de milestones concluídos e poda branches locais cujo upstream foi excluído.
|
||||
|
||||
@@ -36,6 +36,8 @@ npx @opengsd/gsd-core@latest --claude --global
|
||||
|
||||
As habilidades são instaladas em `~/.claude/`. Os comandos aparecem como slash commands `/gsd-*` na sua próxima sessão do Claude Code. Reinicie o Claude Code para carregá-los.
|
||||
|
||||
**Instalação em ambos os escopos `--global` e `--local`.** Essa é uma configuração suportada, mas as próprias regras de resolução de gatilhos do Claude Code — escopo pessoal sobrepõe escopo de projeto, e uma skill sobrepõe um comando de mesmo nome — apontam para a mesma direção: a skill global sempre vence o gatilho `/gsd-<nome>` sobre o comando local. O GSD Core detecta isso e imprime qual escopo está vencendo logo após a instalação (e reporta o mesmo fato pelo `/gsd-health` como o diagnóstico `W028`); é um aviso, não uma falha — a instalação em si continua bem-sucedida. No escopo **global**, a referência da spec de workflow da skill vencedora é resolvida em tempo de execução em relação ao seu diretório de trabalho primeiro, então um projeto com seu próprio `.claude/gsd-core/` ainda obtém suas próprias specs mesmo que a skill global seja o que o Claude Code invoca.
|
||||
|
||||
**Substituir o diretório de instalação:**
|
||||
|
||||
```bash
|
||||
|
||||
@@ -99,6 +99,8 @@ Sources consulted:
|
||||
- Context7 /websites/code_claude
|
||||
- Context7 /llmstxt/code_claude_llms_txt
|
||||
|
||||
**Cross-scope trigger shadowing and spec-root reachability (#2873, epic #2866 Phase 4, resolving #2218).** GSD's claude `artifactLayout` installs `global=[skills]` and `local=[commands, agents]` (see "Trigger precedence" above). Claude Code's own documented precedence — personal overrides project, and a same-named skill overrides a same-named command — means both rules point the same direction when a user installs both scopes: the global skill always wins the `/gsd-<name>` trigger, and the project-local `.claude/gsd-core/` spec tree the local command correctly points at becomes unreachable through that trigger, silently. GSD Core now (a) detects this at install time and from `/gsd-health` (diagnostic `W028`) and prints which scope wins — an advisory only, exit code unchanged; and (b) for claude at **global** scope only, resolves the winning skill's own workflow-spec `@`-include at runtime rather than pre-expanding it: the skill body carries an explicit imperative instruction that resolves `.claude/gsd-core/workflows/<name>.md` relative to the working directory first, falling back to `~/.claude/gsd-core/workflows/<name>.md` when no local tree exists. This is instruction-following, not the guaranteed inclusion a real `@`-include provides — it costs the agent one file read — and is deliberately confined to this one reference, in this one runtime, at this one scope: the skill's `references/`/`templates/` includes and the local scope's own emission are unchanged. See [Interpret install-shadow warnings](../how-to/interpret-install-shadow-warnings.md) and [Install on your runtime — Claude Code](../how-to/install-on-your-runtime.md#claude-code).
|
||||
|
||||
---
|
||||
|
||||
## codex
|
||||
|
||||
@@ -814,6 +814,8 @@ ROADMAP.md 中阶段的 CRUD 操作 — 通过单一合并命令添加、插入
|
||||
/gsd-health --context # 上下文使用率分类
|
||||
```
|
||||
|
||||
**跨作用域安装遮蔽(`W028`)。** 当某个运行时同时安装在 `global` 和 `local` 两个作用域,且宿主的触发器解析规则使其中一个作用域的 `/gsd-*` 界面变得不可达——Claude Code 的情况:个人技能总是胜过项目命令——健康检查会添加一条 WARNING 级别的提示,指出被遮蔽的触发器、胜出的作用域以及落败的作用域。它从不改变健康检查的通过/失败状态,也从不会被自动修复(不存在唯一正确应移除的作用域),因此 `--repair` 永远不会处理它。这与 GSD Core 在安装时打印的提示完全相同。
|
||||
|
||||
### `/gsd-cleanup`
|
||||
|
||||
归档已完成里程碑中积累的阶段目录,并删除上游已删除的本地分支。
|
||||
|
||||
@@ -36,6 +36,8 @@ npx @opengsd/gsd-core@latest --claude --global
|
||||
|
||||
技能文件存放于 `~/.claude/`。下次 Claude Code 会话中,命令将以 `/gsd-*` 斜杠命令的形式出现。重启 Claude Code 以加载它们。
|
||||
|
||||
**同时在 `--global` 和 `--local` 两个作用域安装。** 这是受支持的配置(不同项目有时需要不同的自定义配置),但 Claude Code 自身的触发器解析规则——个人作用域覆盖项目作用域,且技能(skill)覆盖同名命令——都指向同一个方向:全局技能总是在 `/gsd-<name>` 触发器上胜过本地命令。GSD Core 会检测到这一点,并在安装完成后立即打印出哪个作用域胜出(并通过 `/gsd-health` 以诊断代码 `W028` 呈现相同的事实);这只是一条提示,不是失败——安装本身仍然会成功。在**全局**作用域下,胜出技能的工作流规范引用会在运行时优先相对于你的工作目录解析,因此即使 Claude Code 实际调用的是全局技能,拥有自己 `.claude/gsd-core/` 的项目仍然能获取到自己的规范。
|
||||
|
||||
**覆盖安装目录:**
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user