mirror of
https://github.com/glittercowboy/get-shit-done
synced 2026-04-25 17:25:23 +02:00
Bug #2453: After tsc builds sdk/dist/cli.js, npm install -g from a local directory does not chmod the bin-script target (unlike tarball extraction). The file lands at mode 644, the gsd-sdk symlink points at a non-executable file, and command -v gsd-sdk fails on every first install. Fix: explicitly chmodSync(cliPath, 0o755) immediately after npm install -g completes, mirroring the pattern used for hook files throughout the installer. Bug #2451: gsd-context-monitor warning messages over-reported usage by ~13 percentage points vs CC native /context. Root cause: gsd-statusline.js wrote a buffer-normalized used_pct (accounting for the 16.5% autocompact reserve) to the bridge file, inflating values. The bridge used_pct is now raw (Math.round(100 - remaining_percentage)), consistent with what CC's native /context command reports. The statusline progress bar continues to display the normalized value; only the bridge value changes. Updated the existing #2219 tests to check the normalized display via hook stdout rather than bridge.used_pct, and added a new assertion that bridge.used_pct is raw. Closes #2453 Closes #2451 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
89 lines
3.7 KiB
JavaScript
89 lines
3.7 KiB
JavaScript
/**
|
|
* Regression test for bug #2453
|
|
*
|
|
* installSdkIfNeeded() builds sdk/dist/cli.js via `tsc` then runs
|
|
* `npm install -g .`. TypeScript emits files at process umask (0o644) and
|
|
* npm install from a local directory does NOT chmod bin-script targets the
|
|
* way tarball extraction does. The result: the globally-installed
|
|
* dist/cli.js lands with mode 644 (non-executable), the `gsd-sdk` symlink
|
|
* points at a non-executable file, and `command -v gsd-sdk` fails on every
|
|
* new install.
|
|
*
|
|
* Fix: after `npm install -g .`, the installer must explicitly
|
|
* `chmodSync(cliPath, 0o755)` on the installed dist/cli.js. This mirrors
|
|
* the pattern already used four times in install.js for hook files.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const { test, describe } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
const INSTALL_SRC = path.join(__dirname, '..', 'bin', 'install.js');
|
|
|
|
describe('bug #2453: installSdkIfNeeded chmods sdk dist/cli.js to 0o755', () => {
|
|
let installSrc;
|
|
|
|
test('install.js source exists', () => {
|
|
assert.ok(fs.existsSync(INSTALL_SRC), 'bin/install.js must exist');
|
|
installSrc = fs.readFileSync(INSTALL_SRC, 'utf-8');
|
|
});
|
|
|
|
test('installSdkIfNeeded contains a chmodSync call for dist/cli.js', () => {
|
|
installSrc = installSrc || fs.readFileSync(INSTALL_SRC, 'utf-8');
|
|
|
|
// Locate the installSdkIfNeeded function body
|
|
const fnStart = installSrc.indexOf('function installSdkIfNeeded()');
|
|
assert.ok(fnStart !== -1, 'installSdkIfNeeded function must exist in install.js');
|
|
|
|
// Find the end of the function (next top-level function declaration)
|
|
const fnEnd = installSrc.indexOf('\nfunction ', fnStart + 1);
|
|
const fnBody = fnEnd !== -1 ? installSrc.slice(fnStart, fnEnd) : installSrc.slice(fnStart);
|
|
|
|
// Must chmod dist/cli.js to make it executable after npm install -g .
|
|
const hasChmod = fnBody.includes('chmodSync') && fnBody.includes('dist/cli.js');
|
|
assert.ok(
|
|
hasChmod,
|
|
'installSdkIfNeeded must call chmodSync on dist/cli.js after npm install -g . ' +
|
|
'(tsc emits 644; npm does not chmod bin targets from local dir installs — ' +
|
|
'root cause of #2453: gsd-sdk symlink target is non-executable on first install)'
|
|
);
|
|
});
|
|
|
|
test('chmodSync for dist/cli.js uses mode 0o755', () => {
|
|
installSrc = installSrc || fs.readFileSync(INSTALL_SRC, 'utf-8');
|
|
|
|
const fnStart = installSrc.indexOf('function installSdkIfNeeded()');
|
|
const fnEnd = installSrc.indexOf('\nfunction ', fnStart + 1);
|
|
const fnBody = fnEnd !== -1 ? installSrc.slice(fnStart, fnEnd) : installSrc.slice(fnStart);
|
|
|
|
// The chmod call must use 0o755 (executable), not 0o644
|
|
const has755 = fnBody.includes('0o755') && fnBody.includes('dist/cli.js');
|
|
assert.ok(
|
|
has755,
|
|
'chmodSync for dist/cli.js must use mode 0o755 to make the binary executable'
|
|
);
|
|
});
|
|
|
|
test('chmodSync appears after npm install -g . step', () => {
|
|
installSrc = installSrc || fs.readFileSync(INSTALL_SRC, 'utf-8');
|
|
|
|
const fnStart = installSrc.indexOf('function installSdkIfNeeded()');
|
|
const fnEnd = installSrc.indexOf('\nfunction ', fnStart + 1);
|
|
const fnBody = fnEnd !== -1 ? installSrc.slice(fnStart, fnEnd) : installSrc.slice(fnStart);
|
|
|
|
const npmGlobalIdx = fnBody.indexOf("'install', '-g', '.'");
|
|
const chmodIdx = fnBody.indexOf('chmodSync');
|
|
|
|
assert.ok(npmGlobalIdx !== -1, "npm install -g . step must be present in installSdkIfNeeded");
|
|
assert.ok(chmodIdx !== -1, 'chmodSync must be present in installSdkIfNeeded');
|
|
assert.ok(
|
|
chmodIdx > npmGlobalIdx,
|
|
'chmodSync must appear AFTER the npm install -g . step ' +
|
|
'(the file to chmod does not exist until npm installs it globally)'
|
|
);
|
|
});
|
|
});
|