chore(gsd): delete 3 unreferenced dead files and orphaned test (#3728)

Phase 0 of #3631 — remove dead code before screaming architecture reorg.

- auto-observability.ts (72 LOC): zero imports anywhere in codebase
- rtk-status.ts (53 LOC): zero imports anywhere in codebase
- file-watcher.ts (100 LOC): zero imports anywhere in codebase
- file-watcher.test.ts: test for dead file-watcher.ts

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Iouri Goussev 2026-04-13 08:30:32 -04:00 committed by GitHub
parent 9e18dc46d7
commit 71f10a0d53
4 changed files with 0 additions and 373 deletions

View file

@ -1,72 +0,0 @@
/**
* Pre-dispatch observability checks for auto-mode units.
* Validates plan/summary file quality and builds repair instructions
* for the agent to fix gaps before proceeding with the unit.
*/
import type { ExtensionContext } from "@gsd/pi-coding-agent";
import {
validatePlanBoundary,
validateExecuteBoundary,
validateCompleteBoundary,
formatValidationIssues,
} from "./observability-validator.js";
import type { ValidationIssue } from "./observability-validator.js";
import { parseUnitId } from "./unit-id.js";
export async function collectObservabilityWarnings(
ctx: ExtensionContext,
basePath: string,
unitType: string,
unitId: string,
): Promise<ValidationIssue[]> {
// Hook units have custom artifacts — skip standard observability checks
if (unitType.startsWith("hook/")) return [];
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
if (!mid || !sid) return [];
let issues = [] as Awaited<ReturnType<typeof validatePlanBoundary>>;
if (unitType === "plan-slice") {
issues = await validatePlanBoundary(basePath, mid, sid);
} else if (unitType === "execute-task" && tid) {
issues = await validateExecuteBoundary(basePath, mid, sid, tid);
} else if (unitType === "complete-slice") {
issues = await validateCompleteBoundary(basePath, mid, sid);
}
if (issues.length > 0) {
ctx.ui.notify(
`Observability check (${unitType}) found ${issues.length} warning${issues.length === 1 ? "" : "s"}:\n${formatValidationIssues(issues)}`,
"warning",
);
}
return issues;
}
export function buildObservabilityRepairBlock(issues: ValidationIssue[]): string {
if (issues.length === 0) return "";
const items = issues.map(issue => {
const fileName = issue.file.split("/").pop() || issue.file;
let line = `- **${fileName}**: ${issue.message}`;
if (issue.suggestion) line += `${issue.suggestion}`;
return line;
});
return [
"",
"---",
"",
"## Pre-flight: Observability gaps to fix FIRST",
"",
"The following issues were detected in plan/summary files for this unit.",
"**Read each flagged file, apply the fix described, then proceed with the unit.**",
"",
...items,
"",
"---",
"",
].join("\n");
}

View file

@ -1,100 +0,0 @@
import type { FSWatcher } from "chokidar";
import type { EventBus } from "@gsd/pi-coding-agent";
import { relative } from "node:path";
let watcher: FSWatcher | null = null;
let pending = new Map<string, ReturnType<typeof setTimeout>>();
const EVENT_MAP: Record<string, string> = {
"settings.json": "settings-changed",
"auth.json": "auth-changed",
"models.json": "models-changed",
};
const EXTENSIONS_DIR = "extensions";
const IGNORED_PATTERNS = [
"**/sessions/**",
"**/*.tmp",
"**/*.swp",
"**/*~",
"**/.DS_Store",
];
const DEBOUNCE_MS = 300;
/**
* Start watching `agentDir` (e.g. `~/.gsd/agent/`) for config changes.
* Emits events on the supplied EventBus when watched files are modified.
*/
export async function startFileWatcher(
agentDir: string,
eventBus: EventBus,
): Promise<void> {
if (watcher) {
await watcher.close();
}
const { watch } = await import("chokidar");
pending = new Map<string, ReturnType<typeof setTimeout>>();
function debounceEmit(event: string): void {
const existing = pending.get(event);
if (existing) clearTimeout(existing);
pending.set(
event,
setTimeout(() => {
pending.delete(event);
eventBus.emit(event, { timestamp: Date.now() });
}, DEBOUNCE_MS),
);
}
function resolveEvent(filePath: string): string | null {
const rel = relative(agentDir, filePath);
if (rel.startsWith("..")) return null;
// Check direct file matches
for (const [file, event] of Object.entries(EVENT_MAP)) {
if (rel === file) return event;
}
// Check extensions directory
if (rel.startsWith(EXTENSIONS_DIR + "/") || rel === EXTENSIONS_DIR) {
return "extensions-changed";
}
return null;
}
watcher = watch(agentDir, {
ignoreInitial: true,
depth: 2,
ignored: IGNORED_PATTERNS,
});
for (const eventType of ["add", "change", "unlink"] as const) {
watcher.on(eventType, (filePath: string) => {
const event = resolveEvent(filePath);
if (event) debounceEmit(event);
});
}
// Wait for watcher to be ready
await new Promise<void>((resolve) => {
watcher!.on("ready", resolve);
});
}
/**
* Stop the file watcher and clean up resources.
*/
export async function stopFileWatcher(): Promise<void> {
for (const timer of pending.values()) clearTimeout(timer);
pending.clear();
if (watcher) {
await watcher.close();
watcher = null;
}
}

View file

@ -1,53 +0,0 @@
import type { ExtensionContext } from "@gsd/pi-coding-agent";
import {
ensureRtkSessionBaseline,
formatRtkSavingsLabel,
getRtkSessionSavings,
} from "../shared/rtk-session-stats.js";
import { loadEffectiveGSDPreferences } from "./preferences.js";
const STATUS_KEY = "gsd-rtk";
const REFRESH_INTERVAL_MS = 30_000;
let refreshTimer: ReturnType<typeof setInterval> | null = null;
function clearTimer(): void {
if (refreshTimer) {
clearInterval(refreshTimer);
refreshTimer = null;
}
}
function isRtkEnabledInPrefs(): boolean {
return loadEffectiveGSDPreferences()?.preferences.experimental?.rtk === true;
}
function updateStatus(ctx: ExtensionContext): void {
if (!ctx.hasUI) return;
if (!isRtkEnabledInPrefs()) return;
const basePath = ctx.cwd;
const sessionId = ctx.sessionManager.getSessionId();
ensureRtkSessionBaseline(basePath, sessionId);
const savings = getRtkSessionSavings(basePath, sessionId);
ctx.ui.setStatus(STATUS_KEY, formatRtkSavingsLabel(savings) ?? undefined);
}
export function startRtkStatusUpdates(ctx: ExtensionContext): void {
clearTimer();
if (!isRtkEnabledInPrefs()) {
// Ensure any previously set status is cleared (e.g. preference was toggled off)
ctx.ui.setStatus(STATUS_KEY, undefined);
return;
}
updateStatus(ctx);
if (!ctx.hasUI) return;
refreshTimer = setInterval(() => {
updateStatus(ctx);
}, REFRESH_INTERVAL_MS);
}
export function stopRtkStatusUpdates(ctx?: ExtensionContext): void {
clearTimer();
ctx?.ui.setStatus(STATUS_KEY, undefined);
}

View file

@ -1,148 +0,0 @@
import { test, afterEach } from "node:test";
import assert from "node:assert";
import { mkdtempSync, mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { setTimeout as delay } from "node:timers/promises";
import {
startFileWatcher,
stopFileWatcher,
} from "../resources/extensions/gsd/file-watcher.ts";
function createTempAgentDir(): string {
const tmp = mkdtempSync(join(tmpdir(), "gsd-fw-test-"));
mkdirSync(join(tmp, "extensions"), { recursive: true });
// Seed watched files so chokidar treats writes as "change" not "add"
writeFileSync(join(tmp, "settings.json"), "{}");
writeFileSync(join(tmp, "auth.json"), "{}");
writeFileSync(join(tmp, "models.json"), "{}");
return tmp;
}
function createMockEventBus() {
const events: { channel: string; data: unknown }[] = [];
return {
events,
emit(channel: string, data: unknown) {
events.push({ channel, data });
},
on(_channel: string, _handler: (data: unknown) => void) {
return () => {};
},
};
}
afterEach(async () => {
await stopFileWatcher();
});
test("startFileWatcher and stopFileWatcher run without errors", async () => {
const dir = createTempAgentDir();
const bus = createMockEventBus();
await startFileWatcher(dir, bus);
await stopFileWatcher();
});
test("stopFileWatcher is safe to call when no watcher is active", async () => {
await stopFileWatcher();
});
test("settings.json change emits settings-changed event", async () => {
const dir = createTempAgentDir();
const bus = createMockEventBus();
await startFileWatcher(dir, bus);
await delay(200);
writeFileSync(join(dir, "settings.json"), JSON.stringify({ updated: true }));
// Wait for debounce (300ms) + filesystem propagation
await delay(800);
const matched = bus.events.filter((e) => e.channel === "settings-changed");
assert.ok(matched.length > 0, "should emit settings-changed event");
});
test("auth.json change emits auth-changed event", async () => {
const dir = createTempAgentDir();
const bus = createMockEventBus();
await startFileWatcher(dir, bus);
// Allow watcher to fully initialize before writing
await delay(200);
writeFileSync(join(dir, "auth.json"), JSON.stringify({ token: "new" }));
await delay(800);
const matched = bus.events.filter((e) => e.channel === "auth-changed");
assert.ok(matched.length > 0, "should emit auth-changed event");
});
test("models.json change emits models-changed event", async () => {
const dir = createTempAgentDir();
const bus = createMockEventBus();
await startFileWatcher(dir, bus);
await delay(200);
writeFileSync(join(dir, "models.json"), JSON.stringify({ model: "new" }));
await delay(800);
const matched = bus.events.filter((e) => e.channel === "models-changed");
assert.ok(matched.length > 0, "should emit models-changed event");
});
test("extensions directory change emits extensions-changed event", { skip: process.platform === "win32" ? "chokidar subdirectory events are unreliable on Windows CI" : undefined }, async () => {
const dir = createTempAgentDir();
const bus = createMockEventBus();
await startFileWatcher(dir, bus);
await delay(500);
writeFileSync(
join(dir, "extensions", "my-ext.json"),
JSON.stringify({ name: "test" }),
);
await delay(2000);
const matched = bus.events.filter(
(e) => e.channel === "extensions-changed",
);
assert.ok(matched.length > 0, "should emit extensions-changed event");
});
test("unrelated file changes are ignored", async () => {
const dir = createTempAgentDir();
const bus = createMockEventBus();
await startFileWatcher(dir, bus);
// Wait for watcher to settle, then clear any residual events from setup
await delay(400);
bus.events.length = 0;
writeFileSync(join(dir, "random.txt"), "hello");
await delay(600);
assert.strictEqual(bus.events.length, 0, "should not emit any events");
});
test("debouncing coalesces rapid changes into one event", async () => {
const dir = createTempAgentDir();
const bus = createMockEventBus();
await startFileWatcher(dir, bus);
// Rapid-fire writes
for (let i = 0; i < 5; i++) {
writeFileSync(join(dir, "settings.json"), JSON.stringify({ i }));
}
await delay(800);
const matched = bus.events.filter((e) => e.channel === "settings-changed");
assert.strictEqual(
matched.length,
1,
"rapid changes should be debounced into a single event",
);
});