mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-21 23:33:07 +00:00
chore: final dev commit
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -90,6 +90,8 @@ pnpm-lock.yaml
|
|||||||
yarn.lock
|
yarn.lock
|
||||||
|
|
||||||
# Fork-specific workflow files (should never be committed)
|
# Fork-specific workflow files (should never be committed)
|
||||||
|
DEVELOPMENT_WORKFLOW.md
|
||||||
|
check-sync.sh
|
||||||
# API key files
|
# API key files
|
||||||
data/.api-key
|
data/.api-key
|
||||||
data/credentials.json
|
data/credentials.json
|
||||||
|
|||||||
@@ -1,253 +0,0 @@
|
|||||||
# Development Workflow
|
|
||||||
|
|
||||||
This document defines the standard workflow for keeping a branch in sync with the upstream
|
|
||||||
release candidate (RC) and for shipping feature work. It is paired with `check-sync.sh`.
|
|
||||||
|
|
||||||
## Quick Decision Rule
|
|
||||||
|
|
||||||
1. Ask the user to select a workflow:
|
|
||||||
- **Sync Workflow** → you are maintaining the current RC branch with fixes/improvements
|
|
||||||
and will push the same fixes to both origin and upstream RC when you have local
|
|
||||||
commits to publish.
|
|
||||||
- **PR Workflow** → you are starting new feature work on a new branch; upstream updates
|
|
||||||
happen via PR only.
|
|
||||||
2. After the user selects, run:
|
|
||||||
```bash
|
|
||||||
./check-sync.sh
|
|
||||||
```
|
|
||||||
3. Use the status output to confirm alignment. If it reports **diverged**, default to
|
|
||||||
merging `upstream/<TARGET_RC>` into the current branch and preserving local commits.
|
|
||||||
For Sync Workflow, when the working tree is clean and you are behind upstream RC,
|
|
||||||
proceed with the fetch + merge without asking for additional confirmation.
|
|
||||||
|
|
||||||
## Target RC Resolution
|
|
||||||
|
|
||||||
The target RC is resolved dynamically so the workflow stays current as the RC changes.
|
|
||||||
|
|
||||||
Resolution order:
|
|
||||||
|
|
||||||
1. Latest `upstream/v*rc` branch (auto-detected)
|
|
||||||
2. `upstream/HEAD` (fallback)
|
|
||||||
3. If neither is available, you must pass `--rc <branch>`
|
|
||||||
|
|
||||||
Override for a single run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./check-sync.sh --rc <rc-branch>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pre-Flight Checklist
|
|
||||||
|
|
||||||
1. Confirm a clean working tree:
|
|
||||||
```bash
|
|
||||||
git status
|
|
||||||
```
|
|
||||||
2. Confirm the current branch:
|
|
||||||
```bash
|
|
||||||
git branch --show-current
|
|
||||||
```
|
|
||||||
3. Ensure remotes exist (origin + upstream):
|
|
||||||
```bash
|
|
||||||
git remote -v
|
|
||||||
```
|
|
||||||
|
|
||||||
## Sync Workflow (Upstream Sync)
|
|
||||||
|
|
||||||
Use this flow when you are updating the current branch with fixes or improvements and
|
|
||||||
intend to keep origin and upstream RC in lockstep.
|
|
||||||
|
|
||||||
1. **Check sync status**
|
|
||||||
```bash
|
|
||||||
./check-sync.sh
|
|
||||||
```
|
|
||||||
2. **Update from upstream RC before editing (no pulls)**
|
|
||||||
- **Behind upstream RC** → fetch and merge RC into your branch:
|
|
||||||
```bash
|
|
||||||
git fetch upstream
|
|
||||||
git merge upstream/<TARGET_RC> --no-edit
|
|
||||||
```
|
|
||||||
When the working tree is clean and the user selected Sync Workflow, proceed without
|
|
||||||
an extra confirmation prompt.
|
|
||||||
- **Diverged** → stop and resolve manually.
|
|
||||||
3. **Resolve conflicts if needed**
|
|
||||||
- Handle conflicts intelligently: preserve upstream behavior and your local intent.
|
|
||||||
4. **Make changes and commit (if you are delivering fixes)**
|
|
||||||
```bash
|
|
||||||
git add -A
|
|
||||||
git commit -m "type: description"
|
|
||||||
```
|
|
||||||
5. **Build to verify**
|
|
||||||
```bash
|
|
||||||
npm run build:packages
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
6. **Push after a successful merge to keep remotes aligned**
|
|
||||||
- If you only merged upstream RC changes, push **origin only** to sync your fork:
|
|
||||||
```bash
|
|
||||||
git push origin <branch>
|
|
||||||
```
|
|
||||||
- If you have local fixes to publish, push **origin + upstream**:
|
|
||||||
```bash
|
|
||||||
git push origin <branch>
|
|
||||||
git push upstream <branch>:<TARGET_RC>
|
|
||||||
```
|
|
||||||
- Always ask the user which push to perform.
|
|
||||||
- Origin (origin-only sync):
|
|
||||||
```bash
|
|
||||||
git push origin <branch>
|
|
||||||
```
|
|
||||||
- Upstream RC (publish the same fixes when you have local commits):
|
|
||||||
```bash
|
|
||||||
git push upstream <branch>:<TARGET_RC>
|
|
||||||
```
|
|
||||||
7. **Re-check sync**
|
|
||||||
```bash
|
|
||||||
./check-sync.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## PR Workflow (Feature Work)
|
|
||||||
|
|
||||||
Use this flow only for new feature work on a new branch. Do not push to upstream RC.
|
|
||||||
|
|
||||||
1. **Create or switch to a feature branch**
|
|
||||||
```bash
|
|
||||||
git checkout -b <branch>
|
|
||||||
```
|
|
||||||
2. **Make changes and commit**
|
|
||||||
```bash
|
|
||||||
git add -A
|
|
||||||
git commit -m "type: description"
|
|
||||||
```
|
|
||||||
3. **Merge upstream RC before shipping**
|
|
||||||
```bash
|
|
||||||
git merge upstream/<TARGET_RC> --no-edit
|
|
||||||
```
|
|
||||||
4. **Build and/or test**
|
|
||||||
```bash
|
|
||||||
npm run build:packages
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
5. **Push to origin**
|
|
||||||
```bash
|
|
||||||
git push -u origin <branch>
|
|
||||||
```
|
|
||||||
6. **Create or update the PR**
|
|
||||||
- Use `gh pr create` or the GitHub UI.
|
|
||||||
7. **Review and follow-up**
|
|
||||||
|
|
||||||
- Apply feedback, commit changes, and push again.
|
|
||||||
- Re-run `./check-sync.sh` if additional upstream sync is needed.
|
|
||||||
|
|
||||||
## Conflict Resolution Checklist
|
|
||||||
|
|
||||||
1. Identify which changes are from upstream vs. local.
|
|
||||||
2. Preserve both behaviors where possible; avoid dropping either side.
|
|
||||||
3. Prefer minimal, safe integrations over refactors.
|
|
||||||
4. Re-run build commands after resolving conflicts.
|
|
||||||
5. Re-run `./check-sync.sh` to confirm status.
|
|
||||||
|
|
||||||
## Build/Test Matrix
|
|
||||||
|
|
||||||
- **Sync Workflow**: `npm run build:packages` and `npm run build`.
|
|
||||||
- **PR Workflow**: `npm run build:packages` and `npm run build` (plus relevant tests).
|
|
||||||
|
|
||||||
## Post-Sync Verification
|
|
||||||
|
|
||||||
1. `git status` should be clean.
|
|
||||||
2. `./check-sync.sh` should show expected alignment.
|
|
||||||
3. Verify recent commits with:
|
|
||||||
```bash
|
|
||||||
git log --oneline -5
|
|
||||||
```
|
|
||||||
|
|
||||||
## check-sync.sh Usage
|
|
||||||
|
|
||||||
- Uses dynamic Target RC resolution (see above).
|
|
||||||
- Override target RC:
|
|
||||||
```bash
|
|
||||||
./check-sync.sh --rc <rc-branch>
|
|
||||||
```
|
|
||||||
- Optional preview limit:
|
|
||||||
```bash
|
|
||||||
./check-sync.sh --preview 10
|
|
||||||
```
|
|
||||||
- The script prints sync status for both origin and upstream and previews recent commits
|
|
||||||
when you are behind.
|
|
||||||
|
|
||||||
## Stop Conditions
|
|
||||||
|
|
||||||
Stop and ask for guidance if any of the following are true:
|
|
||||||
|
|
||||||
- The working tree is dirty and you are about to merge or push.
|
|
||||||
- `./check-sync.sh` reports **diverged** during PR Workflow, or a merge cannot be completed.
|
|
||||||
- The script cannot resolve a target RC and requests `--rc`.
|
|
||||||
- A build fails after sync or conflict resolution.
|
|
||||||
|
|
||||||
## AI Agent Guardrails
|
|
||||||
|
|
||||||
- Always run `./check-sync.sh` before merges or pushes.
|
|
||||||
- Always ask for explicit user approval before any push command.
|
|
||||||
- Do not ask for additional confirmation before a Sync Workflow fetch + merge when the
|
|
||||||
working tree is clean and the user has already selected the Sync Workflow.
|
|
||||||
- Choose Sync vs PR workflow based on intent (RC maintenance vs new feature work), not
|
|
||||||
on the script's workflow hint.
|
|
||||||
- Only use force push when the user explicitly requests a history rewrite.
|
|
||||||
- Ask for explicit approval before dependency installs, branch deletion, or destructive operations.
|
|
||||||
- When resolving merge conflicts, preserve both upstream changes and local intent where possible.
|
|
||||||
- Do not create or switch to new branches unless the user explicitly requests it.
|
|
||||||
|
|
||||||
## AI Agent Decision Guidance
|
|
||||||
|
|
||||||
Agents should provide concrete, task-specific suggestions instead of repeatedly asking
|
|
||||||
open-ended questions. Use the user's stated goal and the `./check-sync.sh` status to
|
|
||||||
propose a default path plus one or two alternatives, and only ask for confirmation when
|
|
||||||
an action requires explicit approval.
|
|
||||||
|
|
||||||
Default behavior:
|
|
||||||
|
|
||||||
- If the intent is RC maintenance, recommend the Sync Workflow and proceed with
|
|
||||||
safe preparation steps (status checks, previews). If the branch is behind upstream RC,
|
|
||||||
fetch and merge without additional confirmation when the working tree is clean, then
|
|
||||||
push to origin to keep the fork aligned. Push upstream only when there are local fixes
|
|
||||||
to publish.
|
|
||||||
- If the intent is new feature work, recommend the PR Workflow and proceed with safe
|
|
||||||
preparation steps (status checks, identifying scope). Ask for approval before merges,
|
|
||||||
pushes, or dependency installs.
|
|
||||||
- If `./check-sync.sh` reports **diverged** during Sync Workflow, merge
|
|
||||||
`upstream/<TARGET_RC>` into the current branch and preserve local commits.
|
|
||||||
- If `./check-sync.sh` reports **diverged** during PR Workflow, stop and ask for guidance
|
|
||||||
with a short explanation of the divergence and the minimal options to resolve it.
|
|
||||||
If the user's intent is RC maintenance, prefer the Sync Workflow regardless of the
|
|
||||||
script hint. When the intent is new feature work, use the PR Workflow and avoid upstream
|
|
||||||
RC pushes.
|
|
||||||
|
|
||||||
Suggestion format (keep it short):
|
|
||||||
|
|
||||||
- **Recommended**: one sentence with the default path and why it fits the task.
|
|
||||||
- **Alternatives**: one or two options with the tradeoff or prerequisite.
|
|
||||||
- **Approval points**: mention any upcoming actions that need explicit approval (exclude sync
|
|
||||||
workflow pushes and merges).
|
|
||||||
|
|
||||||
## Failure Modes and How to Avoid Them
|
|
||||||
|
|
||||||
Sync Workflow:
|
|
||||||
|
|
||||||
- Wrong RC target: verify the auto-detected RC in `./check-sync.sh` output before merging.
|
|
||||||
- Diverged from upstream RC: stop and resolve manually before any merge or push.
|
|
||||||
- Dirty working tree: commit or stash before syncing to avoid accidental merges.
|
|
||||||
- Missing remotes: ensure both `origin` and `upstream` are configured before syncing.
|
|
||||||
- Build breaks after sync: run `npm run build:packages` and `npm run build` before pushing.
|
|
||||||
|
|
||||||
PR Workflow:
|
|
||||||
|
|
||||||
- Branch not synced to current RC: re-run `./check-sync.sh` and merge RC before shipping.
|
|
||||||
- Pushing the wrong branch: confirm `git branch --show-current` before pushing.
|
|
||||||
- Unreviewed changes: always commit and push to origin before opening or updating a PR.
|
|
||||||
- Skipped tests/builds: run the build commands before declaring the PR ready.
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- Avoid merging with uncommitted changes; commit or stash first.
|
|
||||||
- Prefer merge over rebase for PR branches; rebases rewrite history and often require a force push,
|
|
||||||
which should only be done with an explicit user request.
|
|
||||||
- Use clear, conventional commit messages and split unrelated changes into separate commits.
|
|
||||||
215
check-sync.sh
215
check-sync.sh
@@ -1,215 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
DEFAULT_RC_PATTERN="v*rc"
|
|
||||||
DEFAULT_PREVIEW_COUNT=5
|
|
||||||
|
|
||||||
PREVIEW_COUNT="${PREVIEW_COUNT:-$DEFAULT_PREVIEW_COUNT}"
|
|
||||||
CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
|
||||||
|
|
||||||
ORIGIN_REF="origin/${CURRENT_BRANCH}"
|
|
||||||
TARGET_RC_SOURCE="auto"
|
|
||||||
|
|
||||||
print_header() {
|
|
||||||
echo "=== Sync Status Check ==="
|
|
||||||
echo
|
|
||||||
printf "Target RC: %s (%s)\n" "$TARGET_RC" "$TARGET_RC_SOURCE"
|
|
||||||
echo
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_git_repo() {
|
|
||||||
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
||||||
echo "Not inside a git repository."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_remote() {
|
|
||||||
local remote="$1"
|
|
||||||
if ! git remote get-url "$remote" >/dev/null 2>&1; then
|
|
||||||
echo "Remote '$remote' is not configured."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch_remote() {
|
|
||||||
local remote="$1"
|
|
||||||
git fetch --quiet "$remote"
|
|
||||||
}
|
|
||||||
|
|
||||||
warn_if_dirty() {
|
|
||||||
if [[ -n "$(git status --porcelain)" ]]; then
|
|
||||||
echo "Warning: working tree has uncommitted changes."
|
|
||||||
echo
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve_target_rc() {
|
|
||||||
if [[ -n "${TARGET_RC:-}" ]]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
local rc_candidates
|
|
||||||
rc_candidates="$(git for-each-ref --format='%(refname:short)' "refs/remotes/upstream/${DEFAULT_RC_PATTERN}" || true)"
|
|
||||||
if [[ -n "$rc_candidates" ]]; then
|
|
||||||
TARGET_RC="$(printf "%s\n" "$rc_candidates" | sed 's|^upstream/||' | sort -V | tail -n 1)"
|
|
||||||
TARGET_RC_SOURCE="auto:latest"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
local upstream_head
|
|
||||||
upstream_head="$(git symbolic-ref --quiet --short refs/remotes/upstream/HEAD 2>/dev/null || true)"
|
|
||||||
if [[ -n "$upstream_head" ]]; then
|
|
||||||
TARGET_RC="${upstream_head#upstream/}"
|
|
||||||
TARGET_RC_SOURCE="auto:upstream-head"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Unable to resolve target RC automatically. Use --rc <branch>."
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
ref_exists() {
|
|
||||||
local ref="$1"
|
|
||||||
git show-ref --verify --quiet "refs/remotes/${ref}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_status_line() {
|
|
||||||
local label="$1"
|
|
||||||
local behind="$2"
|
|
||||||
local ahead="$3"
|
|
||||||
|
|
||||||
if [[ "$behind" -eq 0 && "$ahead" -eq 0 ]]; then
|
|
||||||
printf "✅ %s: in sync (behind %s, ahead %s)\n" "$label" "$behind" "$ahead"
|
|
||||||
elif [[ "$behind" -eq 0 ]]; then
|
|
||||||
printf "⬆️ %s: ahead %s (behind %s)\n" "$label" "$ahead" "$behind"
|
|
||||||
elif [[ "$ahead" -eq 0 ]]; then
|
|
||||||
printf "⬇️ %s: behind %s (ahead %s)\n" "$label" "$behind" "$ahead"
|
|
||||||
else
|
|
||||||
printf "⚠️ %s: %s behind, %s ahead (diverged)\n" "$label" "$behind" "$ahead"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
print_preview() {
|
|
||||||
local title="$1"
|
|
||||||
local range="$2"
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "$title"
|
|
||||||
git log --oneline -n "$PREVIEW_COUNT" "$range"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_branch_context() {
|
|
||||||
echo "Branch: $CURRENT_BRANCH"
|
|
||||||
echo "Upstream RC: $UPSTREAM_REF"
|
|
||||||
echo "Upstream push: enabled for sync workflow"
|
|
||||||
echo
|
|
||||||
}
|
|
||||||
|
|
||||||
print_upstream_summary() {
|
|
||||||
local behind="$1"
|
|
||||||
local ahead="$2"
|
|
||||||
|
|
||||||
if [[ "$behind" -eq 0 && "$ahead" -eq 0 ]]; then
|
|
||||||
echo "Branch vs upstream RC: in sync (behind $behind, ahead $ahead)"
|
|
||||||
else
|
|
||||||
echo "Branch vs upstream RC: behind $behind, ahead $ahead"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
print_workflow_hint() {
|
|
||||||
local behind="$1"
|
|
||||||
local ahead="$2"
|
|
||||||
|
|
||||||
if [[ "$behind" -eq 0 && "$ahead" -eq 0 ]]; then
|
|
||||||
echo "Workflow: sync"
|
|
||||||
elif [[ "$behind" -gt 0 && "$ahead" -eq 0 ]]; then
|
|
||||||
echo "Workflow: sync (merge upstream RC)"
|
|
||||||
elif [[ "$ahead" -gt 0 && "$behind" -eq 0 ]]; then
|
|
||||||
echo "Workflow: pr (local work not in upstream)"
|
|
||||||
else
|
|
||||||
echo "Workflow: diverged (resolve manually)"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
print_usage() {
|
|
||||||
echo "Usage: ./check-sync.sh [--rc <branch>] [--preview <count>]"
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_args() {
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--rc)
|
|
||||||
shift
|
|
||||||
if [[ -z "${1-}" ]]; then
|
|
||||||
echo "Missing value for --rc"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
TARGET_RC="$1"
|
|
||||||
TARGET_RC_SOURCE="flag"
|
|
||||||
;;
|
|
||||||
--preview)
|
|
||||||
shift
|
|
||||||
if [[ -z "${1-}" ]]; then
|
|
||||||
echo "Missing value for --preview"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if ! [[ "$1" =~ ^[0-9]+$ ]]; then
|
|
||||||
echo "Invalid preview count: $1"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
PREVIEW_COUNT="$1"
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
print_usage
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown argument: $1"
|
|
||||||
print_usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_git_repo
|
|
||||||
ensure_remote origin
|
|
||||||
ensure_remote upstream
|
|
||||||
parse_args "$@"
|
|
||||||
|
|
||||||
fetch_remote origin
|
|
||||||
fetch_remote upstream
|
|
||||||
resolve_target_rc
|
|
||||||
|
|
||||||
UPSTREAM_REF="upstream/${TARGET_RC}"
|
|
||||||
|
|
||||||
print_header
|
|
||||||
warn_if_dirty
|
|
||||||
print_branch_context
|
|
||||||
|
|
||||||
if ! ref_exists "$ORIGIN_REF"; then
|
|
||||||
echo "Origin branch '$ORIGIN_REF' does not exist."
|
|
||||||
else
|
|
||||||
read -r origin_behind origin_ahead < <(git rev-list --left-right --count "$ORIGIN_REF...HEAD")
|
|
||||||
print_status_line "Origin" "$origin_behind" "$origin_ahead"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! ref_exists "$UPSTREAM_REF"; then
|
|
||||||
echo "Upstream ref '$UPSTREAM_REF' does not exist."
|
|
||||||
else
|
|
||||||
read -r upstream_behind upstream_ahead < <(git rev-list --left-right --count "$UPSTREAM_REF...HEAD")
|
|
||||||
print_status_line "Upstream" "$upstream_behind" "$upstream_ahead"
|
|
||||||
echo
|
|
||||||
print_upstream_summary "$upstream_behind" "$upstream_ahead"
|
|
||||||
print_workflow_hint "$upstream_behind" "$upstream_ahead"
|
|
||||||
|
|
||||||
if [[ "$upstream_behind" -gt 0 ]]; then
|
|
||||||
print_preview "Recent upstream commits:" "HEAD..$UPSTREAM_REF"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$upstream_ahead" -gt 0 ]]; then
|
|
||||||
print_preview "Commits on this branch not in upstream:" "$UPSTREAM_REF..HEAD"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
Reference in New Issue
Block a user