Skip to content

Epic: make the adoption walk compose — preview → init --local-review → verify #327

Closed

Description

@pengfei-threemoonslab

Completed with #325 (2026-09-04), consistent with the owner's closure scope. #326 shipped in #486; #323's subprocess adoption fixture in #459 proves that the emitted actions compose, including human-owned declaration review and setup/release authority separation. Revalidated the 16-test adoption suite. #309 remains deferred relevance work; #328 remains the independently tracked output taxonomy problem and #329 is complete. #506/#485/#497/#498 and #521 are follow-on distribution/activation work, not unfulfilled requirements of this delivered epic.

Why this epic exists

Every issue below was found in a single walk through the adoption flow against external repositories — usestrix/strix, google/adk-python#6605, google/adk-samples#1745. None was found by a test. They are filed as separate defects, but they share one root cause pattern:

Each step's output does not quite compose with the next step's input.

Preview identifies a diff but not the framework in it. Init writes a manifest but names the wrong agent and then routes past its own unresolved placeholders. Scan fails on a binding shape the adapter itself understands. Each defect is individually small; together they are the reason a first-contact evaluation does not complete without a human reading source code.

Fixing them one at a time produces seven local fixes and no guarantee the flow composes at the end. This epic defines the flow those fixes must add up to.

Shared control-plane dependency: #333 defines the v0.17 envelope; #323 owns its v0.18 rollout. #322 is the invocation child of #334.

Target experience

The adoption walk should collapse to three clear stages.

verify --preview
  → identify the framework (e.g. ADK) and the actual changed files
  → explicitly require initializing a local evaluation config

init --local-review
  → generate the manifest
  → pause and require confirmation of the root agent and declared purpose

verify
  → scan shared tool bindings
  → produce receipt, handoff, report
  → complete / agent_action_required / human_review_required

Note what is absent: there is no user-facing scan stage. scan remains the engine; verify is the command an adopter runs.

Invariants

Every stage must satisfy all five.

  1. Exactly one executable next action. Not a ranked menu, not a sentence containing a command, not a prerequisite and a command joined by "then".
  2. Suggested commands preserve the current invocation style. A flow entered through python -m agents_shipgate stays runnable through it.
  3. Unreadable evidence is reported as unknown or insufficient — never as "no change". An input the tool could not read must never be rendered as a finding about the repository.
  4. Product defects are distinguished from user configuration errors. A crash in our extractor must not be presented as something the user misconfigured.
  5. Proceeding must not require understanding the internal identity model. No source_type / source_id / native_locator vocabulary in anything an adopter is expected to act on.

Issue map

Stage 1 — verify --preview

Stage 2 — init --local-review

Stage 3 — verify

Cross-cutting

Gaps this epic exposes

The two previously unowned invariants now have explicit owners:

Invariant 4 — #328. Today the distinction is inverted in at least two places. #307's ID collision surfaced as internal_error routing the user to init --minimal — a product defect presented as a recovery the user should perform. #321 raises InputParseError, which reads as "your input is malformed" for what is a defect in our extractor. A first-contact adopter cannot tell "this repository is unusual" from "this tool is broken", and will reasonably assume the former. Needs a taxonomy: which exit codes and error kinds mean ours versus yours, and a rule that a product defect never emits a user-remediation action.

Invariant 5 — #329. #321's error message is the clearest violation — it prints source_type=, source_id=, and native_locator= at an adopter — but the principle is broader than that one message and nothing tracks it. Needs an audit of adopter-facing strings for internal-model vocabulary.

Conflicts to resolve before the member issues land

#325's routing target is now aligned. Placeholder resolution advances to verify, not a user-facing scan stage.

#318 targets a surface this flow demotes. It is written against the scan console output. If scan stops being an adopter-facing stage, the framework-aware remediation belongs on verify's terminal output instead. The underlying defect — renderers overwriting what release_decision already decided — is unchanged either way.

#326's surface justification is now settled. It was held unmilestoned pending a headline metric under the CONTRIBUTING.md gate. This flow makes local-review a named stage rather than an optional mode, and the metric is time-to-first-verdict / activation rate: it is the step that lets an external PR be evaluated at all without mutating the target worktree. The security boundary in that issue still governs the design — an ephemeral manifest must not be able to produce something shaped like reviewed release evidence.

Stage 2 implies a default change. Making init --local-review the stage-2 command means the evaluation path is local-review and init --write is the durable-adoption path chosen deliberately. That is a reasonable split, but it should be stated, since init --write is what preview routes to today.

Definition of done

A single end-to-end fixture walks an unadopted external repository through all three stages using only the emitted next action at each step — no source reading, no manual command construction, no internal vocabulary — and reaches a terminal control state. The same fixture must be able to reach human_review_required honestly: the goal is a flow that completes, not a flow that always says yes.

Non-goals

  • Weakening insufficient_evidence where the diff is a capability change.
  • Letting an agent author binding, effect, or authority declarations (do_not_auto_assert).
  • Making local-review artifacts indistinguishable from repository-reviewed evidence.
  • A second verdict: every control state stays a projection of release_decision.decision.

Activity

  1. added this to the v0.17.0 milestone on Aug 7, 2026
  2. added
    P1Picked up inside the current milestone window; keep about 15 open
    area:initinit / detect / manifest generation
    area:agent-modeAgent-mode contract: control envelope, next actions, command strings
    epicTracking issue coordinating a group of related issues
    area:adapterFramework input adapters and tool catalog construction
    area:verifyverify / preview orchestration and SHIP-VERIFY-* checks
    area:triggerTrigger catalog and relevance routing
    on Aug 7, 2026
  3. pengfei-threemoonslab commented on Aug 7, 2026

    @pengfei-threemoonslab
    ContributorAuthor

    Milestone update: this epic moves to v0.18.0, with one member staying in v0.17.0.

    Why. v0.17.0 was holding 24 issues, which is a backlog with a label rather than a release. It is now scoped to the control plane and deadlock removal — the foundation this epic and #338 both consume:

    Everything else in this epic — #311, #315, #320, #324, #325, #326, #318, #322, #328, #329, and the fixtures #310/#316 — lands in v0.18.0 on top of that foundation.

    #323 is merging into #333. They are the same surface from opposite ends: #323 horizontal (every command speaks one vocabulary), #333 vertical (compact, unambiguous about what is permitted). Both edit core/agent_control.py. They ship as one design in v0.17.0, and this epic's stage-3 terminal states (complete / agent_action_required / human_review_required) become a consumer of it rather than a separate definition.

    One open question moves with it. The #325 triage raised that init and doctor have no release_decision to project a control state from, so their state derives from setup facts instead. That question is now an input to the v0.17.0 envelope design, not something #325 settles on its own — otherwise the envelope ships with control_state meaning "the gate says" in one command and "setup says" in another. #325 then implements the answer in v0.18.0.

    Sequencing inside v0.18.0 is unchanged from the triage on each issue: #311+#315 as one PR after PR #340 merges (it holds docs/triggers.json), #320+#324 as one PR (same function in signals.py), fixtures after their trigger dependencies, and #312 last so the numbers describe what actually shipped.

  4. removed this from the v0.18.0 milestone on Aug 31, 2026
  5. pengfei-threemoonslab commented on Aug 31, 2026

    @pengfei-threemoonslab
    ContributorAuthor

    Unmilestoned in the re-cut: epics span milestones. Remaining members are #326 (v0.18.0) and #325 (v0.19.0); #323 closed via PR #459 with the composing-walk fixture. The epic closes when the two members land.

  6. pengfei-threemoonslab commented on Sep 2, 2026

    @pengfei-threemoonslab
    ContributorAuthor

    Checklist updated: #323 shipped via #459 (envelope rollout + the composing-walk fixture), #326 shipped via #486 (side-effect-contained local review). Remaining: #325 (v0.19.0) and #309 (unmilestoned stretch, gated on its metric decision). The epic closes with #325.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Picked up inside the current milestone window; keep about 15 openarea:adapterFramework input adapters and tool catalog constructionarea:agent-modeAgent-mode contract: control envelope, next actions, command stringsarea:initinit / detect / manifest generationarea:triggerTrigger catalog and relevance routingarea:verifyverify / preview orchestration and SHIP-VERIFY-* checksepicTracking issue coordinating a group of related issues

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions