S00-012: Record blocked task and remediation handoff

Changes: Preserve incomplete work and blocker metadata for S00-012. This checkpoint does not mark implementation accepted.
Validation: Session ended with status blocked.
Blocker: Submit-transition descendant regression fails: repeated stop_process_tree after parent reap raises EPERM at os.killpg; launch OSError handling then attempts invalid escalation from review state.

Task: S00-012
Agent: auto-ci-cd-28868645424b
Role: ci-cd
Action: claim
Status: blocked

Task title: Fix runner prompt delivery after partial stdin timeout
This commit is contained in:
wt committed 2026-10-15 01:45:17 +07:00
1 parent b6691d9c8b
commit 49c054aaf9
14 files changed
+295 -20

No files matched your search

+43
View File
@@ -276,6 +276,49 @@ else:
self.assertEqual(result['stop'], 'session_limit')
self.assertEqual(self.tracker.state()['tasks']['S00-001']['status'], 'blocked')
def _check_descendant_cleanup(self, transition):
import time
ready = self.root / 'state/descendant-ready'
late_write = self.root / 'src/late-descendant-write.txt'
child_code = (
"import pathlib,signal,time;signal.signal(signal.SIGTERM,signal.SIG_IGN);"
f"pathlib.Path({str(ready)!r}).write_text('ready');"
"time.sleep(1.5);"
f"pathlib.Path({str(late_write)!r}).write_text('unexpected')"
)
startup = (
"import subprocess,time\n"
f"subprocess.Popen([sys.executable,'-c',{child_code!r}])\n"
f"while not pathlib.Path({str(ready)!r}).exists():time.sleep(.01)\n"
)
fake = self.root / 'fake_agent.py'
source = fake.read_text().replace(
"prompt=sys.stdin.read();assert 'fresh session' in prompt",
startup + ("prompt=sys.stdin.read();assert 'fresh session' in prompt"
if transition else "time.sleep(10)"))
fake.write_text(source + '\nimport time;time.sleep(10)\n')
(self.root / 'state/first-blocker').write_text('skip fixture blocker')
runner = RUN_MODULE.Runner(self.root, dict(self.config, max_sessions=1,
timeout_seconds=2 if transition else .5))
result = runner.run()
self.assertEqual(result['launched'], 1)
self.assertTrue(ready.is_file(), 'Descendant must start before cleanup')
record = json.loads(next((self.root / 'state/runs').glob('*/run.json')).read_text())
self.assertEqual(record['stopped_after_transition'], transition)
self.assertEqual(self.tracker.state()['tasks']['S00-001']['status'],
'review' if transition else 'blocked')
time.sleep(1.6)
self.assertFalse(late_write.exists(), 'Descendant survived process-group cleanup')
self.assertEqual(record['scope_violations'], [])
@unittest.skipUnless(sys.platform != 'win32', 'POSIX process-group cleanup')
def test_timeout_stops_source_writing_descendant(self):
self._check_descendant_cleanup(transition=False)
@unittest.skipUnless(sys.platform != 'win32', 'POSIX process-group cleanup')
def test_submit_transition_stops_source_writing_descendant(self):
self._check_descendant_cleanup(transition=True)
def test_scope_matcher_checks_modified_created_deleted_files(self):
self.assertEqual(RUN_MODULE.scope_violations({'a': 'old', 'gone': 'old'}, {'a': 'new', 'created': 'new'}, ['a']), ['created', 'gone'])