diff --git a/autoprompt/07_worktree_only_edits.md b/autoprompt/07_worktree_only_edits.md deleted file mode 100644 index 1173f426..00000000 --- a/autoprompt/07_worktree_only_edits.md +++ /dev/null @@ -1,121 +0,0 @@ -# Enforce worktree-only edits on canonical checkouts - -> ⚠️ **Caveat — drafted from a stale repo state.** This prompt was drafted on 2026-04-27 during a forensic sweep that found local checkouts up to 101 commits behind origin. The trigger looked like a structural workflow flaw, but later analysis showed the drift was largely driven by **stale local checkouts being edited without `git pull` first**, not by missing tooling. Now that PyAutoPrompt is the canonical source-of-truth and `skills/install.sh` auto-discovers across both repos, some of the recommendations below may be over-engineered for the day-to-day case. Re-evaluate whether each measure is still warranted — the cheap habits (pull before edit, never rewrite history) buy most of the win. - -This is the structural fix. The other six prompts add visibility and discipline; -this one removes the *opportunity* for drift entirely. - -The PyAuto worktree infrastructure already exists: - -- `admin_jammy/software/worktree.sh` — create/remove task worktrees, conflict-check -- `/start_library`, `/start_workspace` — set up worktrees and branches per task -- `/ship_library`, `/ship_workspace` — finish a task, remove the worktree -- Worktree root: `~/Code/PyAutoLabs-wt//` - -But the rule "all editing happens in a worktree" was never enforced. On -2026-04-27, the workspace repos that drifted hadn't been edited in worktrees — -they'd been edited directly in the canonical checkout under -`~/Code/PyAutoLabs//`. That's how local commits accumulated independently -of origin. - -Once canonical checkouts become *read-only mirrors of origin/main*, the drift -mechanism is structurally impossible: any change has to go through a worktree, -which has to push to origin, which becomes the single source of truth by -construction. - -## What to ship - -Three layers, all required: - -### 1. Make the rule explicit - -Add to every PyAuto repo's `CLAUDE.md` (consolidate with the rules from -`03_history_rewrite_guard.md` and `04_source_of_truth_rule.md`): - -```markdown -## No editing in canonical checkouts - -The directory `~/Code/PyAutoLabs//` is a **read-only mirror** of -`origin/main`. Never edit files in it directly. All work happens in -**task worktrees** under `~/Code/PyAutoLabs-wt//`, set up by -`/start_library` or `/start_workspace`. - -If you find yourself wanting to `cd ~/Code/PyAutoLabs//` to "just fix -something quickly" — stop. That's how parallel-history drift starts. Use -`/start_dev` to draft a prompt for it instead, even for one-line fixes. - -The only operations allowed in the canonical checkout: `git fetch`, `git pull ---ff-only`, `git status`, `git log`. Everything else uses a worktree. -``` - -### 2. Soft enforcement — pre-edit hook - -A `~/.bashrc` function or a `direnv` config that prints a loud warning when -`vim` / `nano` / `cursor` / `code` / etc. opens a file under -`~/Code/PyAutoLabs//` (not `~/Code/PyAutoLabs-wt/`): - -```bash -__pyauto_canonical_warn() { - case "$PWD" in - "$HOME/Code/PyAutoLabs/admin_jammy"|"$HOME/Code/PyAutoLabs/admin_jammy/"*) return ;; - "$HOME/Code/PyAutoLabs/PyAutoPrompt"|"$HOME/Code/PyAutoLabs/PyAutoPrompt/"*) return ;; - "$HOME/Code/PyAutoLabs/"*) - printf "\033[31m⚠ Editing in canonical checkout. Did you mean to use a worktree?\033[0m\n" >&2 - printf " /start_dev → /start_library to create one.\n" >&2 - ;; - esac -} -``` - -(Wired into `cd` or as a function `vw` / `vw 'just open my editor'`.) Whitelist -admin_jammy and PyAutoPrompt because those *are* edited directly — the rule is -specifically about library and workspace canonical checkouts. - -### 3. Hard enforcement — `/sync` resets canonical checkouts unconditionally - -After `05_sync_slash_command.md` ships, the `/sync` skill should treat canonical -checkouts of library/workspace repos as fully resettable to `origin/main` with -no confirmation needed for ff-pulls and only "is everything duplicated?" checks -for divergent state. Worktrees are where work lives; canonicals are throwaway. - -The implication: any uncommitted local change in a canonical checkout should be -treated as junk by default. If you really need to keep it, move it to a -worktree first. - -## Acceptance - -- The CLAUDE.md rule lands in every library and workspace repo. -- The shell warning fires when opening a file in a canonical PyAuto repo, and - doesn't fire for admin_jammy / PyAutoPrompt. -- `/sync` no longer asks "what about your dirty file in PyAutoArray/scratch.py?" - — it just nukes it after a 2-second warning. -- A month after this lands, `pyauto-status` should show clean dirty:0 across - all canonicals. Any non-zero is a sign someone broke the rule. - -## Migration - -The current canonicals already have stray dirty files (`PyAutoArray/test_autoarray/profile_tst.py`, -`PyAutoGalaxy/scrap.py` etc.). Move each to either a real prompt + worktree -flow, or delete it as scratch. Don't carry them across. - -## Out of scope - -- Symlinks / read-only filesystems for canonical checkouts. Possible but invasive - (breaks `pip install -e`). Behavioural enforcement via warning + `/sync` reset - is enough. -- Renaming the canonical-vs-worktree convention. Keep the existing path layout. - -## Why this is the biggest single fix - -Prompts 01-06 catch drift after it happens or warn about modes that lead to -drift. This one removes the path that produced the 2026-04-27 mess: making -local commits in a canonical checkout that origin doesn't know about. - -If only one of these seven prompts ships, ship this one — the others become -nice-to-haves rather than load-bearing. - -## Files touched - -- CLAUDE.md across all library + workspace repos (one PR each, can batch) -- `~/.bashrc` (one-time, on this machine) -- `PyAutoPrompt/skills/sync/SKILL.md` (depends on `05_sync_slash_command.md`) diff --git a/autoprompt/README.md b/autoprompt/README.md index 3c0b045f..9f51e452 100644 --- a/autoprompt/README.md +++ b/autoprompt/README.md @@ -1,47 +1,70 @@ # autoprompt/ -Prompts about the PyAuto workflow infrastructure itself — i.e. the tooling that -makes prompts in this repo flow smoothly from idea to merged PR. - -> ⚠️ **Caveat — drafted from a stale repo state.** These prompts were drafted on -> 2026-04-27 during a forensic sweep that found local checkouts up to 101 commits -> behind origin. The trigger looked like a structural workflow flaw, but later -> analysis showed the drift was largely driven by **stale local checkouts being -> edited without `git pull` first**, not by missing tooling. Now that PyAutoPrompt -> is the canonical source-of-truth and `skills/install.sh` auto-discovers across -> both repos, several of the recommendations here may be over-engineered for the -> day-to-day case. Re-evaluate whether each measure is still warranted before -> implementing — the cheap habits (pull before edit, never rewrite history) buy -> most of the win. Each prompt has its own caveat at the top. - -These were drafted after a forensic sweep on 2026-04-27 found that local checkouts -across 12 repos had drifted up to 101 commits behind origin, with parallel -"fresh start" history rewrites and 41 redundant local commits. The root causes -were structural — multiple environments writing in parallel without flow rules, -no visible drift indicator, generated artifacts polluting `git status` so real -divergence was invisible, and skills/scripts that didn't enforce a "pull first" -discipline. - -The seven prompts below address those root causes in increasing order of -investment / impact. Numbers indicate suggested implementation order; later -prompts assume earlier ones have landed. - -| # | Prompt | Tier | Effort | Prevents | -|---|---|---|---|---| -| [01](01_status_dashboard.md) | `pyauto-status` shell function | 1 | 15 min | Drift being invisible | -| [02](02_gitignore_noise.md) | `.gitignore` workspace artifacts | 1 | 30 min | Generated files burying real `git status` signal | -| [03](03_history_rewrite_guard.md) | "Never rewrite history" rule in CLAUDE.md/AGENTS.md | 2 | 30 min | Independent `git init` fresh-starts on multiple machines | -| [04](04_source_of_truth_rule.md) | "Pull before edit" rule | 2 | 30 min | Duplicate-content commits from stale checkouts | -| [05](05_sync_slash_command.md) | `/sync` slash command | 3 | 2-3 h | Manual drift recovery being too expensive to do regularly | -| [06](06_repo_health_audit.md) | Monthly repo-health audit | 3 | 1-2 h | Untethered checkouts, dead branches, stale stashes | -| [07](07_worktree_only_edits.md) | Enforce worktree-only edits on canonical checkouts | 4 | 4-6 h | The whole class of drift, structurally | - -If you do nothing else, do **01** and **03**. Those two cost ~45 minutes and -would have prevented the bulk of what was cleaned up on 2026-04-27. - -The *biggest* single fix is **07** — once canonical checkouts of `PyAuto*` and -`*_workspace*` repos become read-only mirrors of origin/main with all editing -happening in task worktrees, the drift mechanism is structurally impossible. -The infrastructure already exists (`admin_jammy/software/worktree.sh`, -`/start_library`, `/start_workspace`, `/ship_*`); the missing piece is a rule -saying "no one ever `cd` into `~/Code/PyAutoLabs//` to edit, ever." +Workflow-infrastructure prompts drafted on 2026-04-27 after a forensic +sweep found local checkouts up to 101 commits behind origin. The eight +prompts addressed root causes structurally — visibility, gitignore noise, +history-rewrite guards, source-of-truth rules, sync tooling, repo +audits, worktree-only enforcement, and persistent test/build summaries. + +This directory now contains only this README. The shipped prompts live +in [`../issued/`](../issued/) (per-prompt `_.md`); the rejected +ones are gone. + +## Outcomes + +| # | Prompt | Outcome | Implementation | +|---|---|---|---| +| 01 | `pyauto-status` shell function | Shipped | [issued/01_status_dashboard.md](../issued/01_status_dashboard.md) — `scripts/pyauto_status.sh` | +| 02 | `.gitignore` workspace artifacts | Shipped | [issued/02_gitignore_noise.md](../issued/02_gitignore_noise.md) — 8 workspace PRs | +| 03 | "Never rewrite history" rule | Shipped | [issued/03_history_rewrite_guard.md](../issued/03_history_rewrite_guard.md) — 17 repos × CLAUDE.md/AGENTS.md | +| 04 | "Pull before edit" rule | **Skipped** | Redundant with 01 (BEHIND counts) + 03 (history guard) | +| 05 | `/sync` slash command | Shipped (re-scoped) | [issued/05_sync_slash_command.md](../issued/05_sync_slash_command.md) — dashboard's "Follow-up commands:" section instead of a heavyweight skill | +| 06 | Monthly repo-health audit | Shipped (re-scoped) | [issued/06_repo_health_audit.md](../issued/06_repo_health_audit.md) — `scripts/pyauto_audit.sh` (on-demand `pyauto-audit`, no cron) | +| 07 | Worktree-only edits enforcement | **Skipped** | Doc-rule layer wasn't worth 17 PRs; shell hook + `/sync` reset depended on rejected pieces | +| 08 | Persistent test/build summary | Shipped | [issued/08_test_summary.md](../issued/08_test_summary.md) — dashboard "Smoke tests:" + "Last autobuild run:" sections | + +## What the sweep actually fixed + +- **Drift visibility.** `pyauto-status` runs on every venv activation and + prints branch / upstream / behind / ahead / dirty counts plus the + `b` flag for forgotten feature branches. Drift can no longer hide. +- **Generated noise.** Workspaces' `.gitignore` files were rationalised + (prompt 02), so `git status` shows real divergence instead of pyc + pollution and stray artifacts. +- **History-rewrite guard.** Every PyAuto repo's `CLAUDE.md` / + `AGENTS.md` documents the forbidden ops (`rm -rf .git && git init`, + `Initial commit` resets, force-push to main, etc.). Catches the + specific pattern that caused ~40 redundant local commits. +- **Actionable dashboard.** Beyond the table, `pyauto-status` prints + copy-pasteable follow-up commands grouped by category (Pull / + Set missing upstream / Investigate manually) — drift recovery is + now one paste away. +- **Structural audit.** `pyauto-audit` finds non-git directories under + `~/Code/PyAutoLabs/`, stashes >14 days old, and abandoned local-only + branches (>30 days). Run on demand. +- **Test + release status.** Dashboard now reads + `~/.cache/pyauto/smoke/.json` (written by the + `/smoke-test` skill) and PyAutoBuild's committed `test_results/` to + show colored smoke counts and the latest autobuild aggregate on + every venv activation. + +## What the sweep deliberately didn't do + +- Doc rules in CLAUDE.md repeating things the dashboard already + surfaces (prompt 04). +- A heavyweight `/sync` slash command with stash-handling and + duplicate-commit detection (prompt 05's full spec — replaced by + copy-pasteable commands in the dashboard). +- A monthly cron schedule for the audit (prompt 06's full spec — the + audit is on-demand only). +- Read-only-mirror enforcement of canonical checkouts via shell hooks + or `/sync` resets (prompt 07 entirely). + +## Reading order + +If you want the historical narrative, read the shipped prompts in +numeric order in [`../issued/`](../issued/) — each preserves its +2026-04-27 framing, including its own caveat about being drafted from +a stale repo state. Re-evaluate before reusing as a template; the +cheap habits (pull before edit, never rewrite history) bought most of +the win. diff --git a/autoprompt/05_sync_slash_command.md b/issued/05_sync_slash_command.md similarity index 100% rename from autoprompt/05_sync_slash_command.md rename to issued/05_sync_slash_command.md diff --git a/autoprompt/06_repo_health_audit.md b/issued/06_repo_health_audit.md similarity index 100% rename from autoprompt/06_repo_health_audit.md rename to issued/06_repo_health_audit.md diff --git a/autoprompt/08_test_summary.md b/issued/08_test_summary.md similarity index 100% rename from autoprompt/08_test_summary.md rename to issued/08_test_summary.md