Skip to content

feat(launcher): mechanical engagement creation with the enforced machine RoE - #1058

Merged
PurpleCHOIms merged 8 commits into
mainfrom
feat/launcher-roe-mechanical
Oct 22, 2026
Merged

PurpleCHOIms merged 8 commits into
mainfrom
feat/launcher-roe-mechanical

Conversation

@PurpleCHOIms

Copy link
Copy Markdown
Member

Summary

The Go launcher joins the RoE unification (docs/design/2026-10-22-roe-unification.md — see the companion PR for phase 1): engagement creation generates the same machine-enforceable plan/roe.json the MCP bridge and CLI scan produce, the creation flow reviews the generated scope before committing, and the .red-approved approval marker / Red-approval ceremony is retired everywhere. Creating an engagement with a declared scope is the authorization (the operator owns it); the control point is the always-enforced RoE middleware, not an approval ceremony.

Changes

  • Mechanical creation (internal/engagement/scope_targets.go, new): the launcher compiles creation inputs through the core builder's normalization contract — multiple targets (URLs, hostnames, CIDRs, *.domain globs), optional out-of-scope denylist, embedded-list split, userinfo/bracket/port stripping, lowercase + trailing dot, wildcard apex. Pinned to the Python builder by shared golden test vectors (packages/decepticon-core/tests/testdata/roe-target-vectors.json, consumed by both suites). IDNA diverges on purpose: Go rejects non-ASCII with an actionable punycode message, Python IDNA-encodes.
  • Scope review before commit: promptNewEngagement shows the generated scope (in-scope entries, denylist, dropped patterns) via a huh Note + Confirm; createDirectEngagement takes the reviewed scopeLists instead of re-normalizing.
  • Marker retirement: the launcher no longer writes .red-approved; TUI prepareRedApproval//mode red approve removed (assertRedApproved now gates on an enforced machine block), /scope import no longer touches markers, the web plan-approval POST route is deleted and the terminal-server Red gate keys on scopeReady, provision_roe --approve-red removed. Picker, TUI and web readiness all mean "an enforced machine scope exists".
  • Picker UX: each engagement's description shows its scope summary (in-scope/denied counts + first target); counted title. Legacy dual-form RoE documents remain readable (object-form machine entries and human-only lists).
  • Breaking change: provision_roe --approve-red is gone; engagements whose documents carry no machine_enforcement block no longer enable Red. Recorded in CHAGELOG.md (Unreleased).

Intent

  • Issue / ADR this satisfies: docs/design/2026-10-22-roe-unification.md — companion launcher PR section (pulls parts of phases 2 and 4 forward per the maintainer's OSS responsibility-model decision).
  • Anti-goal: no middleware mode removal or HITL scope expansion — phases 3 and 5 remain separate PRs.

Blast radius

  • Tier-delegate — launcher/TUI/web engagement flows + guardrail restructure (documented in the design doc; the machine RoE enforcement is unchanged and remains the control point).

Diff budget

  • Fits: 2 Go files + 1 new Go module (~300 runtime lines across Go/TS/py); docs/tests excluded per QUALITY_BAR.

End-to-end verification

Ran on my machine (worktree feat/launcher-roe-mechanical, Go 1.25.8, npm workspace):

  1. go build ./... && go vet ./... && go test ./... → all packages pass, including 12 shared golden vector cases and the picker scope-summary tests.
  2. Launcher binary smoke: go build -o bin/decepticon . && ./bin/decepticon --help → banner renders.
  3. npm install (install-scripts approved) → node-pty native build succeeds; real PTY spawn smoke (pty.spawn('bash', …)) → PTY_OK.
  4. TUI: vitest run src/commands/ → 82 passed (12 files); web: tsc --noEmit -p . clean + node --import tsx --test "src/**/*.test.ts*" → 62 passed (terminal-server tests transpile the source in a VM, so the gate change is covered without a live PTY).
  5. Python: provision_roe tests 9 passed (including rejection of the removed --approve-red flag); full fast lane pytest -n auto -q -m "not slow" → 5933 passed, 43 skipped, 0 failed.

Testing

  • go test ./... (launcher module) — all pass
  • vitest (clients/cli commands) — 82 passed; web node --test — 62 passed
  • pytest -n auto -q -m "not slow" — 5933 passed
  • Every changed code path executed on my machine (verification items 1–5)
  • ruff clean on changed Python; gofmt applied; TUI/web typecheck clean
  • make quality / make smoke — not run locally (CI covers)

Quality Bar self-check

  • No banned pattern in the diff; no AI-slop signature survives; every changed line traces to the stated intent
  • Every public function I added/changed has explicit type annotations including return type; every raised exception is a named class
  • Guardrail note: the marker removal restructures the authorization ceremony per the design doc — machine RoE enforcement is unchanged and remains the control point
  • I would merge this PR if a stranger opened it

Related Issues

Companion to the RoE unification phase-1 PR (shared golden vectors reference). Retires the Red-approval marker pulled forward from phase 4.

mschoi added 3 commits October 22, 2026 14:21
…ine RoE

The Go launcher generates the same machine-enforceable plan/roe.json the MCP
bridge and CLI scan produce: multiple targets (URLs, hostnames, CIDRs, globs)
plus an optional out-of-scope denylist, normalized by the core builder's
contract pinned through shared golden test vectors. The .red-approved marker
and the Red-approval ceremony (/mode red approve, the web plan-approval POST,
provision_roe --approve-red) are retired — creating an engagement with a
declared scope is the authorization, the middleware enforces it, and
readiness on the picker, TUI Red gate and web dashboard is an enforced
machine scope. Legacy dual-form RoE documents stay readable.
The creation flow now compiles the targets through the shared normalization
contract and shows the generated scope — in-scope entries, the denylist, and
dropped patterns — for an explicit Create confirmation before any workspace
is written; createDirectEngagement takes the reviewed scopeLists instead of
re-normalizing. The engagement picker carries each engagement's scope summary
(in-scope/denied counts and first target) in its description and a counted
title, replacing the generic ready/in-progress copy.
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-22T05:55:51.542831Z
We couldn’t complete this review. Comment @codex review to try again.
1ed28ed PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

Comment thread clients/cli/src/commands/planMode.ts Fixed
mschoi added 5 commits October 22, 2026 15:11
CodeQL flagged a js/file-system-race in assertRedApproved: the scope was
lstat-checked and then read through a fresh path lookup, so a swap between
the two could redirect the parsed content. Open the file once, verify the
opened inode against the path (symlink refusal compares the path identity
to the handle), and parse the same handle's bytes.
Post-unification (#1057) enforcement is unconditional and the runtime
ignores the mode key, so the generated roe.json no longer writes
"mode":"enforce" and the picker's readiness gate keys on the presence
of a machine block with in-scope entries — matching the runtime for
legacy documents too (a legacy audit-mode block is read as ready, since
that is what the runtime does with it).
…hanical

# Conflicts:
#	CHAGELOG.md
#	clients/launcher/internal/engagement/picker.go
@PurpleCHOIms
PurpleCHOIms merged commit 6a63dcc into main Oct 22, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants