mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 10:27:33 +00:00
Stop validation work once preparation cannot be reused
This commit is contained in:
@@ -169,14 +169,21 @@ export class CodexHookLaunchPreparation {
|
||||
return run()
|
||||
}
|
||||
let complete = false
|
||||
const result = await withFileContentObservation(before.files, before.paths, async () => {
|
||||
const status = await run(() => {
|
||||
complete = true
|
||||
})
|
||||
// This read also validates the last exact publications against the observation scope.
|
||||
const after = readCodexLaunchPreparationInputs(homePath)
|
||||
return { status, stable: after?.digest === before.digest }
|
||||
})
|
||||
const result = await withFileContentObservation(
|
||||
before.files,
|
||||
before.paths,
|
||||
async (isStillValid) => {
|
||||
const status = await run(() => {
|
||||
complete = true
|
||||
})
|
||||
// This read also validates the last exact publications against the observation scope.
|
||||
const stable =
|
||||
complete &&
|
||||
isStillValid() &&
|
||||
readCodexLaunchPreparationInputs(homePath, isStillValid)?.digest === before.digest
|
||||
return { status, stable }
|
||||
}
|
||||
)
|
||||
if (complete && result.matches && result.value.stable && digest !== null) {
|
||||
this.completedLaunchPrep.set(key, { digest, status: { ...result.value.status } })
|
||||
if (this.completedLaunchPrep.size > 32) {
|
||||
|
||||
@@ -28,7 +28,8 @@ export type CodexLaunchPreparationInputs = {
|
||||
|
||||
/** Unknown inputs only prevent reuse; preparation retains its existing error/retry behavior. */
|
||||
export function readCodexLaunchPreparationInputs(
|
||||
runtimeHomePath: string
|
||||
runtimeHomePath: string,
|
||||
isStillValid: () => boolean = () => true
|
||||
): CodexLaunchPreparationInputs | null {
|
||||
try {
|
||||
const systemHome = getSystemCodexHomePath()
|
||||
@@ -41,13 +42,22 @@ export function readCodexLaunchPreparationInputs(
|
||||
observeResolvedFilePath(kind, input, output)
|
||||
}
|
||||
for (const home of homes) {
|
||||
if (!isStillValid()) {
|
||||
return null
|
||||
}
|
||||
const resolvedHome = resolveHome(home)
|
||||
facts.push([home, resolvedHome])
|
||||
recordPath('marketplace-home', home, resolvedHome)
|
||||
recordPath('daemon-home', home, resolvedHome)
|
||||
for (const leaf of ['config.toml', 'hooks.json']) {
|
||||
if (!isStillValid()) {
|
||||
return null
|
||||
}
|
||||
const filePath = join(home, leaf)
|
||||
files.push(snapshotFile(filePath, facts))
|
||||
if (!isStillValid()) {
|
||||
return null
|
||||
}
|
||||
const writePath =
|
||||
leaf === 'hooks.json'
|
||||
? resolveHooksJsonWritePath(filePath)
|
||||
@@ -73,8 +83,14 @@ export function readCodexLaunchPreparationInputs(
|
||||
getLegacyCodexProfileTomlPath(),
|
||||
getManagedScriptPath()
|
||||
]) {
|
||||
if (!isStillValid()) {
|
||||
return null
|
||||
}
|
||||
files.push(snapshotFile(filePath, facts))
|
||||
}
|
||||
if (!isStillValid()) {
|
||||
return null
|
||||
}
|
||||
const scriptPath = getManagedScriptPath()
|
||||
// A mode repair is not a fixed point, even if another writer undoes chmod before the final read.
|
||||
const scriptMode = statSync(scriptPath).mode & 0o777
|
||||
@@ -87,6 +103,9 @@ export function readCodexLaunchPreparationInputs(
|
||||
recordPath('toml-write', legacyPath, legacyWritePath)
|
||||
facts.push([`${legacyWritePath}.bak`, entryType(`${legacyWritePath}.bak`)])
|
||||
facts.push([...paths], files)
|
||||
if (!isStillValid()) {
|
||||
return null
|
||||
}
|
||||
return { digest: digestFileContent(JSON.stringify(facts)), files, paths }
|
||||
} catch {
|
||||
return null
|
||||
|
||||
@@ -30,7 +30,7 @@ export function digestFileContent(content: string | Uint8Array): string {
|
||||
export async function withFileContentObservation<T>(
|
||||
files: readonly ObservedFileContent[],
|
||||
paths: ReadonlyMap<string, string>,
|
||||
run: () => Promise<T>
|
||||
run: (isStillValid: () => boolean) => Promise<T>
|
||||
): Promise<{ value: T; matches: boolean }> {
|
||||
const expected = new Map<string, { digest: string | null }>()
|
||||
for (const file of files) {
|
||||
@@ -39,7 +39,7 @@ export async function withFileContentObservation<T>(
|
||||
const key = fileKey(alias)
|
||||
if (expected.has(key)) {
|
||||
// Ambiguous aliases cannot prove which file an operation processed.
|
||||
return { value: await run(), matches: false }
|
||||
return { value: await run(() => false), matches: false }
|
||||
}
|
||||
expected.set(key, entry)
|
||||
}
|
||||
@@ -52,7 +52,7 @@ export async function withFileContentObservation<T>(
|
||||
}
|
||||
return observations.run(observation, async () => {
|
||||
try {
|
||||
const value = await run()
|
||||
const value = await run(() => observation.open && observation.matches)
|
||||
return { value, matches: observation.matches }
|
||||
} finally {
|
||||
observation.open = false
|
||||
@@ -64,7 +64,7 @@ export async function withFileContentObservation<T>(
|
||||
|
||||
export function observeFileDigest(filePath: string, digest: string | null): void {
|
||||
const observation = observations.getStore()
|
||||
if (!observation?.open) {
|
||||
if (!observation?.open || !observation.matches) {
|
||||
return
|
||||
}
|
||||
const expected = observation.files.get(fileKey(filePath))
|
||||
@@ -75,7 +75,7 @@ export function observeFileDigest(filePath: string, digest: string | null): void
|
||||
|
||||
export function observeFileContent(filePath: string, content: string | Uint8Array): void {
|
||||
const observation = observations.getStore()
|
||||
if (!observation?.open || !observation.files.has(fileKey(filePath))) {
|
||||
if (!observation?.open || !observation.matches || !observation.files.has(fileKey(filePath))) {
|
||||
return
|
||||
}
|
||||
observeFileDigest(filePath, digestFileContent(content))
|
||||
@@ -83,7 +83,7 @@ export function observeFileContent(filePath: string, content: string | Uint8Arra
|
||||
|
||||
export function observeFileReadError(filePath: string, error: unknown): void {
|
||||
const observation = observations.getStore()
|
||||
if (!observation?.open || !observation.files.has(fileKey(filePath))) {
|
||||
if (!observation?.open || !observation.matches || !observation.files.has(fileKey(filePath))) {
|
||||
return
|
||||
}
|
||||
if (isDefinitiveAbsence(error)) {
|
||||
@@ -95,7 +95,7 @@ export function observeFileReadError(filePath: string, error: unknown): void {
|
||||
|
||||
export function invalidateFileObservation(filePath: string): void {
|
||||
const observation = observations.getStore()
|
||||
if (observation?.open && observation.files.has(fileKey(filePath))) {
|
||||
if (observation?.open && observation.matches && observation.files.has(fileKey(filePath))) {
|
||||
observation.matches = false
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ export function observeFilePublication(
|
||||
content: string | Uint8Array | null
|
||||
): void {
|
||||
const observation = observations.getStore()
|
||||
if (!observation?.open) {
|
||||
if (!observation?.open || !observation.matches) {
|
||||
return
|
||||
}
|
||||
const expected = observation.files.get(fileKey(filePath))
|
||||
@@ -116,7 +116,7 @@ export function observeFilePublication(
|
||||
|
||||
export function observeResolvedFilePath(kind: string, input: string, resolved: string): string {
|
||||
const observation = observations.getStore()
|
||||
if (!observation?.open) {
|
||||
if (!observation?.open || !observation.matches) {
|
||||
return resolved
|
||||
}
|
||||
const expected = observation.paths.get(`${kind}\0${input}`)
|
||||
@@ -130,6 +130,7 @@ export function observeResolvedFilePathError(kind: string, input: string, error:
|
||||
const observation = observations.getStore()
|
||||
if (
|
||||
observation?.open &&
|
||||
observation.matches &&
|
||||
observation.paths.has(`${kind}\0${input}`) &&
|
||||
!isDefinitiveAbsence(error)
|
||||
) {
|
||||
@@ -140,7 +141,7 @@ export function observeResolvedFilePathError(kind: string, input: string, error:
|
||||
export function observedExistsSync(filePath: string): boolean {
|
||||
const present = existsSync(filePath)
|
||||
const observation = observations.getStore()
|
||||
if (observation?.open) {
|
||||
if (observation?.open && observation.matches) {
|
||||
const expected = observation.files.get(fileKey(filePath))
|
||||
if (expected && present !== (expected.digest !== null)) {
|
||||
observation.matches = false
|
||||
|
||||
Reference in New Issue
Block a user