# Tech Debt Tracker

## Notification event classification — text matching only

**Impact:** `src/headless-events.ts` classifies events (blocked, milestone-ready, auto-stopped) by regex against stderr text. Fragile: any wording change in a notification breaks classification silently.

**Proposed fix:** Implement structured `source`/`kind`/`blocking` metadata per notification-event-model.md. Update headless event parser to use typed fields.

**Verification:** Remove string-match classifiers; confirm headless exit-code logic still triggers correctly via integration test.

**Tracked in:** [active/index.md — Notification Event Model](./active/index.md)

---

## External workflow mutations — RPC/headless only

**Impact:** External orchestrators must advance SF through native SF commands, headless/RPC, or the daemon/RPC client path. SF must not expose workflow mutation tools through MCP.

**Proposed fix:** Extract shared handlers from native tools behind an internal command/RPC boundary. Keep ADR-008 rejected: do not build or restore an SF MCP server.

**Verification:** A daemon/RPC session completes a task through the native `sf_task_complete` path and produces the same DB/projection outcome as interactive SF.

**Tracked in:** [ADR-008 tombstone](../dev/ADR-008-IMPLEMENTATION-PLAN.md)

---

## No ADR template or generation recipes

**Impact:** Every ADR is hand-authored from scratch. No enforced schema means some ADRs omit falsifiers, status dates, or sequencing. No `just adr` recipe means the numbering is manual.

**Proposed fix:** Add `docs/dev/ADR-TEMPLATE.md` with required sections (Status, Date, Context, Options, Decision, Consequences, Falsifiers, Verification). Add `just adr <number> <slug>` recipe that stamps the template.

**Verification:** `just adr 019 my-decision` produces `docs/dev/ADR-019-my-decision.md` with all required section headings.

---

## Parallel milestone state locking — file-based, ad-hoc

**Impact:** Concurrent milestone execution uses ad-hoc file locks on STATE.md and roadmap.md. Race condition possible under heavy parallelism; not blocking for serial execution (current default).

**Proposed fix:** SQLite database in `.sf/sf.db` with atomic transactions for all state mutations. Deferred to ADR-018 Phase 1+.

**Verification:** Two milestone workers simultaneously completing tasks produce consistent STATE.md with no lost updates.

**Tracked in:** [ADR-018](../dev/ADR-018-repo-native-harness-evolution.md) sequencing stage 1.

---

## write-gate BASH_READ_ONLY_RE — monolithic regex

**Location:** `src/resources/extensions/sf/bootstrap/write-gate.ts`

**Impact:** 30+ command patterns are encoded in a single 900-character regex. Adding a new safe command requires editing the regex inline, with no unit coverage per command. Risk of subtle regex alternation bugs.

**Proposed fix:** Replace with a data-driven allowlist (array of patterns with names and comments) that the gate compiles at startup. Each entry is individually testable.

**Verification:** `write-gate.test.ts` achieves per-command coverage without a single monolithic regex match test.

---

## ADR-018 runtime — harness profiler not yet wired

**Impact:** `repo-profiler.ts` exists but is not called during any autonomous dispatch phase. The harness evolution system (ADR-018) exists only as design documentation; no runtime behavior has shipped.

**Proposed fix:** Wire `buildRepoProfile()` call into the pre-dispatch phase (Phase 1). Record result in `.sf/sf.db`.

**Verification:** After any planning milestone, `.sf/sf.db` contains a `repo_profiles` row for the current session.

**Tracked in:** [active/index.md — ADR-018 Phase 1](./active/index.md)

---

## Memory subsystem extraction into swappable sub-extension

**Location:** `src/resources/extensions/sf/memory-store.ts`, `src/resources/extensions/sf/memory-extractor.ts`, `src/resources/extensions/sf/memory-relations.ts`, `src/resources/extensions/sf/memory-sleeper.ts`

**Impact:** SF's memory subsystem (separate from singularity-memory, which serves hermes/ACE) is coupled directly into SF core. Plugging in a different backend — e.g. a vchord-in-docker container for local vector search — is harder than it needs to be.

**Proposed fix:** Extract the four files above into a sub-extension at `src/resources/extensions/sf-memory/` behind a small backend interface, so SF can swap implementations without touching core.

**When to do it:** Defer until a real backend-swap requirement appears (e.g. SF actually needs vector search). Not blocking.

**Estimated effort:** Small — these files have clean module boundaries already.
