gsd-lite 0.7.4 → 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,7 +13,7 @@
13
13
  "name": "gsd",
14
14
  "source": "./",
15
15
  "description": "AI orchestration tool — GSD management shell + Superpowers quality core. 5 commands, 4 agents, 5 workflows, MCP server, context monitoring.",
16
- "version": "0.7.4",
16
+ "version": "0.7.5",
17
17
  "keywords": [
18
18
  "orchestration",
19
19
  "mcp",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gsd",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "AI orchestration tool for Claude Code — GSD management shell + Superpowers quality core",
5
5
  "author": {
6
6
  "name": "sdsrss",
@@ -63,33 +63,17 @@ function runChainCLI(args) {
63
63
  }
64
64
 
65
65
  /**
66
- * Register GSD as a provider in the composite statusline registry.
67
- * Prefers code-graph's statusline-chain.js CLI when available; falls back to
68
- * writing the cache registry directly for older code-graph versions.
69
- * Idempotent: updates existing entry or inserts before code-graph.
70
- * @param {string} statuslineScriptPath - Absolute path to gsd-statusline.cjs
71
- * @returns {boolean} true if registered/updated
66
+ * Rewrite a single registry file to its desired state: exactly one canonical
67
+ * `{id: 'gsd', ...}` entry with the given command, dropping every other entry
68
+ * whose command references gsd-statusline (e.g. ghost `_previous` entries
69
+ * left by code-graph's composite-takeover). Canonical entry is placed before
70
+ * `code-graph` for display priority.
71
+ *
72
+ * Returns true if the registry is now in the desired state (including
73
+ * idempotent no-op), false if the file can't be parsed as an array.
72
74
  */
73
- function registerProvider(statuslineScriptPath) {
74
- const command = `node ${JSON.stringify(statuslineScriptPath)}`;
75
- if (runChainCLI(['register', 'gsd', command, '--stdin'])) return true;
76
-
77
- let registryPath = findCompositeRegistry();
78
-
79
- // If composite statusLine is configured but registry file is missing,
80
- // create it if the parent directory exists (e.g., code-graph installed
81
- // but registry was deleted or not yet created).
82
- if (!registryPath) {
83
- for (const candidate of REGISTRY_PATHS) {
84
- const dir = path.dirname(candidate);
85
- if (fs.existsSync(dir)) {
86
- registryPath = candidate;
87
- break;
88
- }
89
- }
90
- if (!registryPath) return false;
91
- }
92
-
75
+ function normalizeRegistryFile(registryPath, canonicalCommand) {
76
+ const canonical = { id: 'gsd', command: canonicalCommand, needsStdin: true };
93
77
  try {
94
78
  let registry;
95
79
  try {
@@ -99,24 +83,24 @@ function registerProvider(statuslineScriptPath) {
99
83
  }
100
84
  if (!Array.isArray(registry)) return false;
101
85
 
102
- const provider = { id: 'gsd', command, needsStdin: true };
86
+ // Drop every entry pointing at gsd-statusline, regardless of id. This
87
+ // catches the canonical `gsd` slot AND ghosts like `_previous` that
88
+ // code-graph's id-scoped chain CLI `register` can't see.
89
+ const nonGsd = registry.filter(
90
+ e => !(e.command || '').includes('gsd-statusline'),
91
+ );
103
92
 
104
- // Find existing GSD entry (by id or command)
105
- const idx = registry.findIndex(p =>
106
- p.id === 'gsd' || p.command?.includes('gsd-statusline'));
93
+ const cgIdx = nonGsd.findIndex(e => e.id === 'code-graph');
94
+ if (cgIdx >= 0) nonGsd.splice(cgIdx, 0, canonical);
95
+ else nonGsd.unshift(canonical);
107
96
 
108
- if (idx >= 0) {
109
- registry[idx] = provider;
110
- } else {
111
- // Insert before code-graph for display priority
112
- const cgIdx = registry.findIndex(p => p.id === 'code-graph');
113
- if (cgIdx >= 0) registry.splice(cgIdx, 0, provider);
114
- else registry.unshift(provider);
115
- }
97
+ // Skip write if already in desired state (idempotent re-install).
98
+ const before = JSON.stringify(registry);
99
+ const after = JSON.stringify(nonGsd);
100
+ if (before === after) return true;
116
101
 
117
- // Atomic write
118
102
  const tmp = registryPath + `.${process.pid}-${Date.now()}.tmp`;
119
- fs.writeFileSync(tmp, JSON.stringify(registry, null, 2) + '\n');
103
+ fs.writeFileSync(tmp, JSON.stringify(nonGsd, null, 2) + '\n');
120
104
  fs.renameSync(tmp, registryPath);
121
105
  return true;
122
106
  } catch {
@@ -124,6 +108,37 @@ function registerProvider(statuslineScriptPath) {
124
108
  }
125
109
  }
126
110
 
111
+ /**
112
+ * Register GSD as a provider in the composite statusline registry.
113
+ *
114
+ * Calls code-graph's statusline-chain.js CLI when available, THEN post-scrubs
115
+ * every known registry path. The CLI's `register gsd <cmd>` is id-scoped and
116
+ * silently leaves ghost entries (e.g. `_previous` whose command is our
117
+ * gsd-statusline but whose id isn't `gsd`) in place — that caused
118
+ * double-rendering after upgrades where code-graph had previously promoted a
119
+ * top-level GSD statusLine to `_previous`. Post-normalization guarantees
120
+ * exactly one canonical `gsd` entry per registry regardless of which path
121
+ * succeeded.
122
+ *
123
+ * @param {string} statuslineScriptPath - Absolute path to gsd-statusline.cjs
124
+ * @returns {boolean} true if registered or normalized in at least one registry
125
+ */
126
+ function registerProvider(statuslineScriptPath) {
127
+ const command = `node ${JSON.stringify(statuslineScriptPath)}`;
128
+ const cliOk = runChainCLI(['register', 'gsd', command, '--stdin']);
129
+
130
+ let anyNormalized = false;
131
+ for (const candidate of REGISTRY_PATHS) {
132
+ // Only touch paths whose parent dir exists — don't create arbitrary
133
+ // ~/.cache/ subtrees on machines without code-graph.
134
+ const dir = path.dirname(candidate);
135
+ if (!fs.existsSync(dir)) continue;
136
+ if (normalizeRegistryFile(candidate, command)) anyNormalized = true;
137
+ }
138
+
139
+ return cliOk || anyNormalized;
140
+ }
141
+
127
142
  /**
128
143
  * Remove GSD entry from composite statusline registry.
129
144
  * Prefers code-graph's statusline-chain.js CLI when available; falls back to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gsd-lite",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "AI orchestration tool for Claude Code — GSD management shell + Superpowers quality core",
5
5
  "type": "module",
6
6
  "bin": {