From b88cdeb686d5b0acbb01bb0302f97751052b4e60 Mon Sep 17 00:00:00 2001 From: Daniel McCoy Stephenson Date: Wed, 4 Nov 2026 19:52:56 -0700 Subject: [PATCH 1/2] Make Steps 6 and 7 safe to re-run under overwrite mode Co-Authored-By: Claude Opus 5.5 --- create-dev-loop.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/create-dev-loop.md b/create-dev-loop.md index c102fa5..e1c5576 100644 --- a/create-dev-loop.md +++ b/create-dev-loop.md @@ -645,7 +645,7 @@ Use findings from Step 2 to substitute each `{{placeholder}}`. The table below c | `CLAUDE_MD` | True if `CLAUDE.md` exists in the repo root (`ls CLAUDE.md 2>/dev/null`); controls whether the "Project guidance" line appears in the skill header | | `SELF_REVIEW_RUBRIC` | Repo-specific objective yes/no rubric items for the Phase 4 self-review. Each item must be answerable from the diff or a command output, not from judgment. Add items only when the repo has anti-patterns or invariants not already covered by the universal items in Phase 4. Examples: "Every `@Override` matches a real superclass method" (Java); "No `console.log` in committed code" (JS); "Every new permission appears in `plugin.yml`" (Bukkit plugin). Format as one indented Markdown bullet per item: ` - **:** `. Omit the conditional block entirely if no repo-specific items apply. | | `DO_NOT_AUTO_MERGE` | Repo-specific paths that require human review before merge (in addition to the universal entries in Phase 8). Common entries: `plugin.yml` (Bukkit plugins), `pom.xml` (Maven projects), `Cargo.toml` (Rust), `package.json` (Node), the project's main config or schema file. Format as one Markdown bullet per entry, with backticks around the path or glob and a brief rationale after an em-dash. Omit the conditional block entirely if no repo-specific entries apply. | -| `TEMPLATE_VERSION` | Short commit SHA of the `create-dev-loop` repo at generation time. Capture with `git -C rev-parse --short HEAD`. Becomes part of an HTML comment at the top of the generated skill so future cycles can detect template drift. | +| `TEMPLATE_VERSION` | Short commit SHA of the `create-dev-loop` repo at generation time. Capture with `git -C rev-parse --short HEAD`. Becomes part of an HTML comment directly below the H1 heading of the generated skill so future cycles can detect template drift. | | `GENERATED_AT` | ISO-8601 UTC timestamp at generation time. Capture with `date -u +%Y-%m-%dT%H:%M:%SZ`. Pairs with `TEMPLATE_VERSION` in the HTML-comment header. | **When the repo has no build system or no automated test suite**, `COMPILE_CMD`, `TEST_CMD`, `REVALIDATE_INSTRUCTION`, `VALIDATION_NOTE`, and `EXTERNAL_SIGNAL_CMD` must all name the *same* check — whatever the project actually gates correctness on. Also reword the Phase 3 "Confirm the anchor actually executed tests" rule and the Edge cases entries that name tests — "Tests fail during implementation", "Tests fail after addressing a comment", "A test fails intermittently", and the post-rebase verification step of "Branch is behind main or has a merge conflict at Phase 8" — so they refer to that check rather than a test suite (an "executed-test count from `# re-run the manual checklist`" is not a sentence a generated skill should carry); keep the entry order, wording of the surrounding rules, and phase numbers unchanged. @@ -685,22 +685,28 @@ repo-specific choices made (build system, test command, doc sources, reviewer, b **Skip this step if `MODE=update`** — the repo already exists from the initial generation. (Run only when `MODE=fresh` or `MODE=overwrite`.) +Every command in this step is safe to re-run: under `MODE=overwrite` the repo, remote, and labels already exist, so each is re-asserted rather than created a second time. + ```bash -gh repo create -dev-loop --private --description "Autonomous dev loop skill for {{PROJECT_NAME}}" +gh repo view "$(gh api user -q .login)/-dev-loop" >/dev/null 2>&1 || \ + gh repo create -dev-loop --private --description "Autonomous dev loop skill for {{PROJECT_NAME}}" ``` -Initialize the local skill directory as a git repo, commit the skill file, and push: +Initialize the local skill directory as a git repo, commit the skill file, and push. Use the commit message `Initial commit: -dev-loop skill` when `MODE=fresh` and `Regenerate -dev-loop skill` when `MODE=overwrite`. An existing `origin` is left as it is, so a skill repo that has since been transferred or renamed keeps its working remote. The commit is skipped when the regenerated file is unchanged. ```bash cd ~/local-skills/-dev-loop git init git branch -m main -git remote add origin https://github.com/$(gh api user -q .login)/-dev-loop.git +git remote get-url origin >/dev/null 2>&1 || \ + git remote add origin https://github.com/$(gh api user -q .login)/-dev-loop.git git add -dev-loop.md -git commit -m "Initial commit: -dev-loop skill" +git diff --cached --quiet || git commit -m "" git push -u origin main ``` +If the push is rejected, stop and report it — the remote has history this directory does not. Never force-push over it. + The GitHub repo serves as the issue tracker for self-audit findings. When the generated skill's Phase 9 says "file issues there for human review", issues go here. Create the gap-issue labels used by Phase 9 so they exist when the first cycle runs: @@ -714,7 +720,7 @@ for entry in \ "research-gap:B60205:New finding worth a RESEARCH.md entry" \ "process:CFD3D7:Meta-issue about how the loop runs"; do IFS=: read -r name color desc <<< "$entry" - gh label create "$name" --color "$color" --description "$desc" --repo "$OWNER/-dev-loop" + gh label create "$name" --force --color "$color" --description "$desc" --repo "$OWNER/-dev-loop" done ``` @@ -732,18 +738,18 @@ Some users keep a personal catalog repo listing every skill they have and where **If absent** (unset, or set to something that isn't a git repo), skip this step silently — it is not required for the generated skill to work (Step 5 already registered the slash command). Do not create the directory or repo on the user's behalf, and do not guess at a catalog location. -**If present**, open `$CLAUDE_SKILLS_CATALOG/README.md` and append a new row to its skills table using the GitHub repo created in Step 6 (`OWNER=$(gh api user -q .login)`, same as Step 6). Match the existing table's column order rather than assuming this one: +**If present**, open `$CLAUDE_SKILLS_CATALOG/README.md` and add a row to its skills table using the GitHub repo from Step 6 (`OWNER=$(gh api user -q .login)`, same as Step 6). If a row for `-dev-loop` already exists, replace that row in place rather than appending a duplicate. Match the existing table's column order rather than assuming this one: ``` | -dev-loop | `/-dev-loop` | [$OWNER/-dev-loop](https://github.com/$OWNER/-dev-loop) | Autonomous dev loop for {{PROJECT_NAME}} | ``` -Then commit and push: +Then commit and push, skipping the commit when an existing row already matched: ```bash cd "$CLAUDE_SKILLS_CATALOG" git add README.md -git commit -m "Add -dev-loop skill" +git diff --cached --quiet || git commit -m "Add -dev-loop skill" git push ``` From 81882b6ed70d0b3a10fd9c8fa3f8ca14ba87fb83 Mon Sep 17 00:00:00 2001 From: Daniel McCoy Stephenson Date: Thu, 5 Nov 2026 19:21:53 -0700 Subject: [PATCH 2/2] Refuse public skill repos and follow the existing remote in Steps 6 and 7 Stop when an existing skill repo is public, use the existing origin's owner and name for labels, the catalog row, and SKILL_REPO_OWNER, and ignore the generated-at comment when deciding whether a regenerated skill changed. Co-Authored-By: Claude Opus 5.5 --- create-dev-loop.md | 49 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/create-dev-loop.md b/create-dev-loop.md index e1c5576..77fc8f7 100644 --- a/create-dev-loop.md +++ b/create-dev-loop.md @@ -627,7 +627,7 @@ Use findings from Step 2 to substitute each `{{placeholder}}`. The table below c | `REPO_ROOT` | Output of `git rev-parse --show-toplevel`. Used as the *configured* fallback path in the Phase 1 resolution block, not as a hardcoded `cd` target. | | `REPO_ENV_VAR` | Name of the per-repo override env var the Phase 1 resolver checks first, derived from the repo slug: uppercase, non-alphanumerics→`_`, suffix `_DIR` (e.g. `dpm` → `DPM_DIR`, `medieval-factions` → `MEDIEVAL_FACTIONS_DIR`). Substituted bare (no braces) into `${VAR}` in the resolver. | | `GITHUB_OWNER/REPO` | `gh repo view --json nameWithOwner -q .nameWithOwner` | -| `SKILL_REPO_OWNER` | `gh api user -q .login` — the authenticated GitHub account that ran `/create-dev-loop`, i.e. the owner of the skill-tracker repo created in Step 6. Not necessarily the same as `GITHUB_OWNER` when the target project lives under an org. | +| `SKILL_REPO_OWNER` | `gh api user -q .login` — the authenticated GitHub account that ran `/create-dev-loop`, i.e. the owner of the skill-tracker repo created in Step 6. Not necessarily the same as `GITHUB_OWNER` when the target project lives under an org. If `~/local-skills/-dev-loop` is already its own git repo with an `origin`, use that remote's owner instead, so a transferred skill repo is not pointed back at its old owner. | | `DEFAULT_BRANCH` | `gh repo view --json defaultBranchRef -q .defaultBranchRef.name` | | `BRANCH_PREFIX` | From CONTRIBUTING.md, or `feature` if not specified | | `COMPILE_CMD` | Fastest command that catches syntax/import errors without running tests. For Maven: `MVN=$([ -f ./mvnw ] && echo ./mvnw \|\| echo mvn) && $MVN compile`. **If the repo has no build system** (docs-only, config-only, single-template repos), substitute the cheapest mechanical consistency check that would actually catch breakage — e.g. a `grep` for unresolved placeholders, `jq -e . `, a YAML/schema lint. If no such check exists, substitute a shell comment naming what gates correctness instead (e.g. `# no build system — see the validation steps below`) so the fence stays valid bash. Substitute the same text everywhere `{{COMPILE_CMD}}` appears (Phase 3 verify block, Phase 8 rebase fence). | @@ -687,21 +687,45 @@ repo-specific choices made (build system, test command, doc sources, reviewer, b Every command in this step is safe to re-run: under `MODE=overwrite` the repo, remote, and labels already exist, so each is re-asserted rather than created a second time. +Initialize the local skill directory as a git repo and find out which repo it belongs to: + ```bash -gh repo view "$(gh api user -q .login)/-dev-loop" >/dev/null 2>&1 || \ - gh repo create -dev-loop --private --description "Autonomous dev loop skill for {{PROJECT_NAME}}" +cd ~/local-skills/-dev-loop +git init +git branch -m main +git remote get-url origin 2>/dev/null ``` -Initialize the local skill directory as a git repo, commit the skill file, and push. Use the commit message `Initial commit: -dev-loop skill` when `MODE=fresh` and `Regenerate -dev-loop skill` when `MODE=overwrite`. An existing `origin` is left as it is, so a skill repo that has since been transferred or renamed keeps its working remote. The commit is skipped when the regenerated file is unchanged. +Set `` to the `owner/name` part of that URL, or to `/-dev-loop` (with `` from `gh api user -q .login`) if it printed nothing. An existing `origin` is left as it is, so a skill repo that has since been transferred or renamed keeps its working remote, and every later use of the repo in this step and Step 7 follows it through ``. + +Check the repo's visibility: + +```bash +gh repo view --json isPrivate -q .isPrivate 2>/dev/null +``` + +- **`true`:** the repo exists and is private. Continue. +- **`false`:** the repo is public. Stop and report it — a generated skill records repo internals and must not be published. Do not push, and do not change the repo's visibility. +- **No output:** the repo was not found, so create it. If `gh repo view` failed for another reason and the repo does exist, this command fails rather than touching it: + + ```bash + gh repo create --private --description "Autonomous dev loop skill for {{PROJECT_NAME}}" + ``` + +Commit the skill file and push. Use the commit message `Initial commit: -dev-loop skill` when `MODE=fresh` and `Regenerate -dev-loop skill` when `MODE=overwrite`. The `generated-at` comment differs on every run, so it is ignored when deciding whether anything changed: if nothing else did, the committed file is restored and no commit is made. ```bash cd ~/local-skills/-dev-loop -git init -git branch -m main git remote get-url origin >/dev/null 2>&1 || \ - git remote add origin https://github.com/$(gh api user -q .login)/-dev-loop.git -git add -dev-loop.md -git diff --cached --quiet || git commit -m "" + git remote add origin https://github.com/.git +if git rev-parse -q --verify HEAD >/dev/null && \ + [ "$(git show HEAD:-dev-loop.md | grep -v '^