---
name: eck:submit-to-repo
version: "0.7.4"
description: Submit catalog improvements to the upstream GitHub repository via fork-based pull requests.
disable-model-invocation: false
---

# Submit To Repo Workflow

Submit catalog improvements harvested by `/eck:push-to-user-catalog` from your catalog (`$ECK_HOME/`) to the `evolvconsulting/evolv-coder-kit` GitHub repository via a fork-based PR workflow.

---

## Visual Framework

Follow these conventions for all terminal output displayed to the user via the Bash tool.

### Output Mode Awareness

Before producing output, read the user's preferred output mode:

```bash
cat $ECK_HOME/user-preferences.json 2>/dev/null
```

Extract the `outputMode` field and adapt verbosity:

- **guided** — Add explanatory prose after key steps. Describe what is happening and why.
- **standard** (default) — Balanced. Show steps with brief context for non-obvious decisions.
- **concise** — Steps and summary box only. No prose, no explanations.

If the file is missing or `outputMode` is absent, use **standard**.

### ANSI Colors

Declare these variables at the top of **every** Bash tool call (shell state does not persist between calls):

```bash
source $ECK_HOME/colors.sh
```

Every color sequence **must** end with `${RESET}`. No exceptions.

### Stage Banners

Mark major stage transitions with a banner. One blank line before and after.

```bash
echo ""
printf '%b\n' "${ORANGE}${BOLD}STAGE NAME${RESET}"
echo ""
```

### Status Symbols

| Symbol | Meaning          | Color       |
| ------ | ---------------- | ----------- |
| `[*]`  | Active / running | `${CYAN}`   |
| `[x]`  | Completed        | `${GREEN}`  |
| `[!]`  | Error            | `${RED}`    |
| `[-]`  | Skipped          | `${DIM}`    |
| `[>]`  | In progress      | `${YELLOW}` |
| `[ ]`  | Pending          | `${DIM}`    |

```bash
printf '%b\n' "${GREEN}[x]${RESET} Step completed"
printf '%b\n' "${RED}[!]${RESET} Something failed"
```

No emoji in output. Use only these bracket symbols for status.

### Summary Boxes

Display at checkpoints and at the end of the skill. One blank line before and after.

```bash
echo ""
printf '%b\n' "${ORANGE}${BOLD}Title${RESET}"
echo ""
printf '%b\n' "Label: Value"
echo ""
```

### Error Format

```bash
printf '%b\n' "${RED}[!]${RESET} Error message here"
printf '%b\n' "    ${DIM}Recovery guidance here.${RESET}"
```

### Spacing Rules

- One blank line before and after stage banners and summary boxes.
- No blank lines within step lists.
- Maximum output line width: 70 characters.

### Statusline Stage Updates

At the **start** of each stage, update the statusline:

```bash
bash $ECK_HOME/update-stage.sh "{Statusline text from table}"
```

At **skill completion** (success or error), reset:

```bash
bash $ECK_HOME/update-stage.sh
```

---

## Task Registration

| Stage | Subject                 | Active Form             | Statusline      |
| ----- | ----------------------- | ----------------------- | --------------- |
| 1     | Stage 1: Pre-Flight     | Verifying prerequisites | Preflight (1/9) |
| 2     | Stage 2: Detect Changes | Detecting changes       | Changes (2/9)   |
| 3     | Stage 3: Select         | Selecting components    | Select (3/9)    |
| 4     | Stage 4: De-Projectify  | De-projectifying        | DeProject (4/9) |
| 5     | Stage 5: Fork           | Forking repository      | Fork (5/9)      |
| 6     | Stage 6: Push           | Pushing changes         | Push (6/9)      |
| 7     | Stage 7: Create PR      | Creating pull request   | CreatePR (7/9)  |
| 8     | Stage 8: Tracking       | Updating tracking       | Tracking (8/9)  |
| 9     | Stage 9: Cleanup        | Cleaning up             | Cleanup (9/9)   |

## Usage

```bash
/eck:submit-to-repo                          # Submit all pending improvements
```

**Must have `gh` CLI installed and authenticated.** Templates are read from `$ECK_HOME/`.

---

## Stage 1: Pre-Flight

### Inputs

- `$ECK_HOME/` template directory
- `gh` CLI authentication
- Network access to `evolvconsulting/evolv-coder-kit` on GitHub

### Activities

### Requirements

- `gh` CLI installed and authenticated
- Templates installed at `$ECK_HOME/`
- Network access to GitHub

### Verification

```bash
# Check gh authentication
gh auth status

# Check templates exist
ls $ECK_HOME/global-catalog.yaml

# Check upstream repo is reachable
gh repo view evolvconsulting/evolv-coder-kit --json name

# Check for existing open PRs from current user
gh pr list --repo evolvconsulting/evolv-coder-kit --author @me --state open
```

**If `gh` not authenticated:**

```bash
printf '%b\n' "${RED}[!]${RESET} GitHub CLI is not authenticated"
printf '%b\n' "    ${DIM}Run: gh auth login${RESET}"
```

**If templates not installed:**

```bash
printf '%b\n' "${RED}[!]${RESET} Templates not found at $ECK_HOME/"
printf '%b\n' "    ${DIM}Run: npx @evolvconsulting/evolv-coder-kit --global${RESET}"
```

**If upstream unreachable:**

```bash
printf '%b\n' "${RED}[!]${RESET} Cannot reach evolvconsulting/evolv-coder-kit"
printf '%b\n' "    ${DIM}Check network connection and GitHub access.${RESET}"
```

**If open PRs exist:**

```bash
printf '%b\n' "${YELLOW}[>]${RESET} {N} open PR(s) against upstream"
printf '%b\n' "    ${DIM}#{number}: {title} ({state})${RESET}"
printf '%b\n' "    ${DIM}Consider updating an existing PR instead.${RESET}"
```

### Outputs

- Confirmed prerequisites: gh CLI authenticated, templates found, upstream reachable; existing open PRs noted

### Exit Criteria

- All prerequisites passed; skill may proceed

---

## Stage 2: Determine Changes

### Inputs

- `$ECK_HOME/` local templates
- Cloned upstream `evolvconsulting/evolv-coder-kit` (cloned in this stage)
- `$ECK_HOME/audits/pull-candidates.md` (if exists)
- `$ECK_HOME/registry.yaml` (if exists)

### Activities

### Setup Working Directory

```bash
WORK_DIR="/tmp/evolv-coder-kit-upstream-$(date +%s)"
mkdir -p "$WORK_DIR"
```

### Clone Upstream

```bash
gh repo clone evolvconsulting/evolv-coder-kit "$WORK_DIR/upstream" -- --depth 1
```

### File-by-File Comparison

Compare local templates against upstream using SHA-256 checksums:

**Local source:** `$ECK_HOME/{path}`
**Upstream source:** `$WORK_DIR/upstream/scaffold/{path}`

### Exclusions

Skip the following from comparison (runtime/local-only files):

- `audits/` — local audit reports and registry
- `.update-check` — update checker state
- `*.tmp`, `*.bak` — temporary files
- `.DS_Store`, `Thumbs.db` — OS artifacts

### Checksum Comparison

For each file in `$ECK_HOME/` (excluding the above):

```bash
# Compute local checksum (CRLF-normalized)
tr -d '\r' < $ECK_HOME/{path} | shasum -a 256 | cut -c1-12

# Compute upstream checksum (CRLF-normalized)
tr -d '\r' < $WORK_DIR/upstream/scaffold/{path} | shasum -a 256 | cut -c1-12
```

### Categorize Changes

Group changed files by catalog categories:

| Category   | Path Patterns                                                           |
| ---------- | ----------------------------------------------------------------------- |
| root_files | `CLAUDE.md.project.template`, `*.md` at root                            |
| config     | `settings.json.template`, `project-constants.md`, `global-catalog.yaml` |
| agents     | `.claude/agents/*.md`                                                   |
| skills     | `.claude/skills/**/*.md`                                                |
| hooks      | `.claude/hooks/*`                                                       |
| primitives | `.claude/primitives/**/*.md`                                            |
| context    | `.claude/context/*.md`                                                  |

### Source Attribution

Cross-reference with tracking files if they exist:

1. Read `$ECK_HOME/audits/pull-candidates.md` — identify which project each change came from
2. Read `$ECK_HOME/registry.yaml` — get project metadata for attribution

**If tracking files don't exist:** Skip attribution. Changes will be listed without source project info.

### No Changes

**If no differences found:**

```bash
printf '%b\n' "${DIM}[-]${RESET} No differences found — local matches upstream"
printf '%b\n' "    ${DIM}Nothing to submit.${RESET}"
```

Exit cleanly.

### Outputs

- Categorized list of changed files (by category: new, modified) with source attribution; working directory (`$WORK_DIR`) created

### Exit Criteria

- Changed files identified and categorized; skill exits cleanly if no differences found

---

## Stage 3: Present Changes & User Selection

### Inputs

- Categorized change list from Stage 2

### Activities

### Summary Table

Display the changes detected as a summary box.

```bash
echo ""
printf '%b\n' "${ORANGE}${BOLD}Changes Detected${RESET}"
echo ""
printf '%b\n' "${DIM}Category         New   Modified   Total${RESET}"
printf '%b\n' "root_files       {N}    {N}         {N}"
printf '%b\n' "config           {N}    {N}         {N}"
printf '%b\n' "agents           {N}    {N}         {N}"
printf '%b\n' "skills           {N}    {N}         {N}"
printf '%b\n' "hooks            {N}    {N}         {N}"
printf '%b\n' "primitives       {N}    {N}         {N}"
printf '%b\n' "context          {N}    {N}         {N}"
printf '%b\n' "${BOLD}Total            {N}    {N}         {N}${RESET}"
echo ""
```

### Per-Category Selection

For each category with changes, display with status symbols and prompt:

```bash
echo ""
printf '%b\n' "${ORANGE}${BOLD}Category: {CATEGORY_NAME} ({N} files)${RESET}"
echo ""
printf '%b\n' "  ${DIM}#${RESET}  File                          Type      Source"
printf '%b\n' "  ${DIM}──${RESET} ───────────────────────────── ──────── ──────────────"
printf '%b\n' "  1  {path}                         ${GREEN}new${RESET}      {project}"
printf '%b\n' "  2  {path}                         ${YELLOW}modified${RESET} {project}"
```

Prompt: `Include which files? (all / none / 1,3,5 / review N)`

- **all** — Include all files in this category
- **none** — Skip this category entirely
- **1,3,5** — Cherry-pick specific files by number
- **review N** — Show diff for file N, then re-prompt

**STOP:** Do not proceed to Stage 4 until all categories have been presented and user has responded.

**If user selects nothing across all categories:**

```bash
printf '%b\n' "${DIM}[-]${RESET} No files selected for submission. Exiting."
```

Exit cleanly.

### Outputs

- User-approved file list for submission

### Exit Criteria

- User has responded to all categories; at least one file selected or skill exits cleanly

---

## Stage 4: De-Projectification Verification

### Inputs

- Approved file list from Stage 3
- `$ECK_HOME/registry.yaml` (for known placeholder patterns, if exists)

### Activities

Before submitting, verify that approved files don't contain leaked project-specific values.

### Scan for Leaks

For each approved file, check for:

| Pattern                     | Example                                  | Risk     |
| --------------------------- | ---------------------------------------- | -------- |
| Hardcoded URLs              | `https://specific-company.atlassian.net` | High     |
| Specific port numbers       | `:3001`, `:8080` (unless standard)       | Medium   |
| Usernames/emails            | `john@example.com`                       | High     |
| API keys/tokens             | `sk-...`, `ghp_...`, `xoxb-...`          | Critical |
| Absolute local paths        | `/Users/specific-user/...`               | High     |
| Internal hostnames          | `internal.corp.company.com`              | High     |
| Database connection strings | `postgresql://user:pass@host`            | Critical |

### Cross-Reference Placeholders

If `$ECK_HOME/registry.yaml` exists, read known placeholder patterns from registered projects to identify values that should be `<PLACEHOLDER>` tokens.

### Report Findings

**If leaks found:**

```bash
echo ""
printf '%b\n' "${ORANGE}${BOLD}De-Projectification Check${RESET}"
echo ""
printf '%b\n' "${YELLOW}[>]${RESET} Potential project-specific values in {N} files"
echo ""
printf '%b\n' "${RED}[!]${RESET} {path} (line {N})"
printf '%b\n' "    ${DIM}Value: {value}${RESET}"
printf '%b\n' "    ${DIM}Suggested: Replace with {PLACEHOLDER}${RESET}"
```

Prompt per file:

```bash
printf '%b\n' "    ${DIM}1. Auto-fix with {PLACEHOLDER} tokens${RESET}"
printf '%b\n' "    ${DIM}2. Remove from submission${RESET}"
printf '%b\n' "    ${DIM}3. Proceed with warning${RESET}"
```

**If no leaks found:**

```bash
printf '%b\n' "${GREEN}[x]${RESET} De-projectification check passed"
```

### Outputs

- Approved files verified clean (or auto-fixed / excluded per user decision); de-projectification status recorded

### Exit Criteria

- All approved files either passed the check, were auto-fixed, or were removed from submission

---

## Stage 5: Fork Management

### Inputs

- GitHub username (from `gh` CLI)
- `$WORK_DIR` from Stage 2

### Activities

### Create or Use Existing Fork

**MUST** use a fork-based workflow. Do NOT push directly to the upstream repository.

```bash
# Get current GitHub username
GH_USER=$(gh api user --jq '.login')

# Fork (idempotent — no-op if fork already exists)
gh repo fork evolvconsulting/evolv-coder-kit --clone=false

# Clone the fork
gh repo clone "$GH_USER/evolv-coder-kit" "$WORK_DIR/fork" -- --depth 1
```

### Sync Fork with Upstream

```bash
# Sync fork's main branch with upstream
gh repo sync "$GH_USER/evolv-coder-kit" --branch main

# Pull latest into local clone
cd "$WORK_DIR/fork"
git pull origin main
```

### Outputs

- Fork created (or confirmed existing); fork cloned to `$WORK_DIR/fork` and synced with upstream main

### Exit Criteria

- Fork exists and local clone is up-to-date with upstream main

---

## Stage 6: Branch, Commit, Push

### Inputs

- Fork clone at `$WORK_DIR/fork` from Stage 5
- Approved, de-projectified files from Stage 4
- Source attributions from Stage 2

### Activities

### Create Branch

```bash
cd "$WORK_DIR/fork"

# Generate branch name
# {short-description} is derived from the dominant category or "mixed-improvements"
BRANCH="submit/$(date +%Y-%m-%d)/{short-description}"

git checkout -b "$BRANCH"
```

### Copy Approved Files

For each approved file:

```bash
# Copy from local install to fork's templates directory
cp $ECK_HOME/{path} $WORK_DIR/fork/scaffold/{path}
```

Create any necessary parent directories with `mkdir -p` before copying.

### Update Catalog Checksums

Read `$WORK_DIR/fork/scaffold/global/global-catalog.yaml` and update checksums for changed files:

```bash
# Recompute checksum for each changed file (CRLF-normalized)
tr -d '\r' < $WORK_DIR/fork/scaffold/{path} | shasum -a 256 | cut -c1-12
```

Update the corresponding `checksum` field in the catalog.

### Bump Component Versions

For each changed component in the catalog:

- **PATCH bump** — fixes to existing components (e.g., `1.0.0` → `1.0.1`)
- **MINOR bump** — new components or significant improvements (e.g., `1.0.0` → `1.1.0`)

### Commit

```bash
cd "$WORK_DIR/fork"
git add -A

# Structured commit message
git commit -m "sync: template improvements from projects

Changes:
$(for file in {approved_files}; do echo "  - $file"; done)

Source attribution:
$(for attr in {attributions}; do echo "  - $attr"; done)

Submitted by /eck:submit-to-repo"
```

### Push

```bash
git push origin "$BRANCH"
```

### Outputs

- Branch created, files committed, and branch pushed to fork

### Exit Criteria

- Branch pushed to fork without errors

---

## Stage 7: Create PR

### Inputs

- Branch name from Stage 6
- Approved file metadata (categories, descriptions, de-projectification status)
- Source attributions from Stage 2

### Activities

#### Create Pull Request

**MUST** create the pull request against upstream. Do NOT skip PR creation after pushing the branch.

```bash
gh pr create \
  --repo evolvconsulting/evolv-coder-kit \
  --head "$GH_USER:$BRANCH" \
  --base main \
  --title "sync: template improvements ({N} files, {categories})" \
  --body "$(cat <<'PRBODY'
## Summary

Template improvements submitted from global install via `/eck:submit-to-repo`.

### Changes by Category

| Category | New | Modified | Total |
|----------|-----|----------|-------|
{category_table}

### Files Changed

{file_list_with_descriptions}

### Source Attribution

{attribution_table_or_note}

### De-Projectification Status

{status — passed / N items auto-fixed / N items with warnings}

### Testing Checklist

- [ ] All changed files contain only template placeholders (no project-specific values)
- [ ] Catalog checksums match file contents
- [ ] Component versions bumped appropriately
- [ ] No breaking changes to existing template structure
- [ ] Templates deploy correctly with `/eck:new-project`

---
*Submitted by `/eck:submit-to-repo`*
PRBODY
)"
```

Capture the PR URL from the output.

### Outputs

- Pull request created against `evolvconsulting/evolv-coder-kit` main; PR URL captured

### Exit Criteria

- PR created successfully; PR URL available

---

## Stage 8: Update Local Tracking

### Inputs

- PR URL and number from Stage 7
- Submitted file list and source attributions
- `$ECK_HOME/audits/pull-candidates.md` (if exists)
- `$ECK_HOME/registry.yaml` (if exists)

### Activities

Update local tracking files to record the submission. **If any tracking file doesn't exist, skip it with a note.**

### Update Pull Candidates

If `$ECK_HOME/audits/pull-candidates.md` exists:

- Change status of submitted items: `PULLED` → `SUBMITTED`
- Add PR URL to each submitted item's entry

### Update Registry

**Reference:** `ops:registry-update` primitive for the canonical write procedure.

If registry does not exist, log warning and skip this step.

If the project entry is not found in the registry, log warning and skip registry update.

If `$ECK_HOME/registry.yaml` exists:

- Append `sync_history` entry for each source project:

```yaml
- date: "{DATE}"
  action: "upstream-submit"
  performed_by: "/eck:submit-to-repo"
  summary: "Submitted {N} files to upstream PR #{N} ({PR_URL})"
```

- Set `last_modified_at` to current ISO-8601 date.
- Recompute `project_summary` per the `ops:registry-update` primitive.
- Use atomic write: write to `registry.yaml.tmp`, then rename to `registry.yaml`.

### Create/Update Upstream Submissions Log

Create or append to `$ECK_HOME/audits/upstream-submissions.md`:

```markdown
## Submission: {DATE}

- **PR:** {PR_URL}
- **Branch:** {BRANCH}
- **Files:** {N}
- **Categories:** {list}
- **Source projects:** {list or "unknown"}
- **Status:** Open

### Files Submitted

| File   | Type           | Source                 |
| ------ | -------------- | ---------------------- |
| {path} | {new/modified} | {project or "unknown"} |
```

### Outputs

- Pull candidates status updated to `SUBMITTED`; registry sync history updated; upstream submissions log created/updated

### Exit Criteria

- All applicable tracking files updated (or skipped with note if missing)

---

## Stage 9: Cleanup & Summary

### Inputs

- PR URL and file counts from Stage 7
- Tracking update status from Stage 8
- `$WORK_DIR` path from Stage 2

### Activities

### Cleanup

```bash
rm -rf "$WORK_DIR"
```

### Summary

Display the final summary as a branded summary box with status symbols.

```bash
echo ""
printf '%b\n' "${ORANGE}${BOLD}Submit To Repo Complete${RESET}"
echo ""
printf '%b\n' "PR: {PR_URL}"
printf '%b\n' "Files: {N} total"
printf '%b\n' "De-Project: {status}"
echo ""
```

**Files by category:**

```bash
printf '%b\n' "${GREEN}[x]${RESET} {category} — {N} files submitted"
```

**Source attribution:**

```bash
printf '%b\n' "${DIM}[-]${RESET} {path} — from {project or unknown}"
```

**Local tracking updates:**

```bash
printf '%b\n' "${GREEN}[x]${RESET} Pull candidates — {updated/skipped}"
printf '%b\n' "${GREEN}[x]${RESET} Registry — {updated/skipped}"
printf '%b\n' "${GREEN}[x]${RESET} Submissions log — {updated/created/skipped}"
```

**Next steps:**

```bash
printf '%b\n' "${CYAN}[*]${RESET} Monitor PR: gh pr view {PR_NUMBER} --repo evolvconsulting/evolv-coder-kit"
printf '%b\n' "${CYAN}[*]${RESET} After merge: npx @evolvconsulting/evolv-coder-kit --global --overwrite"
printf '%b\n' "${CYAN}[*]${RESET} Propagate: /eck:pull-from-global-catalog on each project"
```

### Outputs

- Working directory cleaned up; completion summary displayed with PR URL and next steps

### Exit Criteria

- Temp directory removed; summary displayed; statusline reset; skill complete

---

## Safety Rules

1. **Never auto-submit** — user approves every file before PR creation
2. **De-projectification mandatory** — scan for leaked values before submission
3. **Fork-based workflow** — never push directly to upstream
4. **Non-destructive locally** — only updates tracking files in `audits/`
5. **Idempotent fork creation** — safe to re-run without duplicate forks
6. **Clean temp dirs** — working directory removed after completion

---

## Error Handling

### gh CLI Not Installed

```bash
printf '%b\n' "${RED}[!]${RESET} GitHub CLI (gh) is not installed"
printf '%b\n' "    ${DIM}Install from https://cli.github.com/${RESET}"
```

### Fork Creation Failed

```bash
printf '%b\n' "${RED}[!]${RESET} Could not fork evolvconsulting/evolv-coder-kit"
printf '%b\n' "    ${DIM}Check GitHub permissions and network connection.${RESET}"
```

### Push Failed

```bash
printf '%b\n' "${RED}[!]${RESET} Could not push branch {BRANCH} to fork"
printf '%b\n' "    ${DIM}May be due to branch protection or network issues.${RESET}"
printf '%b\n' "    ${DIM}Changes preserved in: $WORK_DIR/fork/${RESET}"
```

### PR Creation Failed

```bash
printf '%b\n' "${RED}[!]${RESET} Could not create pull request"
printf '%b\n' "    ${DIM}Branch pushed to: {GH_USER}/evolv-coder-kit:{BRANCH}${RESET}"
printf '%b\n' "    ${DIM}Create PR manually at:${RESET}"
printf '%b\n' "    ${DIM}https://github.com/evolvconsulting/evolv-coder-kit/compare/main...{GH_USER}:{BRANCH}${RESET}"
```

---

## Related Documents

- [Catalog]($ECK_HOME/global-catalog.yaml) - Canonical source of truth
- [/eck:push-to-user-catalog skill](../push-to-user-catalog/SKILL.md) - Push improvements from projects to catalog (prerequisite)
- [/eck:audit-unmanaged-project skill](../audit-unmanaged-project/SKILL.md) - Read-only audit
- [/eck:pull-from-global-catalog skill](../pull-from-global-catalog/SKILL.md) - Pull updates into projects
- [/eck:project-status skill](../project-status/SKILL.md) - Project health dashboard
