Files
msd-core/docs/INVENTORY-MANIFEST.json
Tom Boucher 95d2bc20f8 feat(hooks): opt-in SessionStart update banner for non-statusline users (#2795) (#3035)
* feat(hooks): opt-in SessionStart update banner for non-statusline users (#2795)

When a user declines (or keeps a non-GSD) statusline at install time, the
installer now offers an opt-in SessionStart banner that surfaces GSD update
availability. The banner reads the existing
~/.cache/gsd/gsd-update-check.json cache (written by
gsd-check-update-worker.js) and emits a single systemMessage line only when
update_available is true:

    GSD update available: <installed> → <latest>. Run /gsd-update.

It is silent when up-to-date and rate-limits "check failed" diagnostics to
once per 24h via a sentinel file so a corrupt cache doesn't nag every
session. Removed cleanly by `npx get-shit-done-cc --uninstall` which strips
both the script and the SessionStart entry. The banner is never offered when
GSD's statusline is being installed (statusline already surfaces update
info, so re-prompting would be noise).

Implementation:
- hooks/gsd-update-banner.js — pure functions buildBannerOutput,
  shouldSuppressFailureWarning, readCache; thin main() wires them.
- bin/install.js — handleUpdateBanner() prompt, parseUpdateBannerInput(),
  buildUpdateBannerHookEntry(), buildUpdateBannerPromptText(); chained into
  installAllRuntimes() so finalize() receives both flags. updateBannerCommand
  computed alongside the other JS-hook commands; finishInstall() registers
  the SessionStart entry only when shouldInstallBanner === true and the
  hook file is present at the target.
- Hook ships in scripts/build-hooks.js HOOKS_TO_COPY, listed in
  MANAGED_HOOKS for stale-detection in gsd-check-update-worker.js, in the
  uninstall hook-removal lists in install.js, and in the
  rewriteLegacyManagedNodeHookCommands allowlist.

Tests:
- tests/feat-2795-update-banner.test.cjs — 22 tests, structural-IR
  assertions on parsed JSON envelopes (no raw-text matching). Covers
  pure-function branches (cache present/absent, parseError, rate-limit
  suppression, missing version fields), end-to-end hook invocation against
  fixture cache states, and install.js wiring (prompt text, input parsing,
  hook entry shape).
- tests/trae-install.test.cjs — updated install() return-shape assertion to
  include updateBannerCommand: null for the no-settings runtime.
- 6881/6881 tests pass.

Docs (bundled in same commit per the bundle-docs-with-code skill):
- docs/USER-GUIDE.md — new "Surface GSD Update Notifications Without GSD's
  Statusline" task section with opt-in/opt-out instructions.
- docs/FEATURES.md — REQ-HOOK-08 added; "Update Banner" subsection under
  the Hook System feature with cache flow + removal path.
- docs/INVENTORY.md — hook count 11 → 12, new row for gsd-update-banner.js.
- docs/INVENTORY-MANIFEST.json — regenerated.

Closes #2795

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(install): gate banner prompt on actual installability (CR #3035)

CodeRabbit findings on PR #3035:

- bin/install.js (Major): continueAfterStatusline gated banner prompt on
  the raw `shouldInstallStatusline` flag from handleStatusline. But
  finishInstall later silently skips the statusline write on local
  installs unless --force-statusline is set (#2248). Two consequences:
    1. Interactive local Claude/Gemini installs got neither a statusline
       nor a banner offer.
    2. Codex/Cursor/Copilot/Windsurf/Trae/Cline-only installs (where
       every result.updateBannerCommand is null) still got prompted even
       though the choice was silently ignored.
  Fix: derive willInstallStatusline = shouldInstallStatusline &&
  (isGlobal || forceStatusline), and gate the banner prompt on a
  canInstallBanner precondition computed from results[].updateBannerCommand.
  Pass the raw shouldInstallStatusline through to finalize unchanged so
  per-runtime statusline gating in finishInstall is unaffected.

- tests/feat-2795-update-banner.test.cjs (Minor): rate-limit suppression
  test parsed r1.stdout without first asserting r1.status === 0. Other
  e2e tests in this file (lines 210, 241) do this. A non-zero exit would
  surface as a cryptic SyntaxError instead of a status assertion failure.
  Fix applied verbatim.

6881/6881 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 16:33:16 -04:00

305 lines
7.5 KiB
JSON

{
"generated": "2026-05-02",
"families": {
"agents": [
"gsd-advisor-researcher",
"gsd-ai-researcher",
"gsd-assumptions-analyzer",
"gsd-code-fixer",
"gsd-code-reviewer",
"gsd-codebase-mapper",
"gsd-debug-session-manager",
"gsd-debugger",
"gsd-doc-classifier",
"gsd-doc-synthesizer",
"gsd-doc-verifier",
"gsd-doc-writer",
"gsd-domain-researcher",
"gsd-eval-auditor",
"gsd-eval-planner",
"gsd-executor",
"gsd-framework-selector",
"gsd-integration-checker",
"gsd-intel-updater",
"gsd-nyquist-auditor",
"gsd-pattern-mapper",
"gsd-phase-researcher",
"gsd-plan-checker",
"gsd-planner",
"gsd-project-researcher",
"gsd-research-synthesizer",
"gsd-roadmapper",
"gsd-security-auditor",
"gsd-ui-auditor",
"gsd-ui-checker",
"gsd-ui-researcher",
"gsd-user-profiler",
"gsd-verifier"
],
"commands": [
"/gsd-add-tests",
"/gsd-ai-integration-phase",
"/gsd-audit-fix",
"/gsd-audit-milestone",
"/gsd-audit-uat",
"/gsd-autonomous",
"/gsd-capture",
"/gsd-cleanup",
"/gsd-code-review",
"/gsd-complete-milestone",
"/gsd-config",
"/gsd-debug",
"/gsd-discuss-phase",
"/gsd-docs-update",
"/gsd-eval-review",
"/gsd-execute-phase",
"/gsd-explore",
"/gsd-extract-learnings",
"/gsd-fast",
"/gsd-forensics",
"/gsd-graphify",
"/gsd-health",
"/gsd-help",
"/gsd-import",
"/gsd-inbox",
"/gsd-ingest-docs",
"/gsd-manager",
"/gsd-map-codebase",
"/gsd-milestone-summary",
"/gsd-new-milestone",
"/gsd-new-project",
"/gsd-ns-context",
"/gsd-ns-ideate",
"/gsd-ns-manage",
"/gsd-ns-project",
"/gsd-ns-review",
"/gsd-ns-workflow",
"/gsd-pause-work",
"/gsd-phase",
"/gsd-plan-phase",
"/gsd-plan-review-convergence",
"/gsd-pr-branch",
"/gsd-profile-user",
"/gsd-progress",
"/gsd-quick",
"/gsd-resume-work",
"/gsd-review",
"/gsd-review-backlog",
"/gsd-secure-phase",
"/gsd-settings",
"/gsd-ship",
"/gsd-sketch",
"/gsd-spec-phase",
"/gsd-spike",
"/gsd-stats",
"/gsd-thread",
"/gsd-ui-phase",
"/gsd-ui-review",
"/gsd-ultraplan-phase",
"/gsd-undo",
"/gsd-update",
"/gsd-validate-phase",
"/gsd-verify-work",
"/gsd-workspace",
"/gsd-workstreams"
],
"workflows": [
"add-phase.md",
"add-tests.md",
"add-todo.md",
"ai-integration-phase.md",
"analyze-dependencies.md",
"audit-fix.md",
"audit-milestone.md",
"audit-uat.md",
"autonomous.md",
"check-todos.md",
"cleanup.md",
"code-review-fix.md",
"code-review.md",
"complete-milestone.md",
"diagnose-issues.md",
"discovery-phase.md",
"discuss-phase-assumptions.md",
"discuss-phase-power.md",
"discuss-phase.md",
"do.md",
"docs-update.md",
"edit-phase.md",
"eval-review.md",
"execute-phase.md",
"execute-plan.md",
"explore.md",
"extract_learnings.md",
"fast.md",
"forensics.md",
"graduation.md",
"health.md",
"help.md",
"import.md",
"inbox.md",
"ingest-docs.md",
"insert-phase.md",
"list-phase-assumptions.md",
"list-workspaces.md",
"manager.md",
"map-codebase.md",
"milestone-summary.md",
"new-milestone.md",
"new-project.md",
"new-workspace.md",
"next.md",
"node-repair.md",
"note.md",
"pause-work.md",
"plan-milestone-gaps.md",
"plan-phase.md",
"plan-review-convergence.md",
"plant-seed.md",
"pr-branch.md",
"profile-user.md",
"progress.md",
"quick.md",
"reapply-patches.md",
"remove-phase.md",
"remove-workspace.md",
"research-phase.md",
"resume-project.md",
"review.md",
"scan.md",
"secure-phase.md",
"session-report.md",
"settings-advanced.md",
"settings-integrations.md",
"settings.md",
"ship.md",
"sketch-wrap-up.md",
"sketch.md",
"spec-phase.md",
"spike-wrap-up.md",
"spike.md",
"stats.md",
"sync-skills.md",
"transition.md",
"ui-phase.md",
"ui-review.md",
"ultraplan-phase.md",
"undo.md",
"update.md",
"validate-phase.md",
"verify-phase.md",
"verify-work.md"
],
"references": [
"agent-contracts.md",
"ai-evals.md",
"ai-frameworks.md",
"artifact-types.md",
"autonomous-smart-discuss.md",
"checkpoints.md",
"common-bug-patterns.md",
"context-budget.md",
"continuation-format.md",
"debugger-philosophy.md",
"decimal-phase-calculation.md",
"doc-conflict-engine.md",
"domain-probes.md",
"executor-examples.md",
"gate-prompts.md",
"gates.md",
"git-integration.md",
"git-planning-commit.md",
"ios-scaffold.md",
"mandatory-initial-read.md",
"model-profile-resolution.md",
"model-profiles.md",
"phase-argument-parsing.md",
"planner-antipatterns.md",
"planner-chunked.md",
"planner-gap-closure.md",
"planner-reviews.md",
"planner-revision.md",
"planner-source-audit.md",
"planning-config.md",
"project-skills-discovery.md",
"questioning.md",
"revision-loop.md",
"scout-codebase.md",
"sketch-interactivity.md",
"sketch-theme-system.md",
"sketch-tooling.md",
"sketch-variant-patterns.md",
"tdd.md",
"thinking-models-debug.md",
"thinking-models-execution.md",
"thinking-models-planning.md",
"thinking-models-research.md",
"thinking-models-verification.md",
"thinking-partner.md",
"ui-brand.md",
"universal-anti-patterns.md",
"user-profiling.md",
"verification-overrides.md",
"verification-patterns.md",
"workstream-flag.md"
],
"cli_modules": [
"artifacts.cjs",
"audit.cjs",
"command-aliases.generated.cjs",
"commands.cjs",
"config-schema.cjs",
"config.cjs",
"context-utilization.cjs",
"core.cjs",
"decisions.cjs",
"docs.cjs",
"drift.cjs",
"frontmatter.cjs",
"gap-checker.cjs",
"graphify.cjs",
"gsd2-import.cjs",
"init-command-router.cjs",
"init.cjs",
"install-profiles.cjs",
"intel.cjs",
"learnings.cjs",
"milestone.cjs",
"model-profiles.cjs",
"phase-command-router.cjs",
"phase.cjs",
"phases-command-router.cjs",
"planning-workspace.cjs",
"profile-output.cjs",
"profile-pipeline.cjs",
"roadmap-command-router.cjs",
"roadmap.cjs",
"schema-detect.cjs",
"secrets.cjs",
"security.cjs",
"state-command-router.cjs",
"state.cjs",
"template.cjs",
"uat.cjs",
"validate-command-router.cjs",
"verify-command-router.cjs",
"verify.cjs",
"workstream.cjs"
],
"hooks": [
"gsd-check-update-worker.js",
"gsd-check-update.js",
"gsd-context-monitor.js",
"gsd-phase-boundary.sh",
"gsd-prompt-guard.js",
"gsd-read-guard.js",
"gsd-read-injection-scanner.js",
"gsd-session-state.sh",
"gsd-statusline.js",
"gsd-update-banner.js",
"gsd-validate-commit.sh",
"gsd-workflow-guard.js"
]
}
}