Skip to content

feat(st3): integration adapters — loop/integrations.py + LangGraph & Temporal recipes - #32

Merged
SollanSystems merged 9 commits into
mainfrom
feat/v0.8.0-composes-the-field
Jul 9, 2026
Merged

SollanSystems merged 9 commits into
mainfrom
feat/v0.8.0-composes-the-field

Conversation

@SollanSystems

Copy link
Copy Markdown
Owner

Summary

PR-A of the v0.8.0 "composes the field" milestone — ST3: integration adapters. Spec: docs/superpowers/specs/2026-07-08-v0.8.0-composes-the-field-design.md (normative mapping/precedence: docs/superpowers/specs/2026-06-30-st3-integration-adapters.md).

Three deliverables:

  1. loop/integrations.py — engine-neutral, pure-stdlib projection (EngineOutcome + to_terminal_state) from any engine's "the run ended" signal onto the 7 typed terminal states, fixed precedence safety → human → blocked → budget → spec-gap → gate verdict. Succeeded is structurally unreachable without a green holdout_gate.decide verdict + clean anticheat + a met criterion + evidence + reached_end; false_completion is copied from the gate, never synthesized; missing/invalid gate or anticheat input fails closed to FailedUnverifiable. 14 unit tests pin all of the above.
  2. LangGraph recipe upgraded in place (examples/langgraph-emit/) — the certify node now routes gate → anticheat → adapter → loop.emit; the run scores clean under loop metrics (closes the recorded FCR-1.0 follow-up); sabotage path pins the false-completion invariant. Verified against langgraph 1.2.8.
  3. Temporal recipe (new) (examples/temporal-certify/) — certify-activity pattern (the certify activity is the workflow's only path to a returned result); cancellation → AbortedByHuman proven e2e on a real local Temporal dev server; retry exhaustion → FailedBlocked and timeout → FailedBudget covered at the mapper level; metrics-clean like its sibling. Verified against temporalio 1.30.0.

Acceptance criteria: spec §5 items 1–3 + 6.

Adjudicated deviation (documented carve-out)

Both recipes reset <ws>/RUNLOG.md to emit's own fresh header immediately after open_contract — a direct contract-file write, against the letter of the emit-only constraint. Root cause (confirmed independently by two reviewers): the scaffold seeds an unfilled {{ITERATION_OUTCOME}} placeholder that loop metrics flags as an unrecognized outcome token, and the root fix lives in templates//loop/scaffold.py/loop/emit.py — all outside PR-A's file discipline. The whole-branch review accepted the reset as an honest, contained carve-out (it strips a placeholder, never fabricates state; the header is byte-identical to emit.py's own). Recorded in the plan's Global Constraints; the root-fix affordance (e.g. emit.open_contract(seed_runlog=False)) will be filed as a PR-B contributor issue.

For the human reviewer

  • Commit e13adcf (root CLAUDE.md) rode along on this branch (authored outside this run). The whole-branch review flags it as unfit for the public 0.8.0 cut as-is: the file says "do NOT commit CLAUDE.md" yet is committed; it embeds machine-local /mnt/c/... paths and local-marketplace notes; its "395 tests" figure is stale. No secrets, no gate impact — ST3 code is unaffected. Needs a decision before the PR-B release cut (drop vs. genericize).

Test plan

  • python3 -B scripts/validate_frontmatter.py — 0 errors
  • python3 -B scripts/self_eval.py — 13/13 (100%)
  • uv run --with pytest --with pyyaml --with jsonschema --with langgraph --with temporalio python -B -m pytest -q -p no:cacheprovider scripts391 passed / 9 skipped (baseline 372/10 + ST3 tests; recipe suites run for real)
  • python3 -B -m py_compile loop/*.py scripts/*.py — clean
  • python3 -B -m loop doctor examples/coverage-repair — ok
  • python3 -B -m loop inspect examples/coverage-repair — 90 / strong
  • CI: gates ×3 pythons, recipe-langgraph, recipe-temporal, action-dogfood all green
  • Reviews: per-task spec+quality reviews (Tasks 1–3, all Approved incl. one fix round on Task 3 pinning the metrics-clean claim) + whole-branch review (Ready to merge, zero Critical, carried Minors triaged ACCEPT → PR-B cleanups).

Copilot AI review requested due to automatic review settings July 9, 2026 00:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@SollanSystems
SollanSystems merged commit 68ee4d9 into main Jul 9, 2026
7 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f4158953fb

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread loop/integrations.py
Comment on lines +57 to +61
return (
isinstance(gate.get("verdict"), str)
and isinstance(gate.get("false_completion"), bool)
and _valid_checks(gate.get("visible"))
and _valid_checks(gate.get("holdout"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Recompute gate results before trusting Succeeded

When an adapter receives a malformed or tampered gate dict, _valid_gate only checks that verdict, false_completion, and non-empty check arrays exist; it does not require passed_visible/passed_holdout or re-derive them from the per-check evidence. As a result, a payload such as verdict: "Succeeded", false_completion: false, and a failed holdout check passes validation and to_terminal_state() returns Succeeded, after which emit.terminate will write a successful terminal. This violates the new adapter invariant for any caller that persists or forwards a corrupted gate result instead of the exact holdout_gate.decide() output; validate the flags/verdict against visible and holdout before allowing success.

Useful? React with 👍 / 👎.

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