* feat(#1451): wire gsd capability install/update/remove/list/disable/enable CLI ADR-1244 D5/D6: the management command was built as a library (capability-lifecycle.cjs install/upgrade/remove + capability-ledger.cjs) across Phases 3-5 but never wired to a user-facing command — gsd-tools.cjs 'capability' only handled state/set. This adds the six subcommands, dispatching to the existing lifecycle/ledger: - install <spec> [--integrity] [--scope global|project] [--yes] [--shared-file <rel>]… - update [<id>|--all] [--scope] [--yes] [--shared-file] (re-resolves recorded source) - remove <id> [--purge-data] [--scope] (first-party rejected) - list [--json] (first-party + overlay, both scopes, JSON array) - disable|enable <id> (activation-state alias of capability set --off/--on) Scope→runtimeDir mapping matches capability-loader exactly (global=$GSD_HOME||home, project=project root; caps at <root>/.gsd/capabilities/<id>, ledger at <root>/.gsd-capabilities.json). Consent is non-interactive: --yes grants; without it an executable install aborts after printing the disclosure and writes nothing. Best-effort reconcile before each mutation. Tests: tests/capability-cli.test.cjs (20 behavioral, real resolver via local specs, GSD_HOME-sandboxed) — install consent/block/usage matrix, list, update round-trip, remove round-trip + first-party guard, disable/enable, unknown subcommand. Docs: docs/reference/gsd-capability-command.md reconciled to the real surface (ledger paths, --shared-file, consent model, disable mechanism, outdated marked planned); docs/COMMANDS.md gains the gsd capability entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#1451): resolve adversarial-review findings + root-cause the --raw silent-output bug Adversarial-review (Codex) fixes: - capReadStrict passes a malformed strict_known_registries value THROUGH so the trust gate fail-closes on it (was silently downgrading to permissive) - installCapability/upgradeCapability gain an expectedId guard + first-party-id rejection (capability-lifecycle.cts): an overlay can't shadow a first-party id, and 'update <id>' can't act on a different id if the recorded source was retargeted - capability update: prints the consent disclosure, exits non-zero on --all partial failure, no longer masks the resolved id - capability remove: ledger-first ordering so an overlay is removable even if it shadows a first-party name; first-party guard only fires for ids not in the ledger - gsd-capability-command.md: disable/enable doc corrected (registry-known ids; overlay toggle not yet wired through this path) Silent-output bug (root cause, not waved off as pre-existing): - captureStdoutSyncWrites buffered fd-1 output and DISCARDED it on the throw path — any --raw command that emitted a result/error envelope then threw (to set a non-zero exit) lost ALL of stdout. Now it flushes the captured buffer before re-throwing (exit code preserved). - cmdCapabilitySet threw via process.exit() (bypassing the capture wrapper entirely); now throws ExitError so the wrapper flushes — matches the repo's no-process-exit architecture. - Regression test: capability disable <unknown> --raw must emit the JSON error envelope on stdout. Verified: capability suite 165/165, @file/json-errors/phase 183/183, lint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#1451): address adversarial-review R2 — shared-file confinement, MCP no-clobber, config fail-closed - confinedSharedFile(): realpath-confine every shared-config write/strip to the scope root (mirrors safeRmUnder), so a --shared-file whose parent is a symlink escaping the scope can't write outside it. - mcpServers shared edits: never overwrite an UNOWNED entry — a name collision with the user's (or another capability's) server is skipped, so install/remove can't silently clobber user MCP config (hooks already append; the map-keyed mcpServers path was the gap). - capReadStrict: a PRESENT-but-unparseable .planning/config.json now fails CLOSED (lockdown) instead of silently downgrading the strict_known_registries policy to permissive. - Tests: symlink-escape shared-file writes nothing outside scope; colliding user mcpServers entry preserved; unparseable config blocks an external install. capability suite 83/83, lint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#1451): address code-review — aborted-status robustness + coverage + project-scoped strict doc - install/update: handle an 'aborted' result independently of the requiresConsent flag so it can never fall through to the generic 'blocked: unknown reason' arm (aborted always means consent-needed per the lifecycle contract; latent today, hardened for future status additions). - Clarify capResolveScope comment (project scope === already-resolved cwd) and document that strict_known_registries is a PROJECT-scoped policy (read regardless of --scope; no machine-wide allowlist) in gsd-capability-command.md. - Tests: update --all over an empty ledger returns an empty result set (exit 0); a flag value that looks like another flag (--integrity --scope) is rejected, not swallowed. CLI suite 33/33, lint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(#1451): FEATURES.md entry #147 + Added/Fixed changesets for the capability CLI Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#1451): backfill changeset PR number → #1457 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3,9 +3,11 @@
|
||||
> **Slash form:** `gsd:capability` (surfaced as a slash command on slash-command runtimes)
|
||||
> **CLI form:** `gsd capability`
|
||||
> **Canonical ADR:** [ADR-1244](../adr/1244-capability-ecosystem.md)
|
||||
> **See also:** [Capability Manifest Reference](capability-manifest.md) · [How to develop a capability](../how-to/develop-a-capability.md)
|
||||
> **See also:** [Capability Manifest Reference](capability-manifest.md) · [How to develop a capability](../how-to/develop-a-capability.md) · [The capability trust model](../explanation/capability-trust-model.md)
|
||||
|
||||
The `capability` family manages the installation, upgrade, removal, and inspection of GSD capabilities — both first-party and third-party overlays. A row for this command also appears in [docs/COMMANDS.md](../COMMANDS.md) (that file is not edited here).
|
||||
The `capability` family manages the installation, upgrade, removal, and inspection of GSD capabilities — both first-party (shipped) and third-party overlays. A row for this command also appears in [docs/COMMANDS.md](../COMMANDS.md) (that file is not edited here).
|
||||
|
||||
**Implemented in 1.6.0:** `install`, `update`, `remove`, `list`, `disable`, `enable` (plus the pre-existing `state` and `set` introspection/activation subcommands). **Planned (not yet implemented):** `outdated` — see [Planned subcommands](#planned-subcommands).
|
||||
|
||||
---
|
||||
|
||||
@@ -16,7 +18,7 @@ The `capability` family manages the installation, upgrade, removal, and inspecti
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability install <spec> [--integrity sha512-<hash>] [--scope global|project] [--yes]
|
||||
gsd capability install <spec> [--integrity sha512-<hash>] [--scope global|project] [--yes] [--shared-file <rel>]…
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
@@ -30,16 +32,19 @@ gsd capability install <spec> [--integrity sha512-<hash>] [--scope global|projec
|
||||
| Flag | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `--integrity` | `sha512-<base64>` | — | SHA-512 bundle hash to verify before extraction. When supplied, a mismatch aborts the install. When the source registry or `capability.json` already carries an `integrity` field, both must agree. |
|
||||
| `--scope` | `global` \| `project` | `global` | Installation root. `global` writes to `~/.gsd/capabilities/<id>/`; `project` writes to `.gsd/capabilities/<id>/` in the current working directory. |
|
||||
| `--yes` | flag | off | Suppress the interactive consent prompt. The executable-surface disclosure is still printed; consent is taken as granted. |
|
||||
| `--scope` | `global` \| `project` | `global` | Installation root (see [Install layout](#install-layout)). |
|
||||
| `--yes` | flag | off | Grant consent for the capability's executable surfaces non-interactively. The disclosure is still printed. Without it, an install that declares executable surfaces is **aborted** after printing the disclosure (the CLI is non-interactive — there is no prompt to answer). |
|
||||
| `--shared-file` | path (repeatable) | — | A file, **relative to the scope root**, into which the capability's disclosed hooks / MCP servers should be spliced (e.g. a runtime's `settings.json`). Each fragment is marker-isolated so `remove` can strip exactly it. When omitted, the bundle still installs (declaratively); no shared-file edits are made. |
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Resolves `<spec>` to a versioned, staged capability bundle. The pipeline is: fetch → verify integrity or SHA pin → check `engines.gsd` against the installed GSD version → disclose executable surfaces (hooks, command modules) → obtain consent (unless `--yes`) → validate the incoming manifest against conformance invariants over the merged first-party ∪ existing-overlay ∪ new set → extract to the scope root → write the ledger entry atomically.
|
||||
Resolves `<spec>` to a versioned, staged capability bundle. The pipeline is: fetch → verify integrity or SHA pin → check `engines.gsd` against the installed GSD version → disclose executable surfaces (hooks, command modules, MCP servers) → obtain consent (a declarative capability needs none; an executable one requires `--yes`) → validate the incoming manifest against the trust invariants → extract to the scope root → write the ledger entry atomically.
|
||||
|
||||
An overlay whose `id` collides with a first-party capability `id`, or that claims a skill or agent stem already owned, is rejected before extraction. Install never executes capability code; staging is copy-only.
|
||||
An overlay whose `id` uses a reserved first-party prefix (`gsd-`, `gsd-core-`, `anthropic-`) is rejected before extraction. Install never executes capability code; staging is copy-only. A declined install (executable surface, no `--yes`) writes **nothing** — no bundle, no ledger entry, no shared-file edits.
|
||||
|
||||
The ledger file (`~/.claude/.gsd-capabilities.json` for the global scope on the Claude runtime, and analogues per runtime) records the installed version, source, integrity hash, owned files, and any fragments written into shared files (e.g. hook registrations in `settings.json`).
|
||||
A best-effort reconciliation sweep runs before the mutation to recover any crash orphans from a prior interrupted operation.
|
||||
|
||||
The ledger file (`<scope-root>/.gsd-capabilities.json`, see [Install layout](#install-layout)) records the installed version, source, integrity hash, owned files, and any fragments written into shared files.
|
||||
|
||||
---
|
||||
|
||||
@@ -48,70 +53,39 @@ The ledger file (`~/.claude/.gsd-capabilities.json` for the global scope on the
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability update [<id> | --all]
|
||||
gsd capability update [<id> | --all] [--scope global|project] [--yes] [--shared-file <rel>]…
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
| Argument | Description |
|
||||
|---|---|
|
||||
| `<id>` | Capability identifier to update. Omitting both `<id>` and `--all` is an error. |
|
||||
| `<id>` | Capability identifier to update. Omitting both `<id>` and `--all` is an error; passing both is an error. |
|
||||
|
||||
**Flags**
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--all` | Update every installed overlay capability that has a newer version available from its original source. |
|
||||
| `--all` | Re-resolve and update **every** installed overlay capability in the chosen scope. |
|
||||
| `--scope` | Scope root to operate in (`global` default; see [Install layout](#install-layout)). |
|
||||
| `--yes` | Grant consent when the new version's executable set differs from the previously consented one. |
|
||||
| `--shared-file` | As for `install` — where to splice the (re-derived) hook / MCP fragments. |
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Fetches the latest version (or the newest version satisfying `engines.gsd`) from the capability's recorded source. Follows the atomic stage-then-swap pattern: the new bundle is fully staged, verified, and validated before the ledger write commits the swap. A crash during staging leaves the previous version intact. A crash after the ledger write leaves the new version intact; a reconciliation sweep on next run resolves any orphaned files.
|
||||
Re-resolves the capability's **recorded source** (the `source` stored in its ledger entry at install time) and, if the resolved version differs, performs an atomic stage-then-swap: the new bundle is fully staged, verified, and validated before the ledger write commits the swap. A crash during staging leaves the previous version intact; a crash after the ledger write leaves the new version intact, and a reconciliation sweep on the next run resolves any orphaned files.
|
||||
|
||||
When `--all` is used, update availability is source-dependent:
|
||||
For third-party capabilities, a version whose executable set (hooks, command modules, MCP servers) differs from the previously consented version requires `--yes` to re-consent before the swap completes; without it the update is aborted and the old version is left fully intact.
|
||||
|
||||
| Source kind | Update detection |
|
||||
`--all` iterates every ledger entry in the scope and reports a per-capability outcome (`upgraded` / `not_installed` / `aborted` / `blocked`). Update availability is source-dependent:
|
||||
|
||||
| Source kind | Re-resolution behaviour |
|
||||
|---|---|
|
||||
| `<name>@<registry>` | Registry catalogue query |
|
||||
| git (`https://…/repo.git#<tag>`) | Remote tag fetch |
|
||||
| npm (`npm:@org/pkg@<range>`) | `npm dist-tags` query |
|
||||
| tarball (`https://…/cap-x.y.z.tgz`) | Not auto-detectable; requires manual `install` with the new URL |
|
||||
| local (`./local/path`) | Not auto-detectable |
|
||||
|
||||
For third-party capabilities, auto-update is **off** by default. When auto-update is enabled, a version whose executable set (hooks, command modules) differs from the previously consented version triggers a re-prompt before the swap completes.
|
||||
|
||||
---
|
||||
|
||||
### `outdated`
|
||||
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability outdated
|
||||
```
|
||||
|
||||
**Flags**
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--json` | Emit a JSON array instead of the default table. |
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Queries the source of each installed overlay capability and reports those for which a newer version is available. Capabilities installed from tarball or local-path sources are listed as `"unknown"` for latest version.
|
||||
|
||||
**`--json` output shape**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "string",
|
||||
"current": "semver",
|
||||
"latest": "semver | \"unknown\"",
|
||||
"source": "string",
|
||||
"scope": "global | project"
|
||||
}
|
||||
]
|
||||
```
|
||||
| npm (`npm:@org/pkg@<range>`) | `npm dist-tags` / range resolution |
|
||||
| tarball (`https://…/cap-x.y.z.tgz`) | Re-fetch of the recorded URL |
|
||||
| local (`./local/path`) | Re-read of the recorded filesystem path |
|
||||
|
||||
---
|
||||
|
||||
@@ -120,7 +94,7 @@ Queries the source of each installed overlay capability and reports those for wh
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability remove <id> [--purge-data]
|
||||
gsd capability remove <id> [--purge-data] [--scope global|project]
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
@@ -133,13 +107,14 @@ gsd capability remove <id> [--purge-data]
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--purge-data` | Also remove any data files created by the capability at runtime (artefacts under the capability's declared paths that are not part of the install bundle itself). |
|
||||
| `--purge-data` | Also remove data files created by the capability at runtime (artefacts under the capability's declared paths that are not part of the install bundle). |
|
||||
| `--scope` | Scope root to remove from (`global` default). |
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Reads the ledger entry for `<id>` and removes exactly: the owned files listed in `files`, and the fragments written into shared files listed in `sharedEdits` (e.g. hook registrations spliced into `settings.json`). Shared files are not deleted; only the capability's fragments are stripped. The ledger entry is removed atomically after all file operations complete.
|
||||
Reads the ledger entry for `<id>` and removes exactly: the owned files listed in `files`, and the fragments written into shared files listed in `sharedEdits` (e.g. hook registrations spliced into a `settings.json`). Shared files themselves are not deleted; only the capability's marker-isolated fragments are stripped. The ledger entry is removed atomically after all file operations complete.
|
||||
|
||||
First-party capabilities (shipped with GSD) cannot be removed via this subcommand; the entire product uninstall path (`gsd --uninstall`) handles first-party removal.
|
||||
First-party capabilities (shipped with GSD) **cannot** be removed via this subcommand — `remove` rejects a first-party `id` and points at the product uninstaller (`gsd --uninstall`).
|
||||
|
||||
---
|
||||
|
||||
@@ -148,18 +123,12 @@ First-party capabilities (shipped with GSD) cannot be removed via this subcomman
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability disable <id>
|
||||
gsd capability disable <id> [--config-dir <path>] [--runtime <r>] [--scope <s>]
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
| Argument | Description |
|
||||
|---|---|
|
||||
| `<id>` | Identifier of an installed capability to disable. |
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Marks the capability as disabled in the ledger. A disabled capability is present on disk but excluded from the runtime overlay; it is skipped by the registry loader and contributes no hooks, config keys, or loop extension registrations. The ledger entry is preserved; `enable` reverses the operation without re-fetching.
|
||||
Marks the capability **inactive** in the runtime activation state — identical to `gsd capability set <id> --off`. A disabled capability stays on disk; it is excluded from the active surface and contributes no hooks, config keys, or loop extension registrations until re-enabled. This toggles the capability-state layer (the runtime config), not the install ledger. The id must be a capability known to the registry; activation toggling of an installed **third-party overlay** by id is not yet wired through this path — remove an overlay with `gsd capability remove`. `enable` reverses a disable without re-fetching.
|
||||
|
||||
---
|
||||
|
||||
@@ -168,18 +137,12 @@ Marks the capability as disabled in the ledger. A disabled capability is present
|
||||
**Synopsis**
|
||||
|
||||
```
|
||||
gsd capability enable <id>
|
||||
gsd capability enable <id> [--config-dir <path>] [--runtime <r>] [--scope <s>]
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
| Argument | Description |
|
||||
|---|---|
|
||||
| `<id>` | Identifier of a previously disabled capability to enable. |
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Clears the disabled flag in the ledger entry for `<id>`. On the next GSD invocation, the capability is included in the runtime overlay subject to its `engines.gsd` range. If the GSD version has changed since the capability was disabled, the `engines.gsd` check is re-evaluated at load time; an incompatible capability is skipped with a warning.
|
||||
Clears the inactive flag for `<id>` in the runtime activation state — identical to `gsd capability set <id> --on`. On the next GSD invocation the capability is included in the active surface again, subject to its `engines.gsd` range (an incompatible capability is still skipped with a warning at load time).
|
||||
|
||||
---
|
||||
|
||||
@@ -195,25 +158,25 @@ gsd capability list [--json]
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--json` | Emit a JSON array instead of the default table. |
|
||||
| `--json` | Emit the JSON array explicitly. (In 1.6.0 `list` always emits JSON; a formatted table is planned.) |
|
||||
|
||||
**Behaviour**
|
||||
|
||||
Lists all capabilities visible to the current GSD session: first-party capabilities (shipped with GSD) and installed overlay capabilities in both global and project scopes. Disabled capabilities are included with a `disabled` status.
|
||||
Lists capabilities visible to the current session: first-party capabilities (from the registry) plus installed overlay capabilities in both the `global` and `project` scopes. Emits a JSON array of descriptors.
|
||||
|
||||
**`--json` output shape**
|
||||
**Output shape**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "string",
|
||||
"role": "feature | runtime",
|
||||
"version": "semver",
|
||||
"tier": "core | standard | full",
|
||||
"source": "first-party | string",
|
||||
"role": "feature | runtime | null",
|
||||
"version": "semver | null",
|
||||
"tier": "core | standard | full | null",
|
||||
"source": "first-party | <recorded source string>",
|
||||
"scope": "first-party | global | project",
|
||||
"status": "active | disabled | incompatible",
|
||||
"title": "string"
|
||||
"status": "active | incompatible",
|
||||
"title": "string | null"
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -222,9 +185,20 @@ Lists all capabilities visible to the current GSD session: first-party capabilit
|
||||
|
||||
| Value | Meaning |
|
||||
|---|---|
|
||||
| `active` | Loaded and contributing to the current session. |
|
||||
| `disabled` | Present in the ledger but excluded via `gsd capability disable`. |
|
||||
| `incompatible` | `engines.gsd` range does not satisfy the current GSD version; skipped with a warning at load time. |
|
||||
| `active` | Present and (for overlays) compatible with the running GSD version. |
|
||||
| `incompatible` | An overlay whose `engines.gsd` range does not satisfy the current GSD version; skipped with a warning at load time. |
|
||||
|
||||
> Whether a capability has been turned off via `disable` is reported by `gsd capability state` (the activation-state view), not by `list`.
|
||||
|
||||
---
|
||||
|
||||
## Planned subcommands
|
||||
|
||||
These appear in ADR-1244's command surface but are **not implemented in 1.6.0**. They are documented here so the surface is explicit; invoking them returns the unknown-subcommand error listing the available set.
|
||||
|
||||
| Subcommand | Intended behaviour |
|
||||
|---|---|
|
||||
| `outdated` | Query each installed overlay's source and report those with a newer version available (`--json` for machine output). Until it ships, `update --all` re-resolves every recorded source and reports what changed. |
|
||||
|
||||
---
|
||||
|
||||
@@ -238,19 +212,21 @@ The `install` subcommand accepts the following source specification forms.
|
||||
| Git URL with tag | `https://github.com/org/repo.git#v1.2.0` | Git — clones/fetches at the specified tag; `#sha:<40-hex>` pins a specific commit. |
|
||||
| npm package | `npm:@org/gsd-capability-foo@^1.0.0` | npm — resolves via `npm dist-tags` / semver range; installs with `--ignore-scripts`. |
|
||||
| Tarball URL | `https://host/path/cap-x.y.z.tgz` | Tarball — fetches over HTTPS, verifies SHA-512 when `--integrity` is supplied. |
|
||||
| Local path | `./local/path` | Local — copies from the filesystem path relative to the current working directory. Auto-update and `outdated` detection are not available for this form. |
|
||||
| Local path | `./local/path` (or an absolute path) | Local — copies from the filesystem path. Auto-update detection is not available for this form. |
|
||||
|
||||
All forms pass through the same pipeline: fetch → verify integrity or SHA pin → check `engines.gsd` → obtain consent → validate → extract → record ledger.
|
||||
Which source forms are *permitted* is governed by the `capabilities.strict_known_registries` policy (see [Configuration](../CONFIGURATION.md) and [the capability trust model](../explanation/capability-trust-model.md)): `null`/absent is permissive, `[]` is lockdown (no third-party sources), and a host allowlist permits only matching registries. This policy is **project-scoped** — it is read from the current project's `.planning/config.json` and applied to installs run in that project regardless of `--scope`; there is no machine-wide source allowlist. (A present-but-unparseable config fails **closed** — external installs are blocked until it is fixed.)
|
||||
|
||||
All permitted forms pass through the same pipeline: fetch → verify integrity or SHA pin → check `engines.gsd` → obtain consent → validate → extract → record ledger.
|
||||
|
||||
---
|
||||
|
||||
## Install layout
|
||||
|
||||
Installed overlay capabilities are written to one of two roots, depending on `--scope`:
|
||||
Installed overlay capabilities are written under a **scope root** selected by `--scope`:
|
||||
|
||||
| Scope | Root path | Ledger file |
|
||||
|---|---|---|
|
||||
| `global` | `~/.gsd/capabilities/<id>/` | Per-runtime, e.g. `~/.claude/.gsd-capabilities.json` |
|
||||
| `project` | `.gsd/capabilities/<id>/` (CWD) | Per-runtime, adjacent to project root |
|
||||
| Scope | Scope root | Bundle path | Ledger file |
|
||||
|---|---|---|---|
|
||||
| `global` | `$GSD_HOME`, defaulting to your home directory | `<root>/.gsd/capabilities/<id>/` | `<root>/.gsd-capabilities.json` |
|
||||
| `project` | the current project root | `<root>/.gsd/capabilities/<id>/` | `<root>/.gsd-capabilities.json` |
|
||||
|
||||
The ledger is the commit point for installs and upgrades. Its entries record the installed version, original source URL, integrity hash, owned files, and shared-file edits. A reconciliation sweep on the next GSD run resolves crash orphans (files on disk without a ledger entry, or ledger entries with missing files).
|
||||
The ledger is the commit point for installs and upgrades. Its entries record the installed version, original source, integrity hash, owned files, and shared-file edits. A reconciliation sweep on the next GSD run resolves crash orphans (files on disk without a ledger entry, or ledger entries with missing files). These paths are exactly the ones the runtime registry overlay reads when composing installed capabilities, so an `install` is visible to the loop without any further step.
|
||||
|
||||
Reference in New Issue
Block a user