feat: Adopt an off-pipeline change into the Fab pipeline#451
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new /fab-adopt “late entry” orchestrator that adopts an off-pipeline branch into the existing Fab pipeline by reconstructing artifacts from the branch diff, skipping apply, and then running review/hydrate/ship/review-pr normally. This is supported by a small extension to shared review dispatch (_review.md) and an enhancement to /git-pr so existing OPEN PRs can be retrofitted with the ## Meta block.
Changes:
- Introduce
/fab-adoptorchestration + supporting diff-based artifact generation procedures in_generation.md. - Add
_review.mdmodeparameter (fullvsoutward-only) so adoption can run outward-only review. - Enhance
/git-prto retrofit## Metaonto existing OPEN PRs (idempotent guard), and sweep specs/memory docs to document the new behavior.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/kit/skills/git-pr.md | Adds Step 3d to retrofit ## Meta onto an existing OPEN PR; updates “already shipped” path to also run retrofit. |
| src/kit/skills/fab-adopt.md | New orchestrator skill to adopt off-pipeline work into the pipeline (apply skipped; review/hydrate/ship run). |
| src/kit/skills/_review.md | Adds review dispatch mode (full / outward-only) and mode-gated preconditions/dispatch behavior. |
| src/kit/skills/_preamble.md | Adds a “no new state-table row needed” adoption note for Next: lookup. |
| src/kit/skills/_pipeline.md | Documents /fab-adopt as a partial consumer of _pipeline (reuses loop + hydrate dispatch). |
| src/kit/skills/_generation.md | Adds Intake-from-Diff and Plan-from-Diff procedures for adoption. |
| src/go/fab/cmd/fab/fabhelp.go | Groups fab-adopt under “Planning” in /fab-help. |
| fab/changes/260630-t54n-adopt-off-pipeline-change/plan.md | Change plan documenting requirements/tasks/acceptance for the feature. |
| fab/changes/260630-t54n-adopt-off-pipeline-change/intake.md | Change intake capturing rationale, scope, and design decisions. |
| fab/changes/260630-t54n-adopt-off-pipeline-change/.status.yaml | Status snapshot for this change. |
| fab/changes/260630-t54n-adopt-off-pipeline-change/.history.jsonl | History events for this change. |
| docs/specs/user-flow.md | Updates diagrams/text to include /fab-adopt as an alternate entry point. |
| docs/specs/stage-models.md | Adds /fab-adopt to the orchestrators list consuming fab resolve-agent. |
| docs/specs/skills/SPEC-git-pr.md | Specs the new Step 3d ## Meta retrofit behavior. |
| docs/specs/skills/SPEC-fab-adopt.md | New spec mirror for the /fab-adopt skill. |
| docs/specs/skills/SPEC-_review.md | Updates spec mirror for _review to include mode and gating behavior. |
| docs/specs/skills/SPEC-_preamble.md | Mirrors the adoption note added to _preamble.md. |
| docs/specs/skills/SPEC-_pipeline.md | Mirrors _pipeline “partial consumer” note for /fab-adopt. |
| docs/specs/skills/SPEC-_generation.md | Mirrors the two new diff-based generation procedures. |
| docs/specs/skills.md | Adds /fab-adopt to skill catalog (helpers + behavior). |
| docs/specs/overview.md | Adds /fab-adopt to the quick reference table. |
| docs/specs/glossary.md | Adds /fab-adopt and “Adopt” terminology. |
| docs/memory/pipeline/schemas.md | Documents skip+reset transition composition for adoption’s honest state. |
| docs/memory/pipeline/planning-skills.md | Documents diff-based generation procedures for adoption. |
| docs/memory/pipeline/index.md | Updates pipeline index entries to mention adoption entry-point. |
| docs/memory/pipeline/execution-skills.md | Documents /fab-adopt behavior, _review mode, and /git-pr meta retrofit. |
| docs/memory/pipeline/change-lifecycle.md | Adds adoption section describing apply-skipped honest-state pattern. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 1. Fetch the current PR body: `gh pr view --json body -q '.body'`. | ||
| 2. **Idempotency guard**: if the body already contains a `## Meta` heading, make **no** edit — print nothing and continue (a second run is a no-op; Constitution III). | ||
| 3. Otherwise render the Meta block via `fab pr-meta` (reusing Step 3c's mechanism — same `{name}`, resolved `{type}`, space-joined `{issues}`): | ||
| ```bash | ||
| META=$(fab pr-meta "{name}" --type {type} --issues "{issues}" 2>/dev/null) || META="" | ||
| ``` | ||
| - If exit non-zero or `META` is empty (no fab context / change unresolved / `.status.yaml` absent): make **no** edit and continue silently — same graceful degradation as Step 3c's Meta omission. | ||
| 4. Prepend the rendered Meta block to the existing body (Meta first, then a blank line, then the original body verbatim) and apply it via stdin (avoids shell-quoting issues with multi-line bodies): | ||
| ```bash | ||
| printf '%s\n\n%s\n' "$META" "$existing_body" | gh pr edit --body-file - | ||
| ``` |
There was a problem hiding this comment.
Fixed — Step 3d sub-step 1 now captures the PR body into existing_body, matching the variable referenced in the prepend step (sub-step 4). (6c02221)
| 1. **Detached HEAD / default-branch guard** (reuse `/git-pr`'s messages): | ||
| - `branch` empty (detached HEAD) → STOP: `Cannot ship from a detached HEAD — check out a branch first (run /git-branch).` | ||
| - `branch` is the default branch (or literal `main`/`master`) → STOP: `Cannot adopt from the default branch ({default_branch}).` |
There was a problem hiding this comment.
Fixed — the guard note no longer claims verbatim message reuse; it now states the detached-HEAD message is reused verbatim while the default-branch message is adapted to the adopt context. (6c02221)
| | Condition | Action | | ||
| |-----------|--------| | ||
| | Detached HEAD | STOP: "Cannot ship from a detached HEAD — check out a branch first (run /git-branch)." | | ||
| | On default branch | STOP: "Cannot adopt from the default branch ({default_branch})." | | ||
| | PR already MERGED | STOP: scenario-A out-of-scope message (Step 0.2) | |
There was a problem hiding this comment.
Skipped — the adopt-specific "Cannot adopt from the default branch" wording is intentional; matching /git-pr's "Cannot create PR …" would be semantically wrong for adopt, which operates on already-open or not-yet-created PRs (it is not the PR-create operation). The false verbatim-reuse claim that motivated the mismatch is now fixed at the Step 0 guard note.
Meta
t54nexcludes
fab/,docs/· generated by fab-kit v2.7.1Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr
Summary
Adds
/fab-adopt, a thin orchestration skill that brings an off-pipeline branch into the Fab pipeline without re-authoring the code. It reconstructs intake + plan from the diff, runs a real review and hydrate pass (fixing the permanent-loss problem of undocumented memory drift), retrofits the## Metablock onto an existing open PR, and then lands inreview-pr. Alongside this,_review.mdgains amodeparameter (full/outward-only) and/git-prgains a body-retrofit path so the Meta block is injected into open PRs that are missing it.Changes
/fab-adopt(orchestrator) —src/kit/skills/fab-adopt.md+SPEC-fab-adopt.mdmirrormodeparameter in_review.md(fulldefault /outward-only) — with precondition gating and parallel dispatch changes/git-prbody-retrofit path — injects## Metainto open PRs lacking it, gated for idempotency_generation.mdskills.md,glossary.md,overview.md,user-flow.md,_preamble.md, pipeline memory docs