# Promote To Main

> >

- **Type:** Skill
- **Install:** `agentstack add skill-talont-org-autoskillit-promote-to-main`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [TalonT-Org](https://agentstack.voostack.com/s/talont-org)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [TalonT-Org](https://github.com/TalonT-Org)
- **Source:** https://github.com/TalonT-Org/AutoSkillit/tree/main/.claude/skills/promote-to-main

## Install

```sh
agentstack add skill-talont-org-autoskillit-promote-to-main
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Promote to Main

Orchestrate the integration-to-main promotion workflow. This skill discovers everything
that changed on integration since it diverged from main, runs pre-flight quality checks,
performs change inventory, generates architecture diagrams, synthesizes release notes,
and creates a comprehensive promotion PR.

## Arguments

```
/autoskillit:promote-to-main [batch_branch] [base_branch] [--dry-run]
```

- `batch_branch` (optional) — source branch to promote. Defaults to `integration`.
- `base_branch` (optional) — target branch. Defaults to `main`.
- `--dry-run` — generate the full PR body without creating a PR.

## When to Use

- When the develop branch is stable and ready to be promoted to main
- After feature PRs, bug fixes, and cleanup work have been collected and tested on develop
- This is the final gate before changes land on main

## Critical Constraints

**NEVER:**
- Create files outside `.autoskillit/temp/promote-to-main/`
- Modify any source code — this skill is read-only analysis + PR creation
- Fail silently if `gh` is unavailable — output `pr_url = ` (empty) and exit successfully
- Push or merge anything — this skill only creates the PR
- Skip pre-flight checks — a failing pre-flight must block PR creation
- Use the Bash tool for file reads — use Read, Grep, Glob for all codebase inspection
- Use `gh pr create --body` inline — always use `--body-file`

**ALWAYS:**
- Run ALL pre-flight checks before any analysis work
- Check `gh auth status` before any GitHub operations
- Output `pr_url = ` as a structured token (empty string when GitHub unavailable or dry-run)
- Output `verdict = ` as a structured token
- Carry forward ALL `Closes #N`, `Fixes #N`, and `Resolves #N` references from merged PR bodies
- Use `gh pr create --body-file` (never inline body via `--body`)
- `pr_body_path` must be an absolute path (prepend CWD)
## Workflow

### Phase 0: Setup

#### Step 0.1: Parse Arguments

Parse optional positional arguments and flags:
- `batch_branch` — default `"develop"` if absent or empty
- `base_branch` — default `"main"` if absent or empty
- `dry_run` — `true` if `--dry-run` present in ARGUMENTS

Validate that both branches exist locally:
```bash
git rev-parse --verify {batch_branch} 2>/dev/null
git rev-parse --verify {base_branch} 2>/dev/null
```
If either fails, try fetching:
```bash
git fetch origin {branch}:{branch} 2>/dev/null
```
If still missing, print error to stderr and exit 1.

#### Step 0.2: Compute Divergence Point

```bash
git merge-base {base_branch} {batch_branch}
```

Store as `merge_base_sha`.

Get commit count and timestamp:
```bash
git rev-list --count {merge_base_sha}..{batch_branch}
git show -s --format=%cI {merge_base_sha}
```
Store as `commit_count` and `merge_base_date`.

#### Step 0.3: Retrieve Token Summary from Session Logs

Determine the pipeline working directory and self-retrieve token telemetry from disk.
This aggregates token usage across all constituent PR sessions that ran in this pipeline
working directory.

```bash
mkdir -p .autoskillit/temp/promote-to-main
python3 -  .autoskillit/temp/promote-to-main/token_summary.md 2>/dev/null || true
import json, pathlib, sys
from autoskillit.pipeline.tokens import DefaultTokenLog
from autoskillit.pipeline.telemetry_fmt import TelemetryFormatter
from autoskillit.execution.session_log import resolve_log_dir

cfg_path = pathlib.Path(".autoskillit") / "temp" / ".hook_config.json"
kitchen_id = ""
if cfg_path.exists():
    _cfg = json.loads(cfg_path.read_text())
    if isinstance(_cfg, dict):
        kitchen_id = _cfg.get("kitchen_id") or _cfg.get("pipeline_id", "")

log_root = resolve_log_dir("")
tl = DefaultTokenLog()
n = tl.load_from_log_dir(log_root, kitchen_id_filter=kitchen_id)
if n == 0:
    sys.exit(0)
steps = tl.get_report()
total = tl.compute_total()
print(TelemetryFormatter.format_token_table(steps, total))
EOF
```

- If `.autoskillit/temp/promote-to-main/token_summary.md` is non-empty, set `TOKEN_SUMMARY_CONTENT` to its
  contents and embed it in the PR body under `## Token Usage Summary`.
- If empty or absent (standalone invocation, no pipeline sessions in this cwd), omit the
  section — graceful degradation with no error.

### Phase 1: Pre-flight Checks (parallel, blocking)

Spawn three parallel Task subagents (model: sonnet) to validate promotion readiness.
All three must pass before analysis proceeds. If any fails, report the failure clearly
and exit 1. Do NOT create a PR when pre-flight fails.
#### Subagent 1A: CI and Branch Status

Check:
1. CI is green on the integration branch — run `gh pr checks` for any open PR from
   integration, or `gh run list --branch {batch_branch} --workflow tests.yml --limit 1 --json conclusion`
2. The integration branch is not behind base — run `git rev-list --count {batch_branch}..{base_branch}`
   to check if base has commits not in integration (if > 0, warn that a rebase may be needed)
3. No open PRs targeting integration with failing CI — `gh pr list --base {batch_branch} --state open --json number,title,statusCheckRollup`

Return JSON:
```json
{
  "ci_status": "pass|fail|unknown",
  "ci_details": "description of CI state",
  "behind_base_by": 0,
  "open_prs_with_failing_ci": [],
  "pass": true
}
```

#### Subagent 1B: Version Consistency

Check:
1. `pyproject.toml` version matches `src/autoskillit/.claude-plugin/plugin.json` version
2. `uv lock --check` passes (lockfile consistent)
3. The integration branch version is ahead of the base branch version

Return JSON:
```json
{
  "pyproject_version": "X.Y.Z",
  "plugin_version": "X.Y.Z",
  "versions_match": true,
  "lockfile_consistent": true,
  "version_ahead_of_base": true,
  "pass": true
}
```

#### Subagent 1C: Outstanding Review Items

Check:
1. No open PRs targeting integration with `CHANGES_REQUESTED` reviews —
   `gh pr list --base {batch_branch} --state open --json number,title,reviews`
2. No `in-progress` labeled issues that might indicate incomplete work —
   `gh issue list --label in-progress --state open --json number,title`

Return JSON:
```json
{
  "prs_with_changes_requested": [],
  "in_progress_issues": [],
  "pass": true
}
```

**Pre-flight gate:** If any subagent returns `"pass": false`, report all failures in a
clear summary table and exit 1 without proceeding to analysis. If `ci_status` is `unknown`,
treat as a warning (non-blocking) and note it in the report.

### Phase 2: Change Inventory (parallel subagents)

Spawn four parallel Task subagents (model: sonnet).

#### Subagent 2A: Commit Categorization

Receive the output of:
```bash
git log {merge_base_sha}..{batch_branch} --format="%H %s"
```

Categorize each commit into exactly one category based on its subject line:
- `rectify` — subject contains "Rectify:" or "fix:" or "bugfix" (case-insensitive)
- `feature` — subject contains "Implementation Plan:", "feat:", "Add ", or introduces new capability
- `infra` — subject contains CI, workflow, config, build, or infrastructure changes
- `test` — subject only touches test files (infer from "test" in subject or `tests/` paths)
- `docs` — subject contains "docs:", "README", or documentation-only changes

Extract PR numbers from patterns like `(#123)` in commit subjects.

Return JSON:
```json
{
  "categories": {
    "rectify": [{"sha": "abc123", "title": "...", "pr_number": 495}],
    "feature": [],
    "infra": [],
    "test": [],
    "docs": []
  },
  "totals": {"rectify": 14, "feature": 13, "infra": 3, "test": 1, "docs": 1},
  "category_summary": "14 fixes, 13 features, 3 infra"
}
```

#### Subagent 2B: PR Discovery and Issue Linkage

Run:
```bash
gh pr list --base {batch_branch} --state merged --limit 200 --json number,title,author,mergedAt,body,headRefName,additions,deletions,labels,url
```

Filter to PRs merged after `merge_base_date`. If empty, fall back to commit-subject
discovery:
```bash
git log {merge_base_sha}..{batch_branch} --oneline --grep="(#" --format="%s"
```

For each PR, extract `Closes|Fixes|Resolves #N` references (case-insensitive).
Deduplicate across all PRs. For each linked issue number, fetch details:
```bash
gh issue view {number} --json number,title,state,url,labels 2>/dev/null
```

Build a traceability matrix: for each issue, identify which PR(s) close it.

Return JSON:
```json
{
  "prs": [{"number": 1, "title": "...", "author": "...", "labels": [], "url": "...", "additions": 0, "deletions": 0}],
  "closing_refs": ["Closes #42", "Fixes #50"],
  "linked_issue_numbers": [42, 50],
  "issue_details": [{"number": 42, "title": "...", "state": "OPEN", "url": "...", "labels": ["recipe:implementation"]}],
  "traceability": [{"issue_number": 42, "issue_title": "...", "pr_numbers": [491], "recipe_route": "implementation"}]
}
```

#### Subagent 2C: File Lifecycle Tracking

Run:
```bash
git diff --name-only {base_branch}..{batch_branch}
git diff --diff-filter=A --name-only {base_branch}..{batch_branch}
git diff --diff-filter=M --name-only {base_branch}..{batch_branch}
git diff --diff-filter=D --name-only {base_branch}..{batch_branch}
git diff --diff-filter=R --name-only {base_branch}..{batch_branch}
git diff --stat {base_branch}..{batch_branch} | tail -1
```

Return JSON:
```json
{
  "changed_files": ["..."],
  "new_files": ["..."],
  "modified_files": ["..."],
  "deleted_files": ["..."],
  "renamed_files": ["..."],
  "diff_stat_summary": "185 files changed, 10013 insertions(+), 1164 deletions(-)"
}
```

#### Subagent 2D: Migration and Schema Detection

Scan the diff for changes that require manual attention on merge. Check:
1. Changes to `src/autoskillit/migrations/` — new migration YAML notes
2. Changes to `src/autoskillit/recipe/schema.py` — recipe schema modifications
3. Changes to `pyproject.toml` — dependency additions/removals/version bumps
4. Changes to `src/autoskillit/config/defaults.yaml` — config schema changes
5. Changes to `src/autoskillit/hooks/hooks.json` — hook registration changes
6. Changes to `src/autoskillit/.claude-plugin/plugin.json` — plugin metadata changes
7. Changes to `.github/workflows/` — CI workflow modifications

For each detected change, provide a brief description of what changed and why it
might need attention.

Return JSON:
```json
{
  "migration_changes": ["Added migration note for v0.3.2"],
  "schema_changes": ["New RecipeStep field: optional"],
  "dependency_changes": ["Added httpx>=0.27"],
  "config_changes": ["New config key: github.staged_label"],
  "hook_changes": ["New hook: pretty_output PostToolUse"],
  "ci_changes": ["Updated tests.yml matrix"],
  "attention_required": true,
  "attention_summary": "Brief description of what needs human review"
}
```

### Phase 3: Architecture Diagrams

#### Step 3.1: Select Arch-Lens Lenses

Spawn a Task subagent (model: sonnet) with the `changed_files` list and this lens menu:

```
c4-container, concurrency, data-lineage, deployment, development,
error-resilience, module-dependency, operational, process-flow,
repository-access, scenarios, security, state-lifecycle
```

Return 1-3 lens names. Apply the same selection criteria as open-pr:

**Development lens guard:** Only select `development` if at least one changed file matches:
`pyproject.toml`, `Taskfile*`, `conftest.py`, `.github/workflows/*`, `Makefile`,
`setup.cfg`, `setup.py`, `tox.ini`, `noxfile.py`, or files under `ci/`.

For a promotion PR, prefer lenses that show the broadest architectural impact:
- `module-dependency` if changes span multiple packages
- `process-flow` if workflow routing or state transitions changed
- `c4-container` if new services, tools, or integrations were added

#### Step 3.2: Generate Arch-Lens Diagrams

For each selected lens, follow this exact sequence:

**CRITICAL:** Do NOT output any prose status text between lens iterations.
After completing all sub-steps for one lens, immediately begin sub-step 1 for the
next lens.

**1. Write the PR context to a file using the Write tool:**

- **Path:** `.autoskillit/temp/promote-to-main/pr_arch_lens_context_{YYYY-MM-DD_HHMMSS}.md`
- **Content:**

```markdown
# PR Context — Integration to Main Promotion

This diagram is for a promotion PR merging the integration branch into main. Focus on the areas of the codebase affected by all accumulated changes. Do not create a generic whole-project diagram.

## New files (use star prefix on these nodes):
{list of new_files, or "None"}

## Modified files (use bullet prefix on these nodes):
{list of modified_files, or "None"}

## Deleted files:
{list of deleted_files, or "None"}

## Instructions:
- Focus exploration and the diagram on the architectural areas these files belong to
- Use star prefix on nodes representing new files/components
- Use bullet prefix on nodes representing modified files/components
- Mark deleted components with strikethrough or a X prefix
- Leave unchanged components unmarked (include only if needed for context/connectivity)
- This is a promotion PR — show the cumulative architectural impact of all changes
```

**2. Immediately call the Skill tool** to load the arch-lens skill (e.g.,
`/autoskillit:arch-lens-module-dependency`).

**3. Follow the loaded skill's instructions** to generate the diagram.

Read the output from `.autoskillit/temp/arch-lens-{lens-name}/` and extract the mermaid block(s).

Validate: if the block contains at least one star marker or bullet marker for
new/modified nodes, add to `validated_diagrams`. Otherwise discard.

### Phase 4: Compose PR + Create PR

#### Step 4.1: Release Notes Synthesis

Spawn one Task subagent (model: sonnet) with results from Phase 2 ONLY (no domain
analysis or quality assessment data).
The subagent receives:
- Commit categorization from Subagent 2A
- PR and issue data from Subagent 2B
- File lifecycle from Subagent 2C
- Migration/schema detection from Subagent 2D

Return JSON:
```json
{
  "executive_summary": "3-5 sentence narrative of what this promotion brings, focused on change themes",
  "highlights": ["top 3-5 most significant changes"],
  "release_notes_md": "### New Features\n- ...\n### Bug Fixes\n- ...\n### Infrastructure\n...\n### Breaking Changes\n...\n### Attention Required\n..."
}
```

#### Step 4.2: Write PR Body

Write to `.autoskillit/temp/promote-to-main/pr_body_{YYYY-MM-DD_HHMMSS}.md`
(relative to the current working directory).

Sections in order:
1. `## Promotion: {batch_branch} to {base_branch}` — executive summary + stats (`diff_stat_summary`, `commit_count`, PR count)
2. `### Highlights` — from synthesis
3. `## Release Notes` — from synthesis
4. `## Merged PRs` — table (PR, Title, Author, Labels) from Subagent 2B
5. `## Linked Issues` — table (Issue, Title, Status, Action) from Subagent 2B
6. `## Attention Required` — from Subagent 2D (only if `attention_required=true`)
7. `## Architecture Impact` — validated mermaid diagrams from Phase 3
8. Closing references (`Closes #N` lines from Subagent 2B, one per line)
9. `## Token Usage Summary` — if TOKEN_SUMMARY_CONTENT non-empty
10. Footer: `Generated with Claude Code via AutoSkillit`

#### Step 4.3: Create PR

If `dry_run` is true: skip to Output section.

Check GitHub availability:
```bash
gh auth status 2>/dev/null
```
If exit code non-zero: output `pr_url = ` and exit successfully.

Construct PR title using actual branch names:
`Promote {batch_branch} to {base_branch} ({len(prs)} PRs, {len(linked_issue_numbers)} issues, {category_summary})`

```bash
gh pr create \
  --base {base_branch} \
  --head {batch_branch} \
  --title "{pr_title}" \
  --body-file .autoskillit/temp/promote-to-main/pr_body_{timestamp}.md
```

Capture the PR URL as `pr_url`.

Add label (optional, continue if fails):
```bash
gh pr edit {pr_url} --add-label "promotion" 2>/dev/null || true
```

### Output

Always emit these structured output tokens as the final lines:

```
pr_body_path = {absolute path to .autoskillit/temp/promote-to-main/pr_body_{timestamp}.md}
pr_url = {pr_url, empty if dry-run or gh unavailable}
verdict = {created|dry_run|preflight_failed}
category_summary = {e.g., "14 fixes, 13 features, 3 infra"}
```

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [TalonT-Org](https://github.com/TalonT-Org)
- **Source:** [TalonT-Org/AutoSkillit](https://github.com/TalonT-Org/AutoSkillit)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** yes
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-talont-org-autoskillit-promote-to-main
- Seller: https://agentstack.voostack.com/s/talont-org
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
