* refactor(#1191): inject clock/reset testability seams + handle valid-null settings - worktree-safety reapOrphanWorktrees: injectable deps.nowMs clock for deterministic stale-lock boundary tests (mirrors snapshotWorktreeInventory's options.nowMs). - active-workstream-store: _resetControllingTtyCacheForTests() seam clears the memoized controlling-TTY probe cache; test replaces require.cache busting. - gen-capability-registry: export stripGeneratedComment (additive); test imports the real helper + equivalence assertion, keeping the deliberate drift oracle. - install.js readSettings: a successfully-parsed JSON null is treated as empty settings ({}) instead of being mis-reported as malformed; genuine parse failures still warn. readSettings/stripJsonComments exported (GSD_TEST_MODE-guarded require) for real behavioral tests. Closes #1191 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#1191): add changeset for valid-null settings fix (#1233) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#1191): replace Stryker-incompatible structural reset test with behavioral isTTY-spy The seam-2 reset test read the BUILT active-workstream-store.cjs and grepped for 'didProbeControllingTtyToken = false' — Stryker instruments that file so the literal is absent, failing the mutation DRY RUN. Replaced with a behavioral test that spies on process.stdin.isTTY access count to prove a post-reset probe re-runs (kills the didProbe-reset mutant) without reading source text. Local stryker: dry run passes, score 85.21% >= 80. 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:
@@ -930,13 +930,11 @@ function readSettings(settingsPath) {
|
||||
if (fs.existsSync(settingsPath)) {
|
||||
try {
|
||||
const raw = fs.readFileSync(settingsPath, 'utf8');
|
||||
let parsed;
|
||||
// Try standard JSON first (fast path)
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch {
|
||||
// Fall back to JSONC stripping
|
||||
return JSON.parse(stripJsonComments(raw));
|
||||
}
|
||||
try { parsed = JSON.parse(raw); }
|
||||
catch { parsed = JSON.parse(stripJsonComments(raw)); }
|
||||
return parsed === null ? {} : parsed; // valid JSON null = empty settings, not malformed
|
||||
} catch (e) {
|
||||
// If even JSONC stripping fails, warn instead of silently returning {}
|
||||
console.warn(' ' + yellow + '⚠' + reset + ' Warning: Could not parse ' + settingsPath + ' — file may be malformed. Existing settings preserved.');
|
||||
@@ -12260,6 +12258,9 @@ module.exports = {
|
||||
parseConfigDirFromArgs,
|
||||
cleanupLegacyGsdCc,
|
||||
_applyRuntimeRewrites,
|
||||
// #1191 — exported so tests exercise the REAL readSettings, not a replica
|
||||
readSettings,
|
||||
stripJsonComments,
|
||||
...runtimeArtifactConversion,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user