From 6cfd126b63026a5adfa9d47c1ab86b8aba0251fe Mon Sep 17 00:00:00 2001 From: JoshuaVSherman Date: Tue, 4 Aug 2026 16:40:31 -0400 Subject: [PATCH 1/5] feat: sync canonical cross-AI rules into AGENTS.md --- AGENTS.md | 25 +++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 7361f0a..83771e3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,6 +2,31 @@ Guidance for AI coding agents (agy/Antigravity, etc.) working in this repo. + + +## OPERATIONAL HARD RULES (apply to any AI taking action on Josh's behalf) + +- CALENDAR CONFLICT: never schedule over an existing event without Josh's explicit override. +- EMAIL: always DRAFT, never send. Save as Gmail draft for Josh's review. +- FILES: never create a version-suffixed copy. Edit the master. +- Never contact venues, churches, or other third parties directly — Josh handles all outreach. +- **STATE VERIFICATION**: Before any suggestion, to-do item, or "ready for you" claim about a PR/issue/CI/deploy, run a fresh liveness check in that same turn (e.g. `gh pr view --json state,mergedAt` / `gh issue view --json state`). If state ≠ OPEN, it is done: drop it silently. `mergeable: UNKNOWN/null` on a PR usually means merged/closed — never read it as "the API is slow" and never advise merging without confirming state=OPEN. An inconclusive check is not a completed check: use a definitive fallback (local `git merge-tree`, `statusCheckRollup`) or say plainly that you could not verify — never hand Josh a verification step the agent can run itself. +- **ONE REPO, ONE SESSION**: never edit a repo another AI session is actively working (Josh, 2026-07-11). Before branching or editing, check `git status -sb` — a non-`dev` branch or dirty tree means another session likely has the repo in flight. Hand the change to that session/lane (route via Josh) or ask Josh first. A separate worktree or non-colliding branch does NOT make concurrent edits OK — parallel semver bumps and surprise PRs still collide. +- **MAX 2 CONCURRENT WORKSTREAMS PER TERMINAL**: Two live background jobs (e.g. a subagent + a headless agy dispatch) is the cap. When a THIRD thread (new discussion, dispatch, or background job) starts in the same session, the agent must WARN Josh first and propose a separate terminal — never comply silently. Origin: 2026-07-16, Claude A froze mid-permission-prompt while running a Sonnet subagent + a headless agy dispatch plus a new discussion; recovery required keystroke injection from another session. +- **ISSUE CITATIONS ALWAYS CARRY REPO + NUMBER + TITLE**: Every mention of a GitHub issue or PR — in chat, in a commit message, in an issue/PR body, in a memory or queue file — must be written as `repo#number "title"`, e.g. `web-jam-back#998 "email subject or title still not easy for me to see its target venue"`. **`#` followed by digits is an ILLEGAL token in anything Josh reads.** There is no exception for a repeat mention, a list item, a parenthetical, "the one I just named", or a closing one-line offer. If you don't know the title, look it up (`gh issue view N --repo R --json title`) before writing the sentence — never emit a bare number as a placeholder. If the full citation is too verbose, shorten to the TITLE, never to the number. The violation is almost always the LAST sentence of a message (the "want me to do X?" offer, written after the careful part), so re-read the finished message and check every `#` before sending. Josh has asked for this five times (2026-07-24 → 2026-07-29); he reads these on a phone with many numbers in flight and a bare number costs him a lookup every time. +- **NO AGENT CONNECTS A NEW ACCOUNT, CREDENTIAL, OR MCP SERVER WITHOUT AUTHORIZATION:** No agent adds a connector, account, credential, or MCP server to any Claude or Flash surface without Josh's explicit authorization naming it. Discovering that something *could* be connected is never permission to connect it. This applies to new OAuth grants, new MCP servers, new API tokens, and widening the scope of an existing connection. Origin (2026-07-30, Josh): *"it should NEVER have something else that I have not authorized."* See web-jam-tools#324 "No agent connects a new account, credential, or MCP server without Josh's explicit authorization — add the rule and audit where it can be mechanically enforced" for the enforcement-surface audit. +- **STANDING AGENT CREDENTIAL CLASSIFICATION RULE (MACHINE-CONSUMED VS HUMAN-CONSUMED):** Whenever an agent encounters or generates a new credential, account identifier, or token, the agent must **STOP and prompt Josh to classify it** as either machine-consumed (e.g. `GITHUB_TOKEN`, `GEMINI_API_KEY`, `HEROKU_API_KEY`, `CIRCLECI_TOKEN`, `DENO_DEPLOY_TOKEN` stored in shell rc or secret store) or human-consumed (e.g. `webjam.claude@gmail.com` stored in KeePass only) BEFORE storing, exporting, or configuring it in any shell profile, `.env` file, or configuration file. Human-consumed credentials belong in KeePass only and must never be exported to shell profiles or stored in application configuration files (web-jam-tools#344 "Human-only credentials register and guard hook"). +- **NO AI DELETES OR FORCE-PUSHES A REMOTE BRANCH, EVER, WITHOUT AN EXPLICIT IMPERATIVE FROM JOSH NAMING THAT BRANCH.** "The PR is merged" is NOT such an instruction — it states a fact, it does not authorize deleting anything. Local branch cleanup after a merge (deleting a LOCAL branch with `git branch -d`/`-D`, `git fetch --prune` to prune stale local remote-tracking refs) remains permitted and unchanged — this rule narrows that standing post-merge cleanup habit to local branches only, it does not remove it or require re-approval for it. Enforced by three independent layers: a harness `permissions.deny` block on the ways `git push`/`git branch` can delete or clobber a remote ref (`--delete`/`-d`, empty-source colon refspecs, `--force`/`-f`/`--force-with-lease`, `--mirror`, `--prune`, and `git branch -D`/`--delete --force` against a `remotes/` ref — installed via `scripts/install-hooks.sh` in this repo), a GitHub ruleset restricting deletions on the branches agents create (`claude/**`, `agy/**`, `dev`, `main` — Josh-only UI work, see web-jam-tools#308 "Remote branches can be deleted by an agent with no authorization — advisory guard does not block (3 layers: deny rules, GitHub ruleset, HARD RULES)"), and this HARD RULE. Origin: 2026-07-29, an agent deleted `claude/cross-ai-rules-issue-citation-hard-rule` from `web-jam-tools` immediately after Josh merged web-jam-tools#307 "Add ISSUE CITATIONS hard rule to operational rules" — Josh had only said the PR was merged, never authorized a deletion, and the `PreToolUse` guard that fired was advisory text an agent could rationalize past. +- **REAPER RECORDING SESSIONS & RATE LIMIT SAFETY:** When running REAPER music recording sessions via Reaper MCP: + 1. REAPER DAW, audio interfaces, recorded WAV audio stems, and `.RPP` project files live locally on the user's computer and are 100% safe from rate limit interruptions. + 2. Google does NOT broadcast an advance warning gauge prior to hitting temporary hourly rate limits (`429 Rate Limit Exceeded`). + 3. Use **`Flash Med`** for routine, high-volume REAPER operations (`transport_play`, `transport_stop`, `track_create`, volume/pan tweaks, clip splits) to preserve hourly token headroom. + 4. Reserve **`Flash High`** for complex multi-track creative mixing, sidechain routing, and intricate composition passes. + 5. Always execute a project save (`project_save`) before running large multi-step automated sequences. +- **MAIN BRANCH PRs MUST ORIGINATE FROM DEV:** Across all 8 active WebJamApps repos, any PR targeting `main` must originate from `dev` as its head branch (`dev` → `main`). Feature branches (`gemini/*`, `claude/*`, `feat/*`, `fix/*`) must target `dev` as their base branch. Direct PRs from feature branches to `main` are strictly forbidden and blocked by CI and script guardrails (web-jam-tools#351 "all 8 active github repos - their main branch only accepts PR requests from their dev branch"). +- **MULTI-REPO ISSUES STAY OPEN UNTIL ALL REPOS ARE COMPLETE:** When an issue explicitly covers multiple repositories (e.g. "all 8 active github repos"), no single PR in one repository may pass `--closes` or claim the issue is completed. PRs in individual repos must use `--part-of` so the tracking issue remains OPEN until the final repository's PR is merged. +- **THE `Blocked` LABEL IS CANONICAL — NATIVE ISSUE DEPENDENCIES DO NOT REPLACE IT.** Josh wants BOTH: native GitHub issue-dependency links (the real relationship between issues) AND the `Blocked` label (capital B, hex `B60205`, `repos: all` in `skills/fix-labels/labels.yaml`) as the at-a-glance signal that makes an unworkable issue obvious in a plain list view without opening each issue. They do different jobs: use a native dependency whenever a **specific issue** blocks the work — it names which one, renders in the Issues list, and clears itself on close. Use the `Blocked` label whenever the work is unworkable **for any reason**, including the many with no issue to point at (a vendor, a credential Josh must generate, a physical action). Native dependencies cannot express that case at all, which is why the label is not redundant. No agent may prune `Blocked` from `labels.yaml` (or delete it live) on the theory that native dependencies made it redundant — that is exactly what happened once already: `blocked` (lowercase) was removed in commit 7d2523d as part of a nine-label prune shipped for web-jam-tools#300, justified as "-> native issue dependencies," and Josh never actually agreed to that one — it rode along in a batch whose headline was about priority labels. web-jam-tools#329 "Restore the Blocked label as canonical in labels.yaml — it was pruned in a batch Josh never ratified, and he wants it alongside native dependencies" restored it. See `skills/fix-labels/labels.yaml`'s `Blocked` entry for the full rationale. + ## What this is A React + TypeScript + Vite front-end for Apperson Auto. diff --git a/package.json b/package.json index 872765d..bd27fc1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appersonautomotive.com", - "version": "3.2.3", + "version": "3.2.4", "description": "appersonautomotive.com", "main": "dist/index.html", "repository": { From 5f24f60a530a72ac21fc4ea9bd0faafb7315100a Mon Sep 17 00:00:00 2001 From: JoshuaVSherman Date: Tue, 4 Aug 2026 16:50:56 -0400 Subject: [PATCH 2/5] test: update snapshots for package version 3.2.4 bump --- test/App/__snapshots__/App.spec.tsx.snap | 2 +- test/App/__snapshots__/AppTemplate.spec.tsx.snap | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/App/__snapshots__/App.spec.tsx.snap b/test/App/__snapshots__/App.spec.tsx.snap index c922a95..e611c98 100644 --- a/test/App/__snapshots__/App.spec.tsx.snap +++ b/test/App/__snapshots__/App.spec.tsx.snap @@ -158,7 +158,7 @@ exports[`App component > renders the component 1`] = ` style="font-size: 13px; color: rgb(192, 192, 192); font-family: Habibi, ChivoBlack, Arial, sans-serif;" > v - 3.2.3 + 3.2.4 diff --git a/test/App/__snapshots__/AppTemplate.spec.tsx.snap b/test/App/__snapshots__/AppTemplate.spec.tsx.snap index e4a7ec8..b33aa8e 100644 --- a/test/App/__snapshots__/AppTemplate.spec.tsx.snap +++ b/test/App/__snapshots__/AppTemplate.spec.tsx.snap @@ -154,7 +154,7 @@ exports[`AppTemplate > calls the mobile menu 1`] = ` style="font-size: 13px; color: rgb(192, 192, 192); font-family: Habibi, ChivoBlack, Arial, sans-serif;" > v - 3.2.3 + 3.2.4 @@ -420,7 +420,7 @@ exports[`AppTemplate > renders the component 1`] = ` style="font-size: 13px; color: rgb(192, 192, 192); font-family: Habibi, ChivoBlack, Arial, sans-serif;" > v - 3.2.3 + 3.2.4 From a8d718f9c759dbce8789477800a77a04cddd5477 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:53:44 +0000 Subject: [PATCH 3/5] chore(deps): Bump fast-uri from 3.1.4 to 3.1.5 Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.4 to 3.1.5. - [Release notes](https://github.com/fastify/fast-uri/releases) - [Commits](https://github.com/fastify/fast-uri/compare/v3.1.4...v3.1.5) --- updated-dependencies: - dependency-name: fast-uri dependency-version: 3.1.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index d731579..c32ba20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "appersonautomotive.com", - "version": "3.2.0", + "version": "3.2.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "appersonautomotive.com", - "version": "3.2.0", + "version": "3.2.4", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -56,7 +56,7 @@ "vitest-axe": "^0.1.0" }, "engines": { - "node": "24.18.0" + "node": "24.18.1" } }, "node_modules/@adobe/css-tools": { @@ -4032,9 +4032,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", - "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", "devOptional": true, "funding": [ { From b76490baa20c96ae36d08cded6556967ae84a3b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:55:02 +0000 Subject: [PATCH 4/5] chore(deps-dev): Bump undici from 7.28.0 to 7.29.0 Bumps [undici](https://github.com/nodejs/undici) from 7.28.0 to 7.29.0. - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v7.28.0...v7.29.0) --- updated-dependencies: - dependency-name: undici dependency-version: 7.29.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index d731579..3933e74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "appersonautomotive.com", - "version": "3.2.0", + "version": "3.2.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "appersonautomotive.com", - "version": "3.2.0", + "version": "3.2.4", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -56,7 +56,7 @@ "vitest-axe": "^0.1.0" }, "engines": { - "node": "24.18.0" + "node": "24.18.1" } }, "node_modules/@adobe/css-tools": { @@ -7425,9 +7425,9 @@ } }, "node_modules/undici": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", - "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", "dev": true, "license": "MIT", "engines": { From cfbd4e6d6cb6dab8a7a1f6fa0b58874be9769d40 Mon Sep 17 00:00:00 2001 From: JoshuaVSherman Date: Wed, 5 Aug 2026 06:54:14 -0400 Subject: [PATCH 5/5] docs: sync operational hard rules (restricted laptop Dropbox scope) into AGENTS.md per web-jam-tools#321 --- AGENTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AGENTS.md b/AGENTS.md index 83771e3..8babd16 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,6 +26,7 @@ Guidance for AI coding agents (agy/Antigravity, etc.) working in this repo. - **MAIN BRANCH PRs MUST ORIGINATE FROM DEV:** Across all 8 active WebJamApps repos, any PR targeting `main` must originate from `dev` as its head branch (`dev` → `main`). Feature branches (`gemini/*`, `claude/*`, `feat/*`, `fix/*`) must target `dev` as their base branch. Direct PRs from feature branches to `main` are strictly forbidden and blocked by CI and script guardrails (web-jam-tools#351 "all 8 active github repos - their main branch only accepts PR requests from their dev branch"). - **MULTI-REPO ISSUES STAY OPEN UNTIL ALL REPOS ARE COMPLETE:** When an issue explicitly covers multiple repositories (e.g. "all 8 active github repos"), no single PR in one repository may pass `--closes` or claim the issue is completed. PRs in individual repos must use `--part-of` so the tracking issue remains OPEN until the final repository's PR is merged. - **THE `Blocked` LABEL IS CANONICAL — NATIVE ISSUE DEPENDENCIES DO NOT REPLACE IT.** Josh wants BOTH: native GitHub issue-dependency links (the real relationship between issues) AND the `Blocked` label (capital B, hex `B60205`, `repos: all` in `skills/fix-labels/labels.yaml`) as the at-a-glance signal that makes an unworkable issue obvious in a plain list view without opening each issue. They do different jobs: use a native dependency whenever a **specific issue** blocks the work — it names which one, renders in the Issues list, and clears itself on close. Use the `Blocked` label whenever the work is unworkable **for any reason**, including the many with no issue to point at (a vendor, a credential Josh must generate, a physical action). Native dependencies cannot express that case at all, which is why the label is not redundant. No agent may prune `Blocked` from `labels.yaml` (or delete it live) on the theory that native dependencies made it redundant — that is exactly what happened once already: `blocked` (lowercase) was removed in commit 7d2523d as part of a nine-label prune shipped for web-jam-tools#300, justified as "-> native issue dependencies," and Josh never actually agreed to that one — it rode along in a batch whose headline was about priority labels. web-jam-tools#329 "Restore the Blocked label as canonical in labels.yaml — it was pruned in a batch Josh never ratified, and he wants it alongside native dependencies" restored it. See `skills/fix-labels/labels.yaml`'s `Blocked` entry for the full rationale. +- **RESTRICTED LAPTOP DROPBOX SCOPE & SECURITY GUARDRAILS:** Access to `~/Dropbox` on the laptop is restricted to three approved top-level folders: `joshandmariamusic`, `web-jam-llms`, and `mark_henrickson`. All other top-level `~/Dropbox/*` folders — including `Dropbox/WebJamApps` — are explicitly denied in `permissions.deny` via `install-hooks.sh` for file tools (`Read`, `Edit`, `Write`) and Dropbox MCP mutation tools (`delete`, `move`). Note: Deny rules on file tools do not constrain raw Bash commands (which use string-pattern matching for Bash permission rules), serving as an operational guardrail rather than an absolute security boundary (web-jam-tools#321 "Add the laptop Dropbox deny list, verify Flash confinement, and document the restricted scope"). ## What this is A React + TypeScript + Vite front-end for Apperson Auto.