mirror of
https://github.com/JackChen-me/open-multi-agent.git
synced 2026-10-22 02:53:26 -05:00
Two consecutive Friday runs failed without anyone noticing, and the one that was noticed reported only "OMA release analysis failed." with no cause at all. Both gaps are closed here, with the smaller defects the same investigation surfaced. - Name the cause when a run fails without any agent failing. A token budget stop leaves later tasks skipped and every agent result successful, so the message degenerated to a bare sentence and sent the reader to the raw [OMA] progress log. It now carries the run status with token totals, the run's error kind and flags, and every unfinished task with its status. - Report a failed run as a GitHub issue, opening one or commenting on the open one. A weekly job whose only failure signal is the Actions tab is a job nobody reads. It uses the built-in token, so it needs no App permission and no new secret. - Define what earns a changelog entry in the release contract. The bot reads .github/RELEASING.md as evidence, so the rule applied by hand in #523 and again in #543 is now applied by the bot itself. - Retry the two synthesis tasks once, so a provider timeout or 5xx no longer ends the run. They carry no tools and read a few thousand tokens. The evidence tasks stay at zero because a second attempt re-calls their tools and would trip the exactly-one-call coverage assertion. Schema failures stay terminal either way. - Separate comment-only diffs from behavior changes in the compatibility auditor's instructions. It reported a JSDoc-only edit as a latency and cost risk in #543. - Echo the three validation commands. They dominate the step's wall clock and produced no output at all, so a hang there was indistinguishable from a slow model call. The whole-run token ceiling becomes a named, validated option so the budget-stop path is testable.
47 lines
1.7 KiB
TypeScript
47 lines
1.7 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import { NodeCommandRunner } from '../src/command.js'
|
|
|
|
/** Records what the child wrote through, without swallowing the test reporter. */
|
|
function recordStdout(): { chunks: string[]; restore: () => void } {
|
|
const chunks: string[] = []
|
|
const original = process.stdout.write.bind(process.stdout)
|
|
const spy = vi.spyOn(process.stdout, 'write').mockImplementation(
|
|
((chunk: unknown, ...rest: unknown[]) => {
|
|
chunks.push(String(chunk))
|
|
return (original as (...args: unknown[]) => boolean)(chunk, ...rest)
|
|
}) as typeof process.stdout.write,
|
|
)
|
|
return { chunks, restore: () => spy.mockRestore() }
|
|
}
|
|
|
|
describe('command output echo', () => {
|
|
it('captures output and stays silent by default', async () => {
|
|
const { chunks, restore } = recordStdout()
|
|
try {
|
|
const result = await new NodeCommandRunner().run(
|
|
process.execPath,
|
|
['-e', 'console.log("release-bot-silent-sentinel")'],
|
|
)
|
|
expect(result.stdout.trim()).toBe('release-bot-silent-sentinel')
|
|
expect(chunks.filter(chunk => chunk.includes('release-bot-silent-sentinel'))).toEqual([])
|
|
} finally {
|
|
restore()
|
|
}
|
|
})
|
|
|
|
it('echoes to the parent stream while still capturing', async () => {
|
|
const { chunks, restore } = recordStdout()
|
|
try {
|
|
const result = await new NodeCommandRunner().run(
|
|
process.execPath,
|
|
['-e', 'console.log("release-bot-echo-sentinel")'],
|
|
{ echo: true },
|
|
)
|
|
expect(result.stdout.trim()).toBe('release-bot-echo-sentinel')
|
|
expect(chunks.some(chunk => chunk.includes('release-bot-echo-sentinel'))).toBe(true)
|
|
} finally {
|
|
restore()
|
|
}
|
|
})
|
|
})
|