From c28412ae8f79e03257b4fab2460ff62dc4682c72 Mon Sep 17 00:00:00 2001 From: TolaMironcenko Date: Thu, 15 Oct 2026 01:37:36 +0700 Subject: [PATCH] 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: Required automation suite fails in existing all-prompts budget test: S21-006 exceeds even a diagnostic 90000-character prompt limit. This blocks verification of the stdin remediation; production limit remains 80000. Task: S00-012 Agent: manual-ci-cd-stdin-20261015b Role: ci-cd Action: escalate Status: blocked Task title: Fix runner prompt delivery after partial stdin timeout --- planning/ROADMAP.md | 2 +- planning/TASK_MATRIX.md | 6 +- planning/TRACEABILITY.md | 2 +- planning/stages/S00.md | 4 +- planning/task_matrix.csv | 4 +- planning/tasks.json | 111 +++++++++++++++++- planning/tasks/S00-002.md | 2 +- planning/tasks/S00-012.md | 59 ++++++++++ planning/tasks/S00-013.md | 60 ++++++++++ scripts/runner.py | 18 +-- state/blockers/S00-012.md | 22 ++++ state/blockers/S00-013.md | 22 ++++ ...S00-002-manual-security-stdin-20261015a.md | 14 +++ .../S00-012-manual-ci-cd-stdin-20261015b.md | 22 ++++ state/handoffs/S00-002.md | 2 + state/handoffs/S00-012.md | 7 ++ ...0-002-manual-security-stdin-20261015a.json | 30 +++++ .../S00-012-manual-ci-cd-stdin-20261015b.json | 30 +++++ state/tasks.json | 75 ++++++++++-- tests/tooling/test_automation.py | 24 ++++ 20 files changed, 491 insertions(+), 25 deletions(-) create mode 100644 planning/tasks/S00-012.md create mode 100644 planning/tasks/S00-013.md create mode 100644 state/blockers/S00-012.md create mode 100644 state/blockers/S00-013.md create mode 100644 state/evidence/S00-002-manual-security-stdin-20261015a.md create mode 100644 state/evidence/S00-012-manual-ci-cd-stdin-20261015b.md create mode 100644 state/handoffs/S00-012.md create mode 100644 state/issues/S00-002-manual-security-stdin-20261015a.json create mode 100644 state/issues/S00-012-manual-ci-cd-stdin-20261015b.json diff --git a/planning/ROADMAP.md b/planning/ROADMAP.md index 36d7aee..3b9fe30 100644 --- a/planning/ROADMAP.md +++ b/planning/ROADMAP.md @@ -6,7 +6,7 @@ Зафиксировать Web scope, browser targets и проверенные кандидаты, не устанавливая непроверенный framework по догадке. -Задач: 11; entry: нет; exit: S00-010. +Задач: 13; entry: нет; exit: S00-010. ## [S01: Предметные контракты](stages/S01.md) diff --git a/planning/TASK_MATRIX.md b/planning/TASK_MATRIX.md index 5f60c0b..3aff067 100644 --- a/planning/TASK_MATRIX.md +++ b/planning/TASK_MATRIX.md @@ -1,11 +1,11 @@ # Матрица задач -Generated; state revision **11**. Canonical status: state/tasks.json. +Generated; state revision **14**. Canonical status: state/tasks.json. | ID | Этап | Оператор | Reviewer | Статус | Owner | Зависимости | Задача | | --- | --- | --- | --- | --- | --- | --- | --- | | [S00-001](tasks/S00-001.md) | S00 | orchestrator | security | done | auto-orchestrator-48aab142ecde | | Утвердить Web-профиль | -| [S00-002](tasks/S00-002.md) | S00 | orchestrator | security | review | auto-orchestrator-68a05c587e33 | S00-001, S00-011 | Выбрать framework и build runtime | +| [S00-002](tasks/S00-002.md) | S00 | orchestrator | security | blocked | auto-orchestrator-68a05c587e33 | S00-001, S00-011, S00-012 | Выбрать framework и build runtime | | [S00-003](tasks/S00-003.md) | S00 | protocol | qa | todo | | S00-001, S00-002 | Проверить XMPP WSS/auth библиотеку | | [S00-004](tasks/S00-004.md) | S00 | crypto | security | todo | | S00-001, S00-002 | Проверить browser OMEMO backend | | [S00-005](tasks/S00-005.md) | S00 | storage | qa | todo | | S00-002 | Выбрать IndexedDB wrapper и migration policy | @@ -14,6 +14,8 @@ Generated; state revision **11**. Canonical status: state/tasks.json. | [S00-008](tasks/S00-008.md) | S00 | ci-cd | qa | todo | | S00-003, S00-004 | Описать WSS/upload/TURN/push topology | | [S00-009](tasks/S00-009.md) | S00 | orchestrator | security | todo | | S00-003, S00-004, S00-005, S00-006, S00-007, S00-008 | Согласовать результаты spikes | | [S00-011](tasks/S00-011.md) | S00 | ci-cd | security | done | auto-ci-cd-d105e8027730 | S00-001 | Restore verified npm registry access for the stack spike | +| [S00-012](tasks/S00-012.md) | S00 | ci-cd | qa | blocked | manual-ci-cd-stdin-20261015b | S00-001, S00-011, S00-013 | Fix runner prompt delivery after partial stdin timeout | +| [S00-013](tasks/S00-013.md) | S00 | ci-cd | qa | todo | | S00-001, S00-011 | Bound oversized S21-006 runner context without truncating requirements | | [S00-010](tasks/S00-010.md) | S00 | qa | orchestrator | todo | | S00-001, S00-002, S00-003, S00-004, S00-005, S00-006, S00-007, S00-008, S00-009 | Gate: Профиль и проверка стека | | [S01-001](tasks/S01-001.md) | S01 | orchestrator | security | todo | | S00-010 | Описать identity/model contracts | | [S01-002](tasks/S01-002.md) | S01 | orchestrator | security | todo | | S00-010, S01-001 | Описать async account context | diff --git a/planning/TRACEABILITY.md b/planning/TRACEABILITY.md index 4230848..db75c23 100644 --- a/planning/TRACEABILITY.md +++ b/planning/TRACEABILITY.md @@ -204,7 +204,7 @@ Allocated означает наличие плана/приёмки, а не р | NFR-004 | web | Web requirement; cross-platform clauses apply only in Web context. | S02-012, S09-012, S21-007 | | NFR-005 | web | Web requirement; cross-platform clauses apply only in Web context. | S00-006, S02-012, S09-012, S20-006, S21-011 | | NFR-006 | web | Web requirement; cross-platform clauses apply only in Web context. | S02-012, S09-012 | -| NFR-007 | web | Web requirement; cross-platform clauses apply only in Web context. | S00-002, S00-011, S02-001, S02-002, S09-012, S21-008, S21-009 | +| NFR-007 | web | Web requirement; cross-platform clauses apply only in Web context. | S00-002, S00-011, S00-012, S00-013, S02-001, S02-002, S09-012, S21-008, S21-009 | | NFR-008 | web | Web requirement; cross-platform clauses apply only in Web context. | S02-004, S02-005, S02-006, S09-012, S21-009 | | NFR-009 | web | Web requirement; cross-platform clauses apply only in Web context. | S02-012, S09-012, S19-006, S20-003, S21-010 | | UI-001 | web | Web requirement; cross-platform clauses apply only in Web context. | S03-002, S20-001, S21-006 | diff --git a/planning/stages/S00.md b/planning/stages/S00.md index 4fc1583..88fa231 100644 --- a/planning/stages/S00.md +++ b/planning/stages/S00.md @@ -7,7 +7,7 @@ ## Задачи - [S00-001](../tasks/S00-001.md): Утвердить Web-профиль — orchestrator; done. -- [S00-002](../tasks/S00-002.md): Выбрать framework и build runtime — orchestrator; review. +- [S00-002](../tasks/S00-002.md): Выбрать framework и build runtime — orchestrator; blocked. - [S00-003](../tasks/S00-003.md): Проверить XMPP WSS/auth библиотеку — protocol; todo. - [S00-004](../tasks/S00-004.md): Проверить browser OMEMO backend — crypto; todo. - [S00-005](../tasks/S00-005.md): Выбрать IndexedDB wrapper и migration policy — storage; todo. @@ -16,6 +16,8 @@ - [S00-008](../tasks/S00-008.md): Описать WSS/upload/TURN/push topology — ci-cd; todo. - [S00-009](../tasks/S00-009.md): Согласовать результаты spikes — orchestrator; todo. - [S00-011](../tasks/S00-011.md): Restore verified npm registry access for the stack spike — ci-cd; done. +- [S00-012](../tasks/S00-012.md): Fix runner prompt delivery after partial stdin timeout — ci-cd; blocked. +- [S00-013](../tasks/S00-013.md): Bound oversized S21-006 runner context without truncating requirements — ci-cd; todo. - [S00-010](../tasks/S00-010.md): Gate: Профиль и проверка стека — qa; todo. ## Граница этапа diff --git a/planning/task_matrix.csv b/planning/task_matrix.csv index f5b21cb..9141619 100644 --- a/planning/task_matrix.csv +++ b/planning/task_matrix.csv @@ -1,6 +1,6 @@ id,stage,operator,reviewer,status,owner,depends_on,title S00-001,S00,orchestrator,security,done,auto-orchestrator-48aab142ecde,,Утвердить Web-профиль -S00-002,S00,orchestrator,security,review,auto-orchestrator-68a05c587e33,"S00-001, S00-011",Выбрать framework и build runtime +S00-002,S00,orchestrator,security,blocked,auto-orchestrator-68a05c587e33,"S00-001, S00-011, S00-012",Выбрать framework и build runtime S00-003,S00,protocol,qa,todo,,"S00-001, S00-002",Проверить XMPP WSS/auth библиотеку S00-004,S00,crypto,security,todo,,"S00-001, S00-002",Проверить browser OMEMO backend S00-005,S00,storage,qa,todo,,S00-002,Выбрать IndexedDB wrapper и migration policy @@ -9,6 +9,8 @@ S00-007,S00,security,orchestrator,todo,,"S00-004, S00-005",Утвердить pa S00-008,S00,ci-cd,qa,todo,,"S00-003, S00-004",Описать WSS/upload/TURN/push topology S00-009,S00,orchestrator,security,todo,,"S00-003, S00-004, S00-005, S00-006, S00-007, S00-008",Согласовать результаты spikes S00-011,S00,ci-cd,security,done,auto-ci-cd-d105e8027730,S00-001,Restore verified npm registry access for the stack spike +S00-012,S00,ci-cd,qa,blocked,manual-ci-cd-stdin-20261015b,"S00-001, S00-011, S00-013",Fix runner prompt delivery after partial stdin timeout +S00-013,S00,ci-cd,qa,todo,,"S00-001, S00-011",Bound oversized S21-006 runner context without truncating requirements S00-010,S00,qa,orchestrator,todo,,"S00-001, S00-002, S00-003, S00-004, S00-005, S00-006, S00-007, S00-008, S00-009",Gate: Профиль и проверка стека S01-001,S01,orchestrator,security,todo,,S00-010,Описать identity/model contracts S01-002,S01,orchestrator,security,todo,,"S00-010, S01-001",Описать async account context diff --git a/planning/tasks.json b/planning/tasks.json index 2a991ba..f48a550 100644 --- a/planning/tasks.json +++ b/planning/tasks.json @@ -216,7 +216,8 @@ "outcome": "ADR сравнивает два допустимых стека, фиксирует конкретные проверенные versions, lockfile и один минимальный rendering spike.", "depends_on": [ "S00-001", - "S00-011" + "S00-011", + "S00-012" ], "requirements": [ "NFR-007" @@ -668,6 +669,114 @@ ], "context_budget_chars": 48000 }, + { + "id": "S00-012", + "stage": "S00", + "kind": "blocker", + "root_task": "S00-002", + "blocker_depth": 1, + "unblocks": [ + "S00-002" + ], + "role": "ci-cd", + "reviewer_role": "qa", + "title": "Fix runner prompt delivery after partial stdin timeout", + "outcome": "Reliable complete prompt delivery under startup delay and pipe backpressure, preserving runner lifecycle guarantees.", + "depends_on": [ + "S00-001", + "S00-011", + "S00-013" + ], + "requirements": [ + "NFR-007" + ], + "scope": [ + "scripts/runner.py", + "tests/tooling/test_automation.py" + ], + "inputs": [ + "docs/WEB_PROFILE.md", + "docs/ARCHITECTURE.md", + "docs/CONTRACTS.md", + "docs/TESTING.md", + "roles/orchestrator.md", + "docs/decisions/README.md", + "state/blockers/S00-012.md" + ], + "spec_sections": [], + "ui_sections": [], + "steps": [ + "Read diagnostic evidence and reproduce delayed-reader partial-write timeout without launching a model.", + "Fix only runner stdin delivery; retain fresh sessions, prompt budget, terminal-transition monitoring, timeout and process-tree cleanup.", + "Add a deterministic delayed-reader large-prompt regression check and run focused runner tests plus make check.", + "Record evidence/handoff/commit message and submit for independent review." + ], + "acceptance": [ + "A delayed stdin reader receives the complete large UTF-8 prompt and EOF without hanging.", + "Timeout and terminal-transition process cleanup still work; no background source-writing descendants remain.", + "Existing runner/tooling checks pass; no task scope, spec snapshots or product implementation is changed." + ], + "checks": [ + "Delayed-reader large UTF-8 prompt regression.", + "Existing runner timeout, transition, scope and fresh-session tests.", + "make check" + ], + "context_budget_chars": 48000 + }, + { + "id": "S00-013", + "stage": "S00", + "kind": "blocker", + "root_task": "S00-002", + "blocker_depth": 2, + "unblocks": [ + "S00-012" + ], + "role": "ci-cd", + "reviewer_role": "qa", + "title": "Bound oversized S21-006 runner context without truncating requirements", + "outcome": "All task prompts fit the existing configured budget with exact relevant requirements retained and no silent truncation.", + "depends_on": [ + "S00-001", + "S00-011" + ], + "requirements": [ + "NFR-007" + ], + "scope": [ + "scripts/runner.py", + "tests/tooling/test_automation.py" + ], + "inputs": [ + "docs/WEB_PROFILE.md", + "docs/ARCHITECTURE.md", + "docs/CONTRACTS.md", + "docs/TESTING.md", + "roles/orchestrator.md", + "docs/decisions/README.md", + "state/blockers/S00-012.md", + "state/blockers/S00-013.md" + ], + "spec_sections": [], + "ui_sections": [], + "steps": [ + "Inspect S21-006 prompt inputs and identify unnecessary duplication or overly broad context loading.", + "Implement one bounded context-preparation correction while preserving assignment instructions and exact relevant requirements; retain stdin transport changes.", + "Add focused regression for the real oversized context and run existing prompt-budget checks and make check.", + "Record evidence/handoff/message and submit for independent review." + ], + "acceptance": [ + "S21-006 and all current task prompts fit the existing 80000-character limit.", + "Exact required context is retained; no spec snapshot edits, silent truncation or validation suppression.", + "stdin delivery, timeout and terminal-transition regression checks remain passing; make check passes." + ], + "checks": [ + "Existing FoundationRunnerTests all-current-prompts budget check.", + "Delayed UTF-8 stdin delivery and runner lifecycle tests.", + "make check" + ], + "context_budget_chars": 48000 + }, { "id": "S00-010", "stage": "S00", diff --git a/planning/tasks/S00-002.md b/planning/tasks/S00-002.md index ab5d8c7..ae4ad1a 100644 --- a/planning/tasks/S00-002.md +++ b/planning/tasks/S00-002.md @@ -5,7 +5,7 @@ - Этап: S00 - Оператор: orchestrator - Reviewer: security -- Зависимости: S00-001, S00-011 +- Зависимости: S00-001, S00-011, S00-012 - Требования: NFR-007 ## Один результат diff --git a/planning/tasks/S00-012.md b/planning/tasks/S00-012.md new file mode 100644 index 0000000..bfaa20c --- /dev/null +++ b/planning/tasks/S00-012.md @@ -0,0 +1,59 @@ +# S00-012: Fix runner prompt delivery after partial stdin timeout + +- Remediation для: S00-002; root: S00-002; depth: 1 + +> Generated from planning/tasks.json; status is in state/tasks.json. + +- Этап: S00 +- Оператор: ci-cd +- Reviewer: qa +- Зависимости: S00-001, S00-011, S00-013 +- Требования: NFR-007 + +## Один результат + +Reliable complete prompt delivery under startup delay and pipe backpressure, preserving runner lifecycle guarantees. + +## Разрешённые пути + +- `scripts/runner.py` +- `tests/tooling/test_automation.py` + +Не изменять другие modules, shared contracts или spec snapshots без изменения плана. Stem без расширения разрешает принятые stack-specific extensions и focused test рядом. + +## Прочитать + +- docs/WEB_PROFILE.md +- docs/ARCHITECTURE.md +- docs/CONTRACTS.md +- docs/TESTING.md +- roles/orchestrator.md +- docs/decisions/README.md +- state/blockers/S00-012.md + +## Шаги + +1. Read diagnostic evidence and reproduce delayed-reader partial-write timeout without launching a model. +2. Fix only runner stdin delivery; retain fresh sessions, prompt budget, terminal-transition monitoring, timeout and process-tree cleanup. +3. Add a deterministic delayed-reader large-prompt regression check and run focused runner tests plus make check. +4. Record evidence/handoff/commit message and submit for independent review. + +## Приёмка + +1. A delayed stdin reader receives the complete large UTF-8 prompt and EOF without hanging. +2. Timeout and terminal-transition process cleanup still work; no background source-writing descendants remain. +3. Existing runner/tooling checks pass; no task scope, spec snapshots or product implementation is changed. + +## Focused checks + +1. Delayed-reader large UTF-8 prompt regression. +2. Existing runner timeout, transition, scope and fresh-session tests. +3. make check + +## Блокер и завершение запуска + +Для всех ролей scope — только эта задача. При блокере создать issue JSON по state/ISSUE_TEMPLATE.json, вызвать escalate с текущим ID/role/agent, проверить status=blocked и resolution_task, затем немедленно завершить запуск. Не решать blocker и не выбирать следующую задачу самому. Новый агент назначается runner. Правки metadata через CLI — единственное исключение scope. + +## Передача + +Сохранить evidence/handoff; submit → review и завершить запуск. Reviewer также выполняет только эту задачу, включая обязательное escalate при блокере. diff --git a/planning/tasks/S00-013.md b/planning/tasks/S00-013.md new file mode 100644 index 0000000..28b5467 --- /dev/null +++ b/planning/tasks/S00-013.md @@ -0,0 +1,60 @@ +# S00-013: Bound oversized S21-006 runner context without truncating requirements + +- Remediation для: S00-012; root: S00-002; depth: 2 + +> Generated from planning/tasks.json; status is in state/tasks.json. + +- Этап: S00 +- Оператор: ci-cd +- Reviewer: qa +- Зависимости: S00-001, S00-011 +- Требования: NFR-007 + +## Один результат + +All task prompts fit the existing configured budget with exact relevant requirements retained and no silent truncation. + +## Разрешённые пути + +- `scripts/runner.py` +- `tests/tooling/test_automation.py` + +Не изменять другие modules, shared contracts или spec snapshots без изменения плана. Stem без расширения разрешает принятые stack-specific extensions и focused test рядом. + +## Прочитать + +- docs/WEB_PROFILE.md +- docs/ARCHITECTURE.md +- docs/CONTRACTS.md +- docs/TESTING.md +- roles/orchestrator.md +- docs/decisions/README.md +- state/blockers/S00-012.md +- state/blockers/S00-013.md + +## Шаги + +1. Inspect S21-006 prompt inputs and identify unnecessary duplication or overly broad context loading. +2. Implement one bounded context-preparation correction while preserving assignment instructions and exact relevant requirements; retain stdin transport changes. +3. Add focused regression for the real oversized context and run existing prompt-budget checks and make check. +4. Record evidence/handoff/message and submit for independent review. + +## Приёмка + +1. S21-006 and all current task prompts fit the existing 80000-character limit. +2. Exact required context is retained; no spec snapshot edits, silent truncation or validation suppression. +3. stdin delivery, timeout and terminal-transition regression checks remain passing; make check passes. + +## Focused checks + +1. Existing FoundationRunnerTests all-current-prompts budget check. +2. Delayed UTF-8 stdin delivery and runner lifecycle tests. +3. make check + +## Блокер и завершение запуска + +Для всех ролей scope — только эта задача. При блокере создать issue JSON по state/ISSUE_TEMPLATE.json, вызвать escalate с текущим ID/role/agent, проверить status=blocked и resolution_task, затем немедленно завершить запуск. Не решать blocker и не выбирать следующую задачу самому. Новый агент назначается runner. Правки metadata через CLI — единственное исключение scope. + +## Передача + +Сохранить evidence/handoff; submit → review и завершить запуск. Reviewer также выполняет только эту задачу, включая обязательное escalate при блокере. diff --git a/scripts/runner.py b/scripts/runner.py index af0e410..bc3ae6f 100644 --- a/scripts/runner.py +++ b/scripts/runner.py @@ -206,21 +206,21 @@ The coordinator commits each transition before launching another agent. failure = None stopped_after_transition = False returncode = None - with (session / 'output.log').open('wb') as output: + # Give the child a complete UTF-8 stream ending at EOF. Feeding a pipe + # through short communicate() retries can strand a partially sent prompt + # when the child is slow to start reading. The prompt is already persisted. + with prompt_path.open('rb') as prompt_input, (session / 'output.log').open('wb') as output: try: - process = subprocess.Popen(argv, cwd=self.root, env=env, stdin=subprocess.PIPE, + process = subprocess.Popen(argv, cwd=self.root, env=env, stdin=prompt_input, stdout=output, stderr=subprocess.STDOUT, start_new_session=(os.name == 'posix')) deadline = time.monotonic() + self.timeout - first_communicate = True stopped_after_transition = False try: while True: try: - process.communicate(prompt.encode('utf-8') if first_communicate else None, - timeout=min(.2, max(.01, deadline - time.monotonic()))) + process.wait(timeout=min(.2, max(.01, deadline - time.monotonic()))) break except subprocess.TimeoutExpired: - first_communicate = False try: live = self.tracker.state() current = live['tasks'][item['id']] @@ -231,17 +231,17 @@ The coordinator commits each transition before launching another agent. blocker_exit = executor_exit = reviewer_exit = False if blocker_exit or executor_exit or reviewer_exit: stop_process_tree(process) - process.communicate() + process.wait() stopped_after_transition = True break if time.monotonic() >= deadline: stop_process_tree(process) - process.communicate() + process.wait() failure = 'Agent timed out; process terminated before escalation' break except BaseException: stop_process_tree(process) - process.communicate() + process.wait() raise finally: # Even an exited harness must not leave source-writing descendants alive. diff --git a/state/blockers/S00-012.md b/state/blockers/S00-012.md new file mode 100644 index 0000000..e588ca8 --- /dev/null +++ b/state/blockers/S00-012.md @@ -0,0 +1,22 @@ +# Blocker S00-012 + +- Original task: S00-002 +- Root task: S00-002 +- Reporter: manual-security-stdin-20261015a +- Role: security +- Original owner: auto-orchestrator-68a05c587e33 +- Waits for user/external condition: False + +## Cause + +Reviewer startup hangs waiting for stdin EOF: runner retries communicate(None) after a .2s partial-write timeout. Reproduced with delayed stdin reader and 80000-byte payload on Python 3.9.6; no S00-002 acceptance review was performed. + +## One remediation outcome + +Reliable complete prompt delivery under startup delay and pipe backpressure, preserving runner lifecycle guarantees. + +## Evidence / reproduction + +state/evidence/S00-002-manual-security-stdin-20261015a.md + +The reporting agent must stop now. A new agent implements only S00-012. diff --git a/state/blockers/S00-013.md b/state/blockers/S00-013.md new file mode 100644 index 0000000..87c433b --- /dev/null +++ b/state/blockers/S00-013.md @@ -0,0 +1,22 @@ +# Blocker S00-013 + +- Original task: S00-012 +- Root task: S00-002 +- Reporter: manual-ci-cd-stdin-20261015b +- Role: ci-cd +- Original owner: manual-ci-cd-stdin-20261015b +- Waits for user/external condition: False + +## Cause + +Required automation suite fails in existing all-prompts budget test: S21-006 exceeds even a diagnostic 90000-character prompt limit. This blocks verification of the stdin remediation; production limit remains 80000. + +## One remediation outcome + +All task prompts fit the existing configured budget with exact relevant requirements retained and no silent truncation. + +## Evidence / reproduction + +python3 -m unittest discover -s tests/tooling -p test_automation.py -v: 22 pass, one prompt-budget error. Read-only Runner(max_prompt_chars=90000).prompt for S21-006 also errors. Evidence: state/evidence/S00-012-manual-ci-cd-stdin-20261015b.md + +The reporting agent must stop now. A new agent implements only S00-013. diff --git a/state/evidence/S00-002-manual-security-stdin-20261015a.md b/state/evidence/S00-002-manual-security-stdin-20261015a.md new file mode 100644 index 0000000..bdc5cee --- /dev/null +++ b/state/evidence/S00-002-manual-security-stdin-20261015a.md @@ -0,0 +1,14 @@ +# S00-002 review startup blocker + +Reporter: manual-security-stdin-20261015a, security-role supervisor. +No acceptance review was performed. Implementation commit 59b9ff62fed3d912215bf818a20eeba271ff4f4f is preserved. + +The assigned reviewer auto-security-9b8ae55222db (PID 86944) produced an empty output.log for several minutes. Its prompt.md contains 75696 bytes / 55647 characters. A one-second OS sample showed codex_exec::resolve_root_prompt -> Stdin::read_to_end -> read. This is startup waiting on stdin, before agent execution. + +Actual runtime: Python 3.9.6. scripts/runner.py calls communicate(prompt, timeout=.2), then retries communicate(None). In this runtime Popen._communicate only registers stdin for writing when the current input argument is truthy. A timeout during partial delivery therefore prevents remaining writes/EOF on subsequent calls. + +Synthetic reproduction, exit 0: launch Python child sleeping .5 seconds then reading stdin to EOF; parent sends 80000 bytes with communicate(timeout=.2), observes TimeoutExpired, retries communicate(None, timeout=1), observes a second TimeoutExpired. Child then terminated and reaped. Output: REPRODUCED: retry communicate(None) leaves child waiting for stdin; payload bytes=80000; Python=3.9.6. + +Runner PID 84112 was stopped with SIGINT; its BaseException cleanup terminated/reaped the reviewer and removed .runner.lock. Supervisor exec session returned 130/KeyboardInterrupt. No product source edits, Git rollback, task acceptance or release bypass. Network access remains enabled in runner.local.json and verified by reviewed S00-011. + +Required remediation: make runner prompt delivery resilient to slow startup/backpressure while preserving terminal-transition monitoring, timeout/process-tree cleanup and full untruncated fresh prompts. Add a deterministic delayed-stdin/large-payload regression test. Do not change product stack, requirements or S00-002 implementation. Current original review must resume in a fresh reviewer only after independent remediation acceptance. diff --git a/state/evidence/S00-012-manual-ci-cd-stdin-20261015b.md b/state/evidence/S00-012-manual-ci-cd-stdin-20261015b.md new file mode 100644 index 0000000..a266ab0 --- /dev/null +++ b/state/evidence/S00-012-manual-ci-cd-stdin-20261015b.md @@ -0,0 +1,22 @@ +# S00-012 partial implementation and blocker evidence + +Executor: manual-ci-cd-stdin-20261015b (ci-cd). No submit, review acceptance or done is claimed. +Input: S00-012 card/context packet, diagnostic evidence, accepted ADR 0000 and reviewed S00-001/S00-011 dependency results. Output attempted: complete stdin prompt delivery under startup delay and pipe backpressure. No product/shared contract changes required. + +## Actual changes in scope + +scripts/runner.py now opens the already-persisted UTF-8 prompt.md as binary stdin for the child and polls process.wait rather than attempting timed partial pipe writes through communicate. EOF and complete prompt bytes are supplied by the file; .2s state monitoring, deadlines and stop_process_tree cleanup remain. No prompt truncation or limit changes. + +tests/tooling/test_automation.py adds a delayed-reader regression: synthetic tool harness waits .5s before reading 140024 UTF-8 bytes (emoji and Cyrillic), compares all bytes with LUMA_PROMPT_FILE, observes EOF, then submits one fixture task. No real model/provider task is run. + +## Actual commands/results + +- tasks.py resume: exit 0, empty owned tasks; claim S00-012: exit 0, revision 13; show/packet read. +- Before runner fix: python3 -m unittest discover -s tests/tooling -p test_automation.py -k delayed_reader -v: exit 1. Custom load_tests runs all 23 automation tests despite -k. New delayed-reader regression failed (blocked instead of review) and existing all-prompts budget test errored. +- After runner fix: python3 -m unittest discover -s tests/tooling -p test_automation.py -v: exit 1, 23 tests in 4.465s. New delayed-reader regression passed; 22 tests passed, one existing FoundationRunnerTests.test_all_current_fresh_agent_prompts_fit_configured_budget errored. Timeout, scope and terminal-transition cleanup tests passed. Full suite is not passed. +- Read-only diagnostic iteration with max_prompt_chars=90000: exit 0; only S21-006 still raises Prompt exceeds configured character budget. Production configuration remains 80000 characters; raising it to the allowed maximum still does not fit S21-006. +- git diff --stat scoped inspection: exit 0; only scripts/runner.py and tests/tooling/test_automation.py source files changed by this executor. Pre-existing uncommitted S00-012 blocker/workflow artifacts were present at entry and preserved. + +## Blocker and limits + +Existing prompt-budget validation fails on S21-006 independently of stdin transport. Required tooling suite cannot pass. Stop source edits and create one separate remediation for bounded context preparation; do not truncate requirements, weaken validation or change immutable specs. make check was not run/passed after this blocker was established. No real Codex launch was attempted. Python runtime was 3.9.6. No Git mutations by executor; partial source/workflow changes remain uncommitted for coordinator checkpoint. diff --git a/state/handoffs/S00-002.md b/state/handoffs/S00-002.md index f339234..ccfbf4b 100644 --- a/state/handoffs/S00-002.md +++ b/state/handoffs/S00-002.md @@ -8,3 +8,5 @@ Actual checks: clean npm ci with fresh empty cache, strict TypeScript/Vite build Next step belongs only to separate assigned security reviewer. Read ADR/card/evidence and executor commit/message. From experiments/0001-stack with Node 24.21.0 / npm 11.19.0, run the README's clean npm ci and npm run build. Existing verified macOS ARM64 runtime is at /private/tmp/luma-stack-runtime/node-v24.21.0-darwin-arm64, or retrieve the official exact runtime with verified HTTPS/checksum. Inspect exact manifest/lock pins, licenses including build-only MPL-2.0, runtime notices, no production transport/secrets and no source changes outside card scope. Record acceptance and reviewer metadata in ADR only if warranted, then approve/reject through tasks.py. DOM rendering/counter interaction is an external check: no browser is exposed by this harness. README gives manual steps; do not label them passed. Current compiler floors are not the product browser matrix. Vue was not built or benchmarked. Crypto/XMPP compatibility, full app CI, notices for future libraries, other build-host platforms, provider integration and release readiness remain subsequent cards. Shared contracts/specs/plan definitions unchanged. ADR remains proposed; executor does not set done or perform Git mutations. Coordinator commits this submission and launches the reviewer. + +Review startup blocker reported by manual-security-stdin-20261015a: assigned reviewer never received complete stdin/EOF. Runner stopped cleanly by supervisor; no acceptance review performed. Diagnostic evidence: state/evidence/S00-002-manual-security-stdin-20261015a.md. Implementation commit 59b9ff6 remains preserved. Separate runner transport remediation must be reviewed before original review resumes. diff --git a/state/handoffs/S00-012.md b/state/handoffs/S00-012.md new file mode 100644 index 0000000..10f5bc7 --- /dev/null +++ b/state/handoffs/S00-012.md @@ -0,0 +1,7 @@ +# S00-012 partial handoff + +Executor: manual-ci-cd-stdin-20261015b, ci-cd. Partial stdin transport fix and regression test are in scripts/runner.py and tests/tooling/test_automation.py. New delayed UTF-8 reader test failed before the fix and passed after it. Existing timeout/terminal-transition tests pass. No acceptance/submission is claimed. + +Blocker: the existing all-prompts budget test fails because S21-006 prompt exceeds even the 90000-character diagnostic maximum. Separate context-budget remediation is required; it must retain complete exact task requirements and bounded relevant inputs, without increasing limits beyond contract or suppressing validation. Evidence: state/evidence/S00-012-manual-ci-cd-stdin-20261015b.md. + +After reviewed remediation, a fresh S00-012 executor should inspect the preserved diff, rerun regression and make check, write evidence and commit message, then submit. Coordinator must checkpoint the preserved partial work and pending prior blocker metadata before any automated new agent; current checkout is dirty. Current reporter ends after escalate and cannot continue remediation. diff --git a/state/issues/S00-002-manual-security-stdin-20261015a.json b/state/issues/S00-002-manual-security-stdin-20261015a.json new file mode 100644 index 0000000..e47276c --- /dev/null +++ b/state/issues/S00-002-manual-security-stdin-20261015a.json @@ -0,0 +1,30 @@ +{ + "title": "Fix runner prompt delivery after partial stdin timeout", + "reason": "Reviewer startup hangs waiting for stdin EOF: runner retries communicate(None) after a .2s partial-write timeout. Reproduced with delayed stdin reader and 80000-byte payload on Python 3.9.6; no S00-002 acceptance review was performed.", + "reproduction": "state/evidence/S00-002-manual-security-stdin-20261015a.md", + "role": "ci-cd", + "reviewer_role": "qa", + "scope": [ + "scripts/runner.py", + "tests/tooling/test_automation.py" + ], + "outcome": "Reliable complete prompt delivery under startup delay and pipe backpressure, preserving runner lifecycle guarantees.", + "steps": [ + "Read diagnostic evidence and reproduce delayed-reader partial-write timeout without launching a model.", + "Fix only runner stdin delivery; retain fresh sessions, prompt budget, terminal-transition monitoring, timeout and process-tree cleanup.", + "Add a deterministic delayed-reader large-prompt regression check and run focused runner tests plus make check.", + "Record evidence/handoff/commit message and submit for independent review." + ], + "acceptance": [ + "A delayed stdin reader receives the complete large UTF-8 prompt and EOF without hanging.", + "Timeout and terminal-transition process cleanup still work; no background source-writing descendants remain.", + "Existing runner/tooling checks pass; no task scope, spec snapshots or product implementation is changed." + ], + "checks": [ + "Delayed-reader large UTF-8 prompt regression.", + "Existing runner timeout, transition, scope and fresh-session tests.", + "make check" + ], + "depends_on": [], + "requires_user_input": false +} diff --git a/state/issues/S00-012-manual-ci-cd-stdin-20261015b.json b/state/issues/S00-012-manual-ci-cd-stdin-20261015b.json new file mode 100644 index 0000000..a7feb42 --- /dev/null +++ b/state/issues/S00-012-manual-ci-cd-stdin-20261015b.json @@ -0,0 +1,30 @@ +{ + "title": "Bound oversized S21-006 runner context without truncating requirements", + "reason": "Required automation suite fails in existing all-prompts budget test: S21-006 exceeds even a diagnostic 90000-character prompt limit. This blocks verification of the stdin remediation; production limit remains 80000.", + "reproduction": "python3 -m unittest discover -s tests/tooling -p test_automation.py -v: 22 pass, one prompt-budget error. Read-only Runner(max_prompt_chars=90000).prompt for S21-006 also errors. Evidence: state/evidence/S00-012-manual-ci-cd-stdin-20261015b.md", + "role": "ci-cd", + "reviewer_role": "qa", + "scope": [ + "scripts/runner.py", + "tests/tooling/test_automation.py" + ], + "outcome": "All task prompts fit the existing configured budget with exact relevant requirements retained and no silent truncation.", + "steps": [ + "Inspect S21-006 prompt inputs and identify unnecessary duplication or overly broad context loading.", + "Implement one bounded context-preparation correction while preserving assignment instructions and exact relevant requirements; retain stdin transport changes.", + "Add focused regression for the real oversized context and run existing prompt-budget checks and make check.", + "Record evidence/handoff/message and submit for independent review." + ], + "acceptance": [ + "S21-006 and all current task prompts fit the existing 80000-character limit.", + "Exact required context is retained; no spec snapshot edits, silent truncation or validation suppression.", + "stdin delivery, timeout and terminal-transition regression checks remain passing; make check passes." + ], + "checks": [ + "Existing FoundationRunnerTests all-current-prompts budget check.", + "Delayed UTF-8 stdin delivery and runner lifecycle tests.", + "make check" + ], + "depends_on": [], + "requires_user_input": false +} diff --git a/state/tasks.json b/state/tasks.json index d24d866..fb53c8c 100644 --- a/state/tasks.json +++ b/state/tasks.json @@ -1,6 +1,6 @@ { "schema_version": 1, - "revision": 11, + "revision": 14, "tasks": { "S00-001": { "status": "done", @@ -15,14 +15,16 @@ "completed_at": "2026-10-14T18:03:56+00:00" }, "S00-002": { - "status": "review", + "status": "blocked", "owner": "auto-orchestrator-68a05c587e33", "started_at": "2026-10-14T18:11:33+00:00", - "reason": null, - "updated_at": "2026-10-14T18:18:53+00:00", - "blocked_by": [], - "resume_status": "in_progress", - "blocker_report": "state/blockers/S00-011.md", + "reason": "Reviewer startup hangs waiting for stdin EOF: runner retries communicate(None) after a .2s partial-write timeout. Reproduced with delayed stdin reader and 80000-byte payload on Python 3.9.6; no S00-002 acceptance review was performed.", + "updated_at": "2026-10-14T18:24:59+00:00", + "blocked_by": [ + "S00-012" + ], + "resume_status": "review", + "blocker_report": "state/blockers/S00-012.md", "handoff": "state/handoffs/S00-002.md", "previous_owner": "auto-orchestrator-3a4f07103316", "resumed_after_blocker": true, @@ -1132,6 +1134,26 @@ "reviewer": "auto-security-1e9200de1765", "review_evidence": "state/evidence/S00-011-review.md", "completed_at": "2026-10-14T18:11:33+00:00" + }, + "S00-012": { + "status": "blocked", + "owner": "manual-ci-cd-stdin-20261015b", + "external_wait": false, + "reason": "Required automation suite fails in existing all-prompts budget test: S21-006 exceeds even a diagnostic 90000-character prompt limit. This blocks verification of the stdin remediation; production limit remains 80000.", + "started_at": "2026-10-14T18:33:49+00:00", + "updated_at": "2026-10-14T18:35:56+00:00", + "blocked_by": [ + "S00-013" + ], + "resume_status": "in_progress", + "blocker_report": "state/blockers/S00-013.md", + "handoff": "state/handoffs/S00-012.md" + }, + "S00-013": { + "status": "todo", + "owner": null, + "external_wait": false, + "reason": null } }, "events": [ @@ -1267,9 +1289,46 @@ "to": "review", "reason": null, "evidence": "state/evidence/S00-002-auto-orchestrator-68a05c587e33.md" + }, + { + "revision": 12, + "at": "2026-10-14T18:24:59+00:00", + "action": "escalate", + "task": "S00-002", + "resolution_task": "S00-012", + "agent": "manual-security-stdin-20261015a", + "role": "security", + "from": "review", + "to": "blocked", + "reason": "Reviewer startup hangs waiting for stdin EOF: runner retries communicate(None) after a .2s partial-write timeout. Reproduced with delayed stdin reader and 80000-byte payload on Python 3.9.6; no S00-002 acceptance review was performed." + }, + { + "revision": 13, + "at": "2026-10-14T18:33:49+00:00", + "action": "claim", + "task": "S00-012", + "agent": "manual-ci-cd-stdin-20261015b", + "role": "ci-cd", + "from": "todo", + "to": "in_progress", + "reason": null + }, + { + "revision": 14, + "at": "2026-10-14T18:35:56+00:00", + "action": "escalate", + "task": "S00-012", + "resolution_task": "S00-013", + "agent": "manual-ci-cd-stdin-20261015b", + "role": "ci-cd", + "from": "in_progress", + "to": "blocked", + "reason": "Required automation suite fails in existing all-prompts budget test: S21-006 exceeds even a diagnostic 90000-character prompt limit. This blocks verification of the stdin remediation; production limit remains 80000." } ], "retired_agents": [ - "auto-orchestrator-3a4f07103316" + "auto-orchestrator-3a4f07103316", + "manual-security-stdin-20261015a", + "manual-ci-cd-stdin-20261015b" ] } diff --git a/tests/tooling/test_automation.py b/tests/tooling/test_automation.py index 7fdb3ea..29749e3 100644 --- a/tests/tooling/test_automation.py +++ b/tests/tooling/test_automation.py @@ -220,6 +220,30 @@ else: self.assertEqual(state['tasks']['S00-001']['status'], 'blocked') self.assertTrue(state['retired_agents']) + def test_delayed_reader_receives_complete_large_utf8_prompt_and_eof(self): + fake = self.root / 'fake_agent.py' + fake.write_text(fake.read_text().replace( + "prompt=sys.stdin.read();assert 'fresh session' in prompt", + "import time;time.sleep(.5)\n" + "payload=sys.stdin.buffer.read()\n" + "assert payload == pathlib.Path(os.environ['LUMA_PROMPT_FILE']).read_bytes()\n" + "prompt=payload.decode('utf-8');assert 'fresh session' in prompt\n" + "print('Complete UTF-8 prompt and EOF:',len(payload),flush=True)")) + (self.root / 'state/first-blocker').write_text('skip fixture blocker') + prompt = 'This is a fresh session.\n' + '\U0001f642\u0416\n' * 20000 + runner = RUN_MODULE.Runner(self.root, dict(self.config, max_sessions=1, + timeout_seconds=3)) + with patch.object(runner, 'prompt', return_value=prompt): + result = runner.run() + self.assertEqual(result['launched'], 1) + self.assertEqual(self.tracker.state()['tasks']['S00-001']['status'], 'review') + record_path = next((self.root / 'state/runs').glob('*/run.json')) + record = json.loads(record_path.read_text()) + self.assertEqual(record['result'], {'status': 'review'}) + self.assertEqual(record['scope_violations'], []) + self.assertIn('Complete UTF-8 prompt and EOF: ' + str(len(prompt.encode('utf-8'))), + record_path.with_name('output.log').read_text()) + def test_scope_violation_quarantines_and_requires_input(self): runner = RUN_MODULE.Runner(self.root, {'git_commits': False, 'argv': [sys.executable, '-c', "from pathlib import Path;Path('bad-edit.txt').write_text('wrong scope')"]}) result = runner.run()