fix(sdlc-launcher): spawn conductor in new console window, drop --web-bg - #302
Merged
Merged
Conversation
PR #300 used --web-bg for the detached launch path. Conductor's bg_runner spawns the workflow child with stdin=DEVNULL (cli/bg_runner.py:172,178,210), which kills any agent that reads stdin — most notably gate agents waiting for the operator's stdin-fallback answer. The web dashboard's 'Answer' button POSTs successfully but no listener is alive to consume it because the gate subworkflow dies with EOFError before it can register one. The failure cascades up through subworkflow_failed → for_each_item_failed. Observed during AB#3071 dogfood 2026-05-11: two parallel plan-level open-questions gates failed within 14ms of being presented; the user's answer never reached an agent. Fix: always pass --web (not --web-bg). Detached path now spawns conductor inside a *new* PowerShell console window via Start-Process pwsh -NoExit. The new window has its own console, so conductor inherits a real TTY (stdin attached). --web foreground works, gate agents can read stdin fallback, and the operator's launching shell stays free. The new window keeps -NoExit so post-mortem stack traces stay visible. Output is also tee'd to a transcript log under %TEMP%\polyphony-sdlc-runs\apex-{id}-{ts}-transcript.log. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PolyphonyRequiem
pushed a commit
that referenced
this pull request
May 12, 2026
PR 3 of AB#3085. Replaces the legacy launcher (whose
`WorktreeRoot = (Get-Location).Path` default was the root cause of the
main-worktree hijack bug) with a self-derivation contract over the
existing CLI verbs.
11-phase preflight chain:
1. cwd is in a git worktree (fail-fast with link to layout doc)
2. bare-repo layout preflight (refuses non-bare clones with link to
Migrate-ToBareRepo.ps1; -SkipLayoutCheck escape hatch)
3. polyphony worktree init-apex (--dry-run on -DryRun) — self-derive
the apex worktree path; surface every failure reason with
remediation text
4. hijack refusal (defense-in-depth: refuse if derived path is or is
inside the main worktree)
5. -WorktreeRoot override validation (must canonicalize to derived
path; OrdinalIgnoreCase on Windows, normalized trailing slash)
6. intent semantics (-Intent resume + outcome=created refused)
7. .twig/ propagation (gitignored, so freshly-added apex worktrees
lack it; copied from main on first launch; never clobbered)
8. assert-clean integration (skipped on -DryRun; surfaces dirty /
wrong-branch / git-op-in-progress with remediation text)
9. metadata derivation (platform + repository auto-detected from
main worktree's git remote)
10. conductor command construction (6 -m flags + apex/intent/platform/
repo inputs; git_repo defaults to main_worktree_path)
11. conductor launch (PR #302's new-console-window pattern preserved
for TTY-attached gate stdin)
Subsumes PR #302 per Daniel's call. Stacked on PR #311 (init-apex
extensions: --dry-run flag, runs_root/main_worktree_path output
fields). Will rebase clean once #311+#312 merge.
C# extensions to polyphony worktree init-apex:
- New --dry-run flag (read-only mirror of create/attach matrix; emits
same hard-refusal envelopes; emits outcome=dry_run on success)
- New output fields on WorktreeInitApexResult: runs_root,
main_worktree_path, dry_run (surface on success AND on
after-resolution failures so launcher can format errors uniformly)
- New outcome enum value: dry_run
Tests:
- 32 new Pester tests / 32 pass — real bare-repo + git-worktree
fixtures per test (mirrors Migrate-ToBareRepo.Tests pattern); no
init-apex/assert-clean mocking
- 8 new xUnit tests / 29 InitApex tests pass total
Rubber-duck-validated design (see PR body for the 11 design
decisions).
Closes AB#3098.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PolyphonyRequiem
added a commit
that referenced
this pull request
May 12, 2026
…314) * feat(worktree): add `worktree create` verb (AB#3096, PR 1b3) Adds `polyphony worktree create --apex N --branch B [--ref R]` — the per-item worktree creation primitive used by all workflow steps that need an impl/, plan/, mg/, or evidence/ worktree under an apex run. Mirrors the structure of `worktree init-apex` (PR #311 / PR 1b2): branch-grammar validation, bootstrap-dependency check, race-tolerant idempotent recovery. Rubber-duck-validated decisions: - Bootstrap dependency is structural: `{apex_root}/feature-{N}` must be a registered worktree on `feature/{N}`, not just Directory.Exists. Catches partial-init in one signal. - Reject `feature/{N}` branches with `unsupported_branch_kind`: init-apex is the canonical path; otherwise create becomes an unprotected back-door. - `remote_branch_exists` always wins (even with `--ref`): workflow-rerun safety; operator must explicitly fetch+branch first to avoid silent fork. - No cwd-refusal: path is self-derived from runs_root; cwd has no impact on safety. Stacked on PR #311. Branch off `feature/worktree-init-apex` tip; rebase onto main once #311 merges. Part of AB#3085 (bare-repo + per-run worktree epic). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(launcher): bare-repo + per-run-worktree rework (AB#3098, PR 3) PR 3 of AB#3085. Replaces the legacy launcher (whose `WorktreeRoot = (Get-Location).Path` default was the root cause of the main-worktree hijack bug) with a self-derivation contract over the existing CLI verbs. 11-phase preflight chain: 1. cwd is in a git worktree (fail-fast with link to layout doc) 2. bare-repo layout preflight (refuses non-bare clones with link to Migrate-ToBareRepo.ps1; -SkipLayoutCheck escape hatch) 3. polyphony worktree init-apex (--dry-run on -DryRun) — self-derive the apex worktree path; surface every failure reason with remediation text 4. hijack refusal (defense-in-depth: refuse if derived path is or is inside the main worktree) 5. -WorktreeRoot override validation (must canonicalize to derived path; OrdinalIgnoreCase on Windows, normalized trailing slash) 6. intent semantics (-Intent resume + outcome=created refused) 7. .twig/ propagation (gitignored, so freshly-added apex worktrees lack it; copied from main on first launch; never clobbered) 8. assert-clean integration (skipped on -DryRun; surfaces dirty / wrong-branch / git-op-in-progress with remediation text) 9. metadata derivation (platform + repository auto-detected from main worktree's git remote) 10. conductor command construction (6 -m flags + apex/intent/platform/ repo inputs; git_repo defaults to main_worktree_path) 11. conductor launch (PR #302's new-console-window pattern preserved for TTY-attached gate stdin) Subsumes PR #302 per Daniel's call. Stacked on PR #311 (init-apex extensions: --dry-run flag, runs_root/main_worktree_path output fields). Will rebase clean once #311+#312 merge. C# extensions to polyphony worktree init-apex: - New --dry-run flag (read-only mirror of create/attach matrix; emits same hard-refusal envelopes; emits outcome=dry_run on success) - New output fields on WorktreeInitApexResult: runs_root, main_worktree_path, dry_run (surface on success AND on after-resolution failures so launcher can format errors uniformly) - New outcome enum value: dry_run Tests: - 32 new Pester tests / 32 pass — real bare-repo + git-worktree fixtures per test (mirrors Migrate-ToBareRepo.Tests pattern); no init-apex/assert-clean mocking - 8 new xUnit tests / 29 InitApex tests pass total Rubber-duck-validated design (see PR body for the 11 design decisions). Closes AB#3098. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Daniel Green <dangreen@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR #300 used --web-bg for the detached launch path. Conductor's
�g_runner spawns the workflow child with stdin=DEVNULL
(cli/bg_runner.py:172,178,210), which kills any agent that reads
stdin — most notably gate agents waiting for the operator's
stdin-fallback answer. The dashboard's Answer button POSTs
successfully but no listener is alive to consume it because the gate
subworkflow dies with EOFError before it can register one. The failure
cascades up through
subworkflow_failed→for_each_item_failed.Repro / observed failure
AB#3071 dogfood 2026-05-11: two parallel plan-level open-questions
gates (items 3073, 3074) failed within 14ms of being presented.
Dashboard event timeline:
09:51:12.204 agent_started open_questions_gate 09:51:12.208 gate_presented open_questions_gate 09:51:12.222 workflow_failed open_questions_gate EOFError 09:51:12.240 → cascade: plan_level_dispatch → dispatch_items → for_each_item_failedOperator's Answer click reached the API as
Answer · sent · awaiting…but no agent ever consumed it.Fix
Always pass
--web(not--web-bg). Detached path now spawns conductor inside a new PowerShell console window viaStart-Process pwsh -NoExit -Command …. The new window has its own console, so conductor inherits a real TTY (stdin attached). Foreground--webworks, gate agents can read stdin fallback, and the operator's launching shell stays free. The new window keeps-NoExitso post-mortem stack traces stay visible.Output also tee'd to a transcript log under
%TEMP%\polyphony-sdlc-runs\apex-{id}-{ts}-transcript.log.Test
Dry-run from sibling worktree confirms args and worktree resolution. Live restart of AB#3071 from
polyphony-3071worktree validates the gate-stdin-EOF cascade is gone.Trade-offs