fix: resolve 5 deployment blockers (runtime-fallback race, hashline legacy, tmux spawn, db open)
- runtime-fallback: guard session.error with sessionRetryInFlight to prevent double-advance during active retry; expand session.stop abort to include sessionAwaitingFallbackResult; remove premature pendingFallbackModel clearing from auto-retry finally block - hashline-edit: add HASHLINE_LEGACY_REF_PATTERN for backward-compatible LINE:HEX dual-parse in parseLineRef and normalizeLineRef - tmux-subagent: defer session on null queryWindowState; unconditionally re-queue deferred session on spawn failure (not just close+spawn) - ultrawork-db: wrap new Database(dbPath) in try/catch to handle corrupted DB - event: add try/catch guards around model-fallback logic in message.updated, session.status, and session.error handlers
This commit is contained in:
@@ -8,3 +8,4 @@ export const HASHLINE_DICT = Array.from({ length: 256 }, (_, i) => {
|
||||
|
||||
export const HASHLINE_REF_PATTERN = /^([0-9]+)#([ZPMQVRWSNKTXJBYH]{2})$/
|
||||
export const HASHLINE_OUTPUT_PATTERN = /^([0-9]+)#([ZPMQVRWSNKTXJBYH]{2}):(.*)$/
|
||||
export const HASHLINE_LEGACY_REF_PATTERN = /^([0-9]+):([0-9a-fA-F]{2,})$/
|
||||
|
||||
@@ -52,3 +52,46 @@ describe("validateLineRef", () => {
|
||||
expect(() => validateLineRef(lines, "1#ZZ")).toThrow(/current hash/)
|
||||
})
|
||||
})
|
||||
|
||||
describe("legacy LINE:HEX backward compatibility", () => {
|
||||
it("parses legacy LINE:HEX ref", () => {
|
||||
//#given
|
||||
const ref = "42:ab"
|
||||
|
||||
//#when
|
||||
const result = parseLineRef(ref)
|
||||
|
||||
//#then
|
||||
expect(result).toEqual({ line: 42, hash: "ab" })
|
||||
})
|
||||
|
||||
it("parses legacy LINE:HEX ref with uppercase hex", () => {
|
||||
//#given
|
||||
const ref = "10:FF"
|
||||
|
||||
//#when
|
||||
const result = parseLineRef(ref)
|
||||
|
||||
//#then
|
||||
expect(result).toEqual({ line: 10, hash: "FF" })
|
||||
})
|
||||
|
||||
it("legacy ref fails validation with hash mismatch, not parse error", () => {
|
||||
//#given
|
||||
const lines = ["function hello() {"]
|
||||
|
||||
//#when / #then
|
||||
expect(() => validateLineRef(lines, "1:ab")).toThrow(/Hash mismatch|current hash/)
|
||||
})
|
||||
|
||||
it("extracts legacy ref from content with markers", () => {
|
||||
//#given
|
||||
const ref = ">>> 42:ab|const x = 1"
|
||||
|
||||
//#when
|
||||
const result = parseLineRef(ref)
|
||||
|
||||
//#then
|
||||
expect(result).toEqual({ line: 42, hash: "ab" })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
import { computeLineHash } from "./hash-computation"
|
||||
import { HASHLINE_REF_PATTERN } from "./constants"
|
||||
import { HASHLINE_REF_PATTERN, HASHLINE_LEGACY_REF_PATTERN } from "./constants"
|
||||
|
||||
export interface LineRef {
|
||||
line: number
|
||||
hash: string
|
||||
}
|
||||
|
||||
const LINE_REF_EXTRACT_PATTERN = /([0-9]+#[ZPMQVRWSNKTXJBYH]{2})/
|
||||
const LINE_REF_EXTRACT_PATTERN = /([0-9]+#[ZPMQVRWSNKTXJBYH]{2}|[0-9]+:[0-9a-fA-F]{2,})/
|
||||
|
||||
function normalizeLineRef(ref: string): string {
|
||||
const trimmed = ref.trim()
|
||||
if (HASHLINE_REF_PATTERN.test(trimmed)) {
|
||||
return trimmed
|
||||
}
|
||||
if (HASHLINE_LEGACY_REF_PATTERN.test(trimmed)) {
|
||||
return trimmed
|
||||
}
|
||||
|
||||
const extracted = trimmed.match(LINE_REF_EXTRACT_PATTERN)
|
||||
if (extracted) {
|
||||
@@ -25,15 +28,22 @@ function normalizeLineRef(ref: string): string {
|
||||
export function parseLineRef(ref: string): LineRef {
|
||||
const normalized = normalizeLineRef(ref)
|
||||
const match = normalized.match(HASHLINE_REF_PATTERN)
|
||||
if (!match) {
|
||||
throw new Error(
|
||||
`Invalid line reference format: "${ref}". Expected format: "LINE#ID" (e.g., "42#VK")`
|
||||
)
|
||||
if (match) {
|
||||
return {
|
||||
line: Number.parseInt(match[1], 10),
|
||||
hash: match[2],
|
||||
}
|
||||
}
|
||||
return {
|
||||
line: Number.parseInt(match[1], 10),
|
||||
hash: match[2],
|
||||
const legacyMatch = normalized.match(HASHLINE_LEGACY_REF_PATTERN)
|
||||
if (legacyMatch) {
|
||||
return {
|
||||
line: Number.parseInt(legacyMatch[1], 10),
|
||||
hash: legacyMatch[2],
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
`Invalid line reference format: "${ref}". Expected format: "LINE#ID" (e.g., "42#VK")`
|
||||
)
|
||||
}
|
||||
|
||||
export function validateLineRef(lines: string[], ref: string): void {
|
||||
|
||||
Reference in New Issue
Block a user