From 4ed248f698b2bedff99eb9c24b01aa3ba2382624 Mon Sep 17 00:00:00 2001 From: Flavio Soibelmann Glock Date: Tue, 28 Apr 2026 12:16:35 +0200 Subject: [PATCH] docs(agents): mandatory pre-flight + forbidden-commands warnings for dirty trees Adds two big warning blocks (peer to the existing `git stash` one) and a short Incident Log so the rules are tied to a real, recent failure. Motivated by a 2026-04-28 incident: an agent ran `git checkout dev/cpan-reports/` on an unstaged cpan-tester refresh and silently destroyed ~600 module results. AGENTS.md already warned about `git stash` but said nothing about `checkout ` / `restore` / `reset --hard` / `clean`, which are equally destructive on a dirty tree. Changes: - New "MANDATORY PRE-FLIGHT FOR ANY DIRTY TREE" block with the exact snapshot + WIP-branch commands to run first. - New "FORBIDDEN COMMANDS ON A DIRTY TREE" block enumerating the destructive verbs and the safe alternative. - New "Incident Log" table; future incidents append here. - Top-of-file note telling readers the warnings document real losses, not hypothetical ones. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- AGENTS.md | 69 +++++++++++++++++++ .../org/perlonjava/core/Configuration.java | 6 +- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3df68c953..e8be5ec90 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,65 @@ # PerlOnJava Agent Guidelines +> **Read this file before touching the working tree.** +> The two warning blocks below are not decorative — they document +> real incidents in which agents silently destroyed user work. +> If you skip them you will eventually be the next incident. + +## ⚠️⚠️⚠️ MANDATORY PRE-FLIGHT FOR ANY DIRTY TREE ⚠️⚠️⚠️ + +``` +╔══════════════════════════════════════════════════════════════════════════════╗ +║ ║ +║ IF `git status` SHOWS *ANY* MODIFIED OR UNTRACKED FILES YOU DID NOT ║ +║ CREATE IN THIS SESSION, RUN THIS BEFORE DOING ANYTHING ELSE: ║ +║ ║ +║ ts=$(date +%Y%m%d-%H%M%S) ║ +║ git diff > /tmp/wip-unstaged-$ts.patch ║ +║ git diff --cached > /tmp/wip-staged-$ts.patch ║ +║ git status -s > /tmp/wip-status-$ts.txt ║ +║ ║ +║ Then put the changes into a real commit on a WIP branch: ║ +║ ║ +║ git checkout -b wip/-$ts ║ +║ git add -A && git commit -m "wip: snapshot before " ║ +║ ║ +║ Only AFTER both backups exist may you run anything that touches the ║ +║ working tree (rebase, checkout, restore, reset, clean, stash, …). ║ +║ ║ +║ The user's unstaged edits are NOT in git's object database. A single ║ +║ wrong `git checkout ` overwrites them with no possible recovery. ║ +║ ║ +╚══════════════════════════════════════════════════════════════════════════════╝ +``` + +## ⚠️⚠️⚠️ FORBIDDEN COMMANDS ON A DIRTY TREE ⚠️⚠️⚠️ + +``` +╔══════════════════════════════════════════════════════════════════════════════╗ +║ ║ +║ The following commands SILENTLY DESTROY unstaged user work. ║ +║ Do NOT run them on a dirty tree, even "just to clean up": ║ +║ ║ +║ git checkout ← overwrites working tree from index ║ +║ git checkout -- ← same thing, no safer ║ +║ git restore ← overwrites working tree from index ║ +║ git restore --staged ← only safe if you've snapshot-ed ║ +║ git reset --hard ← nukes everything unstaged ║ +║ git clean -fd ← deletes untracked files permanently ║ +║ git stash / git stash pop ← see warning below; can lose data ║ +║ ║ +║ If you really need to drop a single file's changes: ║ +║ 1. Do the pre-flight backup above. ║ +║ 2. `mv path/to/file /tmp/discarded-$ts` instead of `git checkout`. ║ +║ 3. Re-create from HEAD with `git show HEAD:path > path` if needed. ║ +║ ║ +║ When the user asks "open a PR with these changes", your FIRST action ║ +║ is `git checkout -b && git add -A && git commit -m wip`. ║ +║ Branch first, snapshot second, polish third. Never reorder these. ║ +║ ║ +╚══════════════════════════════════════════════════════════════════════════════╝ +``` + ## ⚠️⚠️⚠️ CRITICAL WARNING: NEVER USE `git stash` ⚠️⚠️⚠️ ``` @@ -18,6 +78,15 @@ ╚══════════════════════════════════════════════════════════════════════════════╝ ``` +## Incident Log (do not delete — this is why the rules above exist) + +| Date | What was lost | Root cause | +|------------|------------------------------------------------|---------------------------------------------------| +| 2026-04-28 | ~600 cpan-tester module results (4736 → 4139) | Agent ran `git checkout dev/cpan-reports/` on an unstaged refresh; concurrent `cpan_random_tester.pl` instances also race on `.dat` files (separate bug). | + +When you cause a new incident, append a row here in the same commit +that fixes it. Future agents need to see that these warnings are real. + --- ## Project Rules diff --git a/src/main/java/org/perlonjava/core/Configuration.java b/src/main/java/org/perlonjava/core/Configuration.java index 67ab62999..d3357ff1d 100644 --- a/src/main/java/org/perlonjava/core/Configuration.java +++ b/src/main/java/org/perlonjava/core/Configuration.java @@ -33,14 +33,14 @@ public final class Configuration { * Automatically populated by Gradle/Maven during build. * DO NOT EDIT MANUALLY - this value is replaced at build time. */ - public static final String gitCommitId = "69964ee2f"; + public static final String gitCommitId = "7d7723dfb"; /** * Git commit date of the build (ISO format: YYYY-MM-DD). * Automatically populated by Gradle/Maven during build. * DO NOT EDIT MANUALLY - this value is replaced at build time. */ - public static final String gitCommitDate = "2026-04-27"; + public static final String gitCommitDate = "2026-04-28"; /** * Build timestamp in Perl 5 "Compiled at" format (e.g., "Apr 7 2026 11:20:00"). @@ -48,7 +48,7 @@ public final class Configuration { * Parsed by App::perlbrew and other tools via: perl -V | grep "Compiled at" * DO NOT EDIT MANUALLY - this value is replaced at build time. */ - public static final String buildTimestamp = "Apr 27 2026 22:11:34"; + public static final String buildTimestamp = "Apr 28 2026 12:16:39"; // Prevent instantiation private Configuration() {