v1.13.8: system-prompt prefix stability verify-and-measure
Recon during planning disproved the original v1.13.7 (DB-cache) premise: buildSystemPrompt already runs over inputs mtime-cached at the file layer (BOOCHAT.md in system-prompt.ts:25, AGENTS.md global+per-project in agents.ts:245), and DB scalars are byte-stable until edited. The output is microsecond pure-string concat with no I/O. Skills aren't in the prefix; tools live in a separate request body field alpha-sorted by v1.13.3. This batch closes the verification gap with instrumentation, not implementation: - system-prompt.ts: buildSystemPromptWithFingerprint canonical impl computes SHA-256 over the assembled prefix, runs a per-session Map<sessionId, lastHash> observer, emits PrefixFingerprint per call and PrefixDrift (with field-level changed_inputs) on hash change. buildSystemPrompt is now a thin shim returning .prompt. - agents.ts: getAgentsMtimes accessor — cache-read only, no I/O. - payload.ts: buildMessagesPayload takes optional log argument; when passed, emits prefix-fingerprint (info) + prefix-drift (warn). - turn.ts + sentinel-summaries.ts: pass ctx.log at 3 production call sites; sentinel summaries log too so any drift across cap-hit / doom-loop paths surfaces. - system-prompt.test.ts: 4 new tests (byte-identical, no-drift-on- stable, drift-fires-with-changed-inputs, cross-session-no-drift). 194/194 tests pass (was 190). Smoke: 5 messages in a fresh session produced 7 prefix-fingerprint logs (extras from buildMessagesPayload being called from sentinel summary paths), all with identical prefix_hash and prefix_length=2907, zero prefix-drift. Prefix is byte-stable in steady-state. Decision: original system_prompt_cache DB table from the roadmap is permanently dropped. The v1.12.0 mtime caches at the input layer plus alpha tool ordering at the request body (v1.13.3) already address the load-bearing cache-stability surfaces. Instrumentation stays so the claim can be re-verified at any time.
This commit is contained in:
@@ -252,6 +252,22 @@ export function invalidateAgentsCache(projectPath?: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
// v1.13.8: cache-read accessor for the system-prompt prefix-fingerprint log.
|
||||
// Returns the AGENTS.md mtimes that getAgentsForProject() observed on its
|
||||
// last cache fill for this projectPath. Both fields are null when the cache
|
||||
// is cold (e.g. tests, fresh boot before the first inference turn). Does no
|
||||
// I/O — a fresh stat would race the cache and isn't what the fingerprint
|
||||
// wants anyway (we want what was actually used to resolve the agent).
|
||||
export function getAgentsMtimes(projectPath: string): {
|
||||
global: number | null;
|
||||
project: number | null;
|
||||
} {
|
||||
const key = projectPath || '__none__';
|
||||
const entry = cache.get(key);
|
||||
if (!entry) return { global: null, project: null };
|
||||
return { global: entry.globalMtime, project: entry.projectMtime };
|
||||
}
|
||||
|
||||
async function safeStat(path: string): Promise<number | null> {
|
||||
try {
|
||||
const s = await fs.stat(path);
|
||||
|
||||
Reference in New Issue
Block a user