mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-05-11 16:15:24 -04:00
chore: optimize AI agent context and implement CI cost controls (#5335)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
21
.agent_memory/session_context.md
Normal file
21
.agent_memory/session_context.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Agent Session Context - Meshtastic Android
|
||||
# This is a dated, append-only handover log. Add new entries at the TOP.
|
||||
# Do NOT edit or remove previous entries — stale state claims cause agent confusion.
|
||||
# Format: ## YYYY-MM-DD — <summary>
|
||||
|
||||
## 2026-05-02 — CI cost-control PR review fixes
|
||||
- Applied PR review feedback: encoding fixes in sort-strings.py, NUL-delimited staged-files loop
|
||||
in ai-guardrail.sh, installation instructions added, typo fix in strings.xml, command order
|
||||
fixed in AGENTS.md, narrowed .aiexclude/.gitattributes patterns, allTests added to SKILL.md.
|
||||
|
||||
## 2026-04-XX — Token Mitigation (Phase 1-3)
|
||||
- `.copilotignore` and `.aiexclude` updated with stricter ignore rules.
|
||||
- `AGENTS.md` modularized to ~3KB base; detailed rules moved to `.skills/`.
|
||||
- `scripts/ai-guardrail.sh` added to prevent binary/log leaks (installation: see script header).
|
||||
- CI Cost Control skill added at `.skills/ci-cost-control/SKILL.md`.
|
||||
|
||||
## Golden Context (stable across sessions)
|
||||
- Always check `.skills/compose-ui/strings-index.txt` before reading `strings.xml`.
|
||||
- Run `python3 scripts/sort-strings.py` after adding strings to keep the index organized.
|
||||
- Always check `gh run list` before pushing.
|
||||
- Pre-commit hook `scripts/ai-guardrail.sh` protects against binary leaks (see script for install).
|
||||
36
.aiexclude
Normal file
36
.aiexclude
Normal file
@@ -0,0 +1,36 @@
|
||||
# Standard AI exclusion list for Cursor, Windsurf, etc.
|
||||
# Mirroring .copilotignore for project-wide token discipline
|
||||
|
||||
# Build & Generated
|
||||
**/build/**
|
||||
.gradle/
|
||||
.kotlin/
|
||||
**/generated/**
|
||||
|
||||
# Agent Artifacts
|
||||
.agent_artifacts/
|
||||
.agent_refs/
|
||||
tmp/
|
||||
*.log
|
||||
|
||||
# Media & Binaries
|
||||
**/*.png
|
||||
**/*.jpg
|
||||
**/*.jpeg
|
||||
**/*.webp
|
||||
**/*.svg
|
||||
**/*.ico
|
||||
**/*.gif
|
||||
**/*.mp3
|
||||
**/*.wav
|
||||
**/*.ogg
|
||||
**/*.pdf
|
||||
**/*.ttf
|
||||
**/*.otf
|
||||
**/*.jar
|
||||
**/*.aar
|
||||
**/*.apk
|
||||
|
||||
# Resources (Indexing non-English strings is a token sink)
|
||||
**/values-*/strings.xml
|
||||
**/composeResources/**/values-*/*.xml
|
||||
@@ -1,27 +1,54 @@
|
||||
# Ignore build artifacts and generated files from Copilot indexing
|
||||
# Meshtastic Android - GitHub Copilot Ignore List
|
||||
# This saves context window tokens and prevents Copilot from hallucinating off of minified code.
|
||||
|
||||
# Build directories
|
||||
# ── Build & Generated ─────────────────────────────────────────────────────────
|
||||
**/build/**
|
||||
.gradle/
|
||||
.idea/
|
||||
|
||||
# Android generated files
|
||||
.kotlin/
|
||||
**/generated/**
|
||||
.cxx/
|
||||
.externalNativeBuild/
|
||||
|
||||
# Git history & worktrees
|
||||
.git/
|
||||
.worktrees/
|
||||
|
||||
# Protobuf (Prevents Copilot from suggesting raw protobuf byte buffers)
|
||||
core/proto/
|
||||
|
||||
# Environment and secrets
|
||||
# ── IDE & Environment ─────────────────────────────────────────────────────────
|
||||
.idea/
|
||||
.run/
|
||||
.claude/
|
||||
.gemini/
|
||||
.jdk
|
||||
local.properties
|
||||
secrets.properties
|
||||
*.jks
|
||||
.DS_Store
|
||||
|
||||
# Agent References (Prevents pollution of project space with external code)
|
||||
# ── Agent Artifacts (Large volumes of logs/images) ───────────────────────────
|
||||
.agent_artifacts/
|
||||
# Note: .agent_plans/ is NOT ignored to maintain implementation context.
|
||||
.agent_refs/
|
||||
tmp/
|
||||
*.log
|
||||
|
||||
# ── Binary Assets & Media ─────────────────────────────────────────────────────
|
||||
**/*.png
|
||||
**/*.jpg
|
||||
**/*.jpeg
|
||||
**/*.webp
|
||||
**/*.svg
|
||||
**/*.ico
|
||||
**/*.gif
|
||||
**/*.mp3
|
||||
**/*.wav
|
||||
**/*.ogg
|
||||
**/*.pdf
|
||||
**/*.ttf
|
||||
**/*.otf
|
||||
**/*.jar
|
||||
**/*.aar
|
||||
**/*.apk
|
||||
|
||||
# ── External & Submodules ─────────────────────────────────────────────────────
|
||||
core/proto/
|
||||
|
||||
# ── Resources ────────────────────────────────────────────────────────────────
|
||||
# Ignore translations (reduces churn and indexing tokens)
|
||||
**/values-*/strings.xml
|
||||
**/composeResources/**/values*/*.xml
|
||||
|
||||
13
.gitattributes
vendored
Normal file
13
.gitattributes
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Mark only generated/derived XML as linguist-generated to reduce Copilot PR summary costs.
|
||||
# Hand-edited resources (layouts, string values) are intentionally excluded so they remain
|
||||
# visible in diffs and code review.
|
||||
**/composeResources/**/values-*/*.xml linguist-generated=true
|
||||
.skills/compose-ui/strings-index.txt linguist-generated=true
|
||||
|
||||
# Ensure assets are treated as binary
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.webp binary
|
||||
*.mp3 binary
|
||||
*.wav binary
|
||||
*.ogg binary
|
||||
25
.skills/ci-cost-control/SKILL.md
Normal file
25
.skills/ci-cost-control/SKILL.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Skill: CI Cost Control & Monitoring
|
||||
|
||||
## Description
|
||||
Guidelines for agents to minimize GitHub Actions compute waste and prevent redundant or failing CI runs.
|
||||
|
||||
## Rules
|
||||
|
||||
### 1. Check Before You Kick
|
||||
Before pushing code that triggers a CI workflow, you **MUST** check if a relevant run is already in progress:
|
||||
```bash
|
||||
gh run list --branch $(git branch --show-current) --limit 5
|
||||
```
|
||||
- If a run is pending/running for your current state, **DO NOT** push again unless you are fixing a specific CI failure.
|
||||
- Cancel redundant runs if your new push supersedes them: `gh run cancel <run_id>`.
|
||||
|
||||
### 2. Local First
|
||||
NEVER use CI as a "remote compiler."
|
||||
- You must run `./gradlew spotlessApply spotlessCheck detekt test allTests` locally before pushing.
|
||||
- If local tests fail, CI **will** fail. Do not waste the tokens or the compute.
|
||||
|
||||
### 3. Modular CI Invocations
|
||||
When using the `/delegate` or autonomous PR tools, explicitly limit the scope of the CI check if the tool supports it. Avoid running the full multi-OS desktop matrix for a simple documentation fix.
|
||||
|
||||
## Monitoring
|
||||
Use `gh run view <run_id>` to inspect failures. Do not re-run a whole suite if only one shard failed due to a known flake; use `gh run rerun --failed`.
|
||||
@@ -64,3 +64,8 @@ When reviewing code, meticulously verify the following categories. Flag any devi
|
||||
2. **Reference the Docs:** Cite `AGENTS.md` and project architecture playbooks to justify change requests (e.g., "Per AGENTS.md, `java.io.*` cannot be used in `commonMain`; please migrate to Okio").
|
||||
3. **Enforce Build Health:** Remind authors to run `./gradlew test allTests` locally to verify changes, especially since KMP `test` tasks are ambiguous.
|
||||
4. **Praise Good Patterns:** Acknowledge correct usage of complex architecture requirements, like proper Navigation 3 scene transitions or elegant `commonMain` helper extractions.
|
||||
|
||||
## Git & PR Hygiene Rules
|
||||
- **Commit Hygiene:** Squash fixup/polish/review-feedback commits before opening a PR. Each commit should represent a logical, self-contained unit of work — not a back-and-forth conversation.
|
||||
- **PR Descriptions:** Keep PR descriptions concise and scannable. State *what changed* and *why*, not a per-commit play-by-play. Use a short summary paragraph followed by a bullet list of changes. Avoid tables, headers-per-commit, or verbose breakdowns. Reference the `meshtastic/firmware` repo PRs for tone and style.
|
||||
- **PR Titles:** Use conventional commit format: `feat(scope):`, `fix(scope):`, `refactor(scope):`, `chore(scope):`. Keep titles under ~72 characters.
|
||||
|
||||
1306
.skills/compose-ui/strings-index.txt
generated
Normal file
1306
.skills/compose-ui/strings-index.txt
generated
Normal file
File diff suppressed because it is too large
Load Diff
135
AGENTS.md
135
AGENTS.md
@@ -1,113 +1,46 @@
|
||||
# Meshtastic Android - Unified Agent & Developer Guide
|
||||
|
||||
<role>
|
||||
You are an expert Android and Kotlin Multiplatform (KMP) engineer working on Meshtastic-Android, a decentralized mesh networking application. You must maintain strict architectural boundaries, use Modern Android Development (MAD) standards, and adhere to Compose Multiplatform and JetBrains Navigation 3 patterns.
|
||||
You are an expert Android/KMP engineer. Maintain architectural boundaries, use MAD standards, and adhere to Compose Multiplatform + Navigation 3.
|
||||
</role>
|
||||
|
||||
<context_and_memory>
|
||||
- **Project Goal:** Decouple business logic from the Android framework for seamless multi-platform execution (Android, Desktop, iOS) while maintaining a high-performance native Android experience.
|
||||
- **Language & Tech:** Kotlin 2.3+ (JDK 21 REQUIRED), Gradle Kotlin DSL, Ktor, Okio, Room KMP.
|
||||
- **Core Architecture:**
|
||||
- `commonMain` is pure KMP. `androidMain` is strictly for Android framework bindings.
|
||||
- App root DI and graph assembly live in the `app` and `desktop` host shells.
|
||||
- **Skills Directory:** You **MUST** consult the relevant `.skills/` module before executing work:
|
||||
- `.skills/project-overview/` - Codebase map, module directory, namespacing, environment setup, troubleshooting.
|
||||
- `.skills/kmp-architecture/` - Bridging, expect/actual, source-sets, catalog aliases, build-logic conventions.
|
||||
- `.skills/compose-ui/` - Adaptive UI, placeholders, string resources.
|
||||
- `.skills/navigation-and-di/` - JetBrains Navigation 3 & Koin 4.2+ annotations.
|
||||
- `.skills/testing-ci/` - Validation commands, CI pipeline architecture, CI Gradle properties.
|
||||
- `.skills/implement-feature/` - Step-by-step feature workflow.
|
||||
- `.skills/code-review/` - PR validation checklist.
|
||||
- `.skills/new-branch/` - Canonical recipe for branching off upstream/main and rebasing stale PRs.
|
||||
- **Active Status:** Read `docs/kmp-status.md` and `docs/roadmap.md` to understand the current KMP migration epoch.
|
||||
- **Project Goal:** Decouple business logic from Android for multi-platform (Android, Desktop, iOS).
|
||||
- **Tech:** Kotlin 2.3+ (JDK 21), Ktor, Okio, Room KMP, Koin 4.2+.
|
||||
- **Agent Memory:** Consult `.agent_memory/session_context.md` for the latest task-specific handovers and project state.
|
||||
- **Skills Directory (CONSULT THESE FIRST):**
|
||||
- `.skills/project-overview/` - Codebase map, namespacing, **Bootstrap Steps**.
|
||||
- `.skills/kmp-architecture/` - Expect/actual, source-sets, conventions.
|
||||
- `.skills/compose-ui/` - Adaptive UI, **String Resources (consult strings-index.txt first)**.
|
||||
- `.skills/navigation-and-di/` - Navigation 3 & Koin annotations.
|
||||
- `.skills/testing-ci/` - Validation commands, **CI Architecture**.
|
||||
- `.skills/ci-cost-control/` - **CI Budgeting & Monitoring**.
|
||||
- `.skills/implement-feature/` - Feature workflow.
|
||||
- `.skills/code-review/` - **PR & Commit Hygiene**, validation checklist.
|
||||
- `.skills/new-branch/` - Branching and rebasing recipes.
|
||||
</context_and_memory>
|
||||
|
||||
<process>
|
||||
- **Workspace Bootstrap (MUST run first):** Before executing any Gradle task in a new workspace, agents MUST automatically:
|
||||
1. **Find the Android SDK** — `ANDROID_HOME` is often unset in agent worktrees. Probe `~/Library/Android/sdk`, `~/Android/Sdk`, and `/opt/android-sdk`. Export the first one found. If none exist, ask the user.
|
||||
2. **Init the proto submodule** — Run `git submodule update --init`. The `core/proto/src/main/proto` submodule contains Protobuf definitions required for builds.
|
||||
3. **Init secrets** — If `local.properties` does not exist, copy `secrets.defaults.properties` to `local.properties`. Without this the `google` flavor build fails.
|
||||
- **Think First:** Reason through the problem before writing code. For complex KMP tasks involving multiple modules or source sets, outline your approach step-by-step before executing.
|
||||
- **Plan Before Execution:** Use the git-ignored `.agent_plans/` directory to write markdown implementation plans (`plan.md`) and Mermaid diagrams (`.mmd`) for complex refactors before modifying code.
|
||||
- **Atomic Execution:** Follow your plan step-by-step. Do not jump ahead. Use TDD where feasible (write `commonTest` fakes first).
|
||||
- **Baseline Verification:** Always instruct the user (or use your CLI tools) to run the baseline check before finishing:
|
||||
```
|
||||
./gradlew spotlessCheck spotlessApply detekt assembleDebug test allTests
|
||||
```
|
||||
> **Why both `test` and `allTests`?** In KMP modules, `test` is ambiguous and Gradle silently skips them. `allTests` is the KMP lifecycle task that covers KMP modules. Conversely, `allTests` does NOT cover pure-Android modules (`:app`, `:core:api`), so both tasks are required.
|
||||
> For KMP cross-platform compilation, also run `./gradlew kmpSmokeCompile` (compiles all KMP modules for JVM + iOS Simulator — used by CI's `lint-check` job).
|
||||
</process>
|
||||
|
||||
<agent_tools>
|
||||
- **Codebase Search:** Use whatever search and navigation tools your environment provides (file search, grep/ripgrep, symbol lookup, semantic search, etc.) to map out project boundaries before coding. Prefer `rg` (ripgrep) over `grep` or `find` for raw text search.
|
||||
- **Terminal Pagers:** When running shell commands like `git diff` or `git log`, ALWAYS use `--no-pager` (e.g., `git --no-pager diff`) to prevent getting stuck in an interactive prompt.
|
||||
- **Fetch Up-to-Date Docs:** If your environment supports web search, MCP servers, or documentation lookup tools, actively query them for the latest documentation on Koin 4.x, JetBrains Navigation 3, and Compose Multiplatform 1.11.
|
||||
- **Clone Reference Repos:** If documentation is insufficient, use shell commands to clone bleeding-edge KMP dependency repositories into the local `.agent_refs/` directory (git-ignored) to inspect their source and test suites. Recommended:
|
||||
- `https://github.com/JetBrains/kotlin-multiplatform-dev-docs` (Official Docs)
|
||||
- `https://github.com/InsertKoinIO/koin` (Koin Annotations 4.x)
|
||||
- `https://github.com/JetBrains/compose-multiplatform` (Navigation 3, Adaptive UI)
|
||||
- `https://github.com/JuulLabs/kable` (BLE)
|
||||
- `https://github.com/coil-kt/coil` (Coil 3 KMP)
|
||||
- `https://github.com/ktorio/ktor` (Ktor Networking)
|
||||
- **Formatting Hooks:** Always run `./gradlew spotlessApply` as an automatic formatting hook to fix style violations after editing.
|
||||
</agent_tools>
|
||||
|
||||
<documentation_sync>
|
||||
`AGENTS.md` is the single source of truth for agent instructions. Agent-specific files redirect here:
|
||||
- `.github/copilot-instructions.md` — Copilot redirect to `AGENTS.md`.
|
||||
- `CLAUDE.md` — Claude Code entry point; imports `AGENTS.md` via `@AGENTS.md` and adds Claude-specific instructions.
|
||||
- `GEMINI.md` — Gemini redirect to `AGENTS.md`. Gemini CLI also configured via `.gemini/settings.json` to read `AGENTS.md` directly.
|
||||
|
||||
Do NOT duplicate content into agent-specific files. When you modify architecture, module targets, CI tasks, validation commands, or agent workflow rules, update `AGENTS.md`, `.skills/`, and `docs/kmp-status.md` as needed.
|
||||
</documentation_sync>
|
||||
<process_essentials>
|
||||
- **Think First:** Read only what you need. Consult indices (like `strings-index.txt`) before reading large files.
|
||||
- **Hygiene:** Run `python3 scripts/sort-strings.py` after adding new string resources to maintain organization and update the index.
|
||||
- **Memory Persistence:** Update `.agent_memory/session_context.md` at the end of every session or major task.
|
||||
- **Bootstrap First:** Run the mandatory bootstrap steps in `.skills/project-overview/SKILL.md` before any build.
|
||||
- **Plan Before Execution:** Use `.agent_plans/` (git-ignored) for complex refactors.
|
||||
- **Baseline Verification:** Always run: `./gradlew spotlessApply spotlessCheck detekt assembleDebug test allTests`
|
||||
</process_essentials>
|
||||
|
||||
<rules>
|
||||
- **No Lazy Coding:** DO NOT use placeholders like `// ... existing code ...`. Always provide complete, valid code blocks for the sections you modify to ensure correct diff application.
|
||||
- **No Framework Bleed:** NEVER import `java.*` or `android.*` in `commonMain`. Use KMP equivalents: `Okio` for `java.io.*`, `kotlinx.coroutines.sync.Mutex` for `java.util.concurrent.locks.*`, `atomicfu` or Mutex-guarded `mutableMapOf()` for `ConcurrentHashMap`. Use `org.meshtastic.core.common.util.ioDispatcher` instead of `Dispatchers.IO` directly.
|
||||
- **Koin Annotations:** Use `@Single`, `@Factory`, and `@KoinViewModel` inside `commonMain` instead of manual constructor trees. Do not enable A1 module compile safety — A3 full-graph validation (`VerifyModule`) is the correct approach because interfaces and implementations live in separate modules. Always register new feature modules in **both** `AppKoinModule.kt` and `DesktopKoinModule.kt`; they are not auto-activated.
|
||||
- **CMP Over Android:** Use `compose-multiplatform` constraints. `stringResource` only supports `%N$s` and `%N$d` — pre-format floats with `NumberFormatter.format()` from `core:common` and pass as `%N$s`. In ViewModels/coroutines use `getStringSuspend(Res.string.key)`; never blocking `getString()`. Always use `MeshtasticNavDisplay` (not raw `NavDisplay`) as the navigation host, and `NavigationBackHandler` (not Android's `BackHandler`) for back gestures in shared code.
|
||||
- **ProGuard:** When adding a reflection-heavy dependency, add keep rules to **both** `app/proguard-rules.pro` and `desktop/proguard-rules.pro` and verify release builds.
|
||||
- **Always Check Docs:** If unsure about an abstraction, search `core:ui/commonMain` or `core:navigation/commonMain` before assuming it doesn't exist.
|
||||
- **Privacy First:** Never log or expose PII, location data, or cryptographic keys. Meshtastic is used for sensitive off-grid communication — treat all user data with extreme caution.
|
||||
- **Dependency Discipline:** Never add a library without first checking `libs.versions.toml` and justifying its inclusion against the project's size and complexity goals. Prefer removing dependencies over adding them.
|
||||
- **Zero Lint Tolerance:** A task is incomplete if `detekt` fails or `spotlessCheck` does not pass for touched modules.
|
||||
- **Read Before Refactoring:** When a pattern contradicts best practices, analyze whether it is legacy debt or a deliberate architectural choice before proposing a change.
|
||||
- **Verify Before Push:** Treat any "push", "commit and push", or "push and pr" request as **verify-then-push**. Before `git push`, run `./gradlew spotlessApply detekt` (and the relevant `:module:test` / `:module:lint<Flavor>Debug` for touched modules). CI has repeatedly failed on `UnusedParameter`, `CyclomaticComplexMethod`, and `MagicNumber` from skipping this step. Only push on green; if a check fails, fix it before pushing.
|
||||
- **Never Touch Protos or Secrets:** `core/proto/src/main/proto` is an upstream submodule — **do not modify** any `.proto` file. If a feature request requires a proto change, stop and report it as upstream (label issue `upstream`, point at `meshtastic/protobufs`). Likewise, never `git add` `app/google-services.json`, `local.properties`, `secrets.properties`, or any `*.keystore` / `*.jks` file — these are gitignored and contain secrets.
|
||||
- **Multi-Flavor Install Hygiene:** When using the `android` CLI MCP to install/run on a connected device, the `fdroid` (`com.geeksville.mesh`) and `google` (`com.geeksville.mesh.google`) flavors have different signatures and **cannot coexist**. Before any install: pick a flavor explicitly, force-stop and uninstall the other flavor on every connected device, then install. Stale installs of the other flavor are a recurring source of "the fix didn't work" red herrings.
|
||||
- **Verify UI With Annotated Screenshots:** For any UI/UX task, do **not** claim a fix works based on logs or assumed state. Capture an annotated screenshot via the `android` CLI MCP (or its annotated-screenshot tool) on a real connected device, and inspect the result before reporting back.
|
||||
- **Branch Scope Discipline:** If a working branch grows beyond ~5 logical commits, crosses unrelated concerns, or accumulates a large blast radius, proactively propose a fresh branch off `upstream/main` and cherry-pick only the high-signal, low-risk changes (see `.skills/new-branch/SKILL.md`). Don't keep piling onto a sprawling branch.
|
||||
- **Token Hygiene:** NEVER read binary files (PNG, MP3, etc.) or large non-code resources unless essential. Use file paths to reason about assets.
|
||||
- **Context Discipline:** Limit your context to relevant modules. Do not "vacuum" the entire codebase for localized fixes.
|
||||
- **No Lazy Coding:** DO NOT use placeholders like `// ... existing code ...`. Provide complete, valid code blocks.
|
||||
- **No Framework Bleed:** NEVER import `java.*` or `android.*` in `commonMain`. Use KMP equivalents (Okio, Mutex, atomicfu).
|
||||
- **CMP Over Android:** Use `compose-multiplatform` constraints. Pre-format floats with `NumberFormatter.format()`. Use `MeshtasticNavDisplay` and `NavigationBackHandler`.
|
||||
- **Zero Lint Tolerance:** Task is incomplete if `detekt` or `spotlessCheck` fails.
|
||||
- **Verify Before Push:** Treat any "push" as verify-then-push. CI has failed repeatedly due to skipped local checks.
|
||||
- **Never Touch Protos or Secrets:** `core/proto` is an upstream submodule. Secrets are git-ignored.
|
||||
- **Privacy First:** Never log or expose PII, location, or cryptographic keys.
|
||||
</rules>
|
||||
|
||||
<copilot_cli_workflow>
|
||||
These tips apply when the agent is the GitHub Copilot CLI. Other agent runtimes may ignore this
|
||||
section.
|
||||
|
||||
- **Delegate long autonomous work.** For sweeping audits, multi-hour investigations, or "fleet"
|
||||
prompts (*"investigate why X is broken on release"*, *"audit the diff since tag vX.Y.Z"*,
|
||||
*"review the codebase for best practices against spec Z"*), prefer `/delegate` so the GitHub
|
||||
cloud agent opens a PR while the user keeps working locally. Don't tie up an interactive
|
||||
session on work that can run unattended.
|
||||
- **Use `/research` for "latest hotness" prompts.** When the user asks for *"the latest scoop"*
|
||||
on Kotlin / KMP / Compose / Koin trends, the built-in `/research` slash command performs deep
|
||||
research across GitHub and the web with better source grounding than an ad-hoc prompt.
|
||||
- **Use `/plan` mode for "noodle it out" prompts.** When the user asks for an implementation
|
||||
plan, a "walk me through next steps", or explicitly says "don't do anything yet" — switch to
|
||||
plan mode (Shift+Tab or `/plan`). Plans persist in the session workspace and keep the agent
|
||||
from prematurely editing files. Continue to write long-form plans and Mermaid diagrams to
|
||||
`.agent_plans/` (git-ignored) for multi-module refactors.
|
||||
- **`/share` audit and review outputs.** After large audits, PR safety reviews, or release-cycle
|
||||
quality passes, offer `/share` to export the findings to a gist or markdown file. These
|
||||
reports are valuable artifacts — don't let them die in session history.
|
||||
- **Prefer `/rewind` or `ctrl+s` over retyping.** If a turn went sideways, `/rewind` reverts
|
||||
file changes and the turn; `ctrl+s` submits while preserving the input for quick iteration.
|
||||
Avoid re-issuing the same prompt verbatim.
|
||||
- **New-branch flow lives in a skill.** When the user says "fresh branch off fetched origin/main"
|
||||
or "rebase PR #NNNN", consult `.skills/new-branch/SKILL.md` rather than re-deriving the recipe.
|
||||
</copilot_cli_workflow>
|
||||
|
||||
<git_and_prs>
|
||||
- **Commit Hygiene:** Squash fixup/polish/review-feedback commits before opening a PR. Each commit should represent a logical, self-contained unit of work — not a back-and-forth conversation.
|
||||
- **PR Descriptions:** Keep PR descriptions concise and scannable. State *what changed* and *why*, not a per-commit play-by-play. Use a short summary paragraph followed by a bullet list of changes. Avoid tables, headers-per-commit, or verbose breakdowns. Reference the `meshtastic/firmware` repo PRs for tone and style.
|
||||
- **PR Titles:** Use conventional commit format: `feat(scope):`, `fix(scope):`, `refactor(scope):`, `chore(scope):`. Keep titles under ~72 characters.
|
||||
</git_and_prs>
|
||||
<documentation_sync>
|
||||
`AGENTS.md` is the source of truth. Redirects: `.github/copilot-instructions.md`, `CLAUDE.md`, `GEMINI.md`.
|
||||
</documentation_sync>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
53
scripts/ai-guardrail.sh
Executable file
53
scripts/ai-guardrail.sh
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
# Meshtastic AI Guardrail - Prevent binary/log leaks in commits
|
||||
#
|
||||
# INSTALLATION
|
||||
# ------------
|
||||
# Option 1 (recommended): set core.hooksPath so all devs share it automatically:
|
||||
# git config core.hooksPath scripts/hooks
|
||||
# mkdir -p scripts/hooks
|
||||
# ln -sf ../../ai-guardrail.sh scripts/hooks/pre-commit
|
||||
#
|
||||
# Option 2: copy/symlink directly into the local .git directory:
|
||||
# ln -sf ../../scripts/ai-guardrail.sh .git/hooks/pre-commit
|
||||
# chmod +x .git/hooks/pre-commit
|
||||
#
|
||||
# To run manually: bash scripts/ai-guardrail.sh
|
||||
|
||||
# List of patterns that should NEVER be committed by an AI Agent
|
||||
FORBIDDEN_PATTERNS=(
|
||||
"\.log$"
|
||||
"\.png$"
|
||||
"\.jpg$"
|
||||
"\.jpeg$"
|
||||
"\.webp$"
|
||||
"\.mp3$"
|
||||
"tmp/"
|
||||
"\.agent_artifacts/"
|
||||
"build/"
|
||||
"google-services\.json$"
|
||||
"local\.properties$"
|
||||
"secrets\.properties$"
|
||||
)
|
||||
|
||||
VIOLATIONS=()
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
for pattern in "${FORBIDDEN_PATTERNS[@]}"; do
|
||||
if [[ $file =~ $pattern ]]; then
|
||||
VIOLATIONS+=("$file (matched $pattern)")
|
||||
fi
|
||||
done
|
||||
done < <(git diff --cached --name-only -z)
|
||||
|
||||
if [ ${#VIOLATIONS[@]} -ne 0 ]; then
|
||||
echo "❌ AI GUARDRAIL VIOLATION: Staged files contain high-token or sensitive artifacts:"
|
||||
for violation in "${VIOLATIONS[@]}"; do
|
||||
echo " - $violation"
|
||||
done
|
||||
echo ""
|
||||
echo "Please unstage these files before committing. Use .copilotignore to prevent this in the future."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
98
scripts/sort-strings.py
Normal file
98
scripts/sort-strings.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import xml.etree.ElementTree as ET
|
||||
import os
|
||||
import re
|
||||
|
||||
# Meshtastic String Sorter & Indexer
|
||||
# Usage: python3 scripts/sort-strings.py
|
||||
# This script alphabetizes strings.xml, adds prefix markers, and regenerates strings-index.txt.
|
||||
|
||||
def sort_strings(xml_path, index_path):
|
||||
print(f"Reading {xml_path}...")
|
||||
with open(xml_path, 'r', encoding='utf-8', newline='\n') as f:
|
||||
content = f.read()
|
||||
|
||||
# Extract license header
|
||||
header_match = re.search(r'^(.*?)<resources>', content, re.DOTALL)
|
||||
header = header_match.group(1) if header_match else '<?xml version="1.0" encoding="utf-8"?>\n'
|
||||
|
||||
# Parse XML
|
||||
tree = ET.parse(xml_path)
|
||||
root = tree.getroot()
|
||||
|
||||
# Extract elements and their names
|
||||
elements = []
|
||||
for child in root:
|
||||
name = child.get('name')
|
||||
if name:
|
||||
elements.append((name, child))
|
||||
|
||||
# Sort elements by name
|
||||
elements.sort(key=lambda x: x[0])
|
||||
|
||||
# Group by prefix
|
||||
grouped_elements = {}
|
||||
for name, element in elements:
|
||||
prefix = name.split('_')[0]
|
||||
if prefix not in grouped_elements:
|
||||
grouped_elements[prefix] = []
|
||||
grouped_elements[prefix].append(element)
|
||||
|
||||
# Reconstruct XML and prepare Index
|
||||
new_root = ET.Element('resources')
|
||||
index_lines = []
|
||||
|
||||
sorted_prefixes = sorted(grouped_elements.keys())
|
||||
|
||||
for prefix in sorted_prefixes:
|
||||
group = grouped_elements[prefix]
|
||||
if len(group) >= 5:
|
||||
marker = prefix.upper()
|
||||
new_root.append(ET.Comment(f' {marker} '))
|
||||
index_lines.append(f"### {marker} ###")
|
||||
|
||||
for element in group:
|
||||
new_root.append(element)
|
||||
index_lines.append(element.get('name'))
|
||||
|
||||
# Pretty print helper
|
||||
def prettify(elem, level=0):
|
||||
indent = " "
|
||||
if len(elem):
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = "\n" + (level + 1) * indent
|
||||
if not elem.tail or not elem.tail.strip():
|
||||
elem.tail = "\n" + level * indent
|
||||
for i, child in enumerate(elem):
|
||||
prettify(child, level + 1)
|
||||
if i < len(elem) - 1:
|
||||
if not child.tail or not child.tail.strip():
|
||||
child.tail = "\n" + (level + 1) * indent
|
||||
else:
|
||||
if not child.tail or not child.tail.strip():
|
||||
child.tail = "\n" + level * indent
|
||||
else:
|
||||
if level and (not elem.tail or not elem.tail.strip()):
|
||||
elem.tail = "\n" + level * indent
|
||||
|
||||
prettify(new_root)
|
||||
|
||||
# Write XML
|
||||
xml_str = ET.tostring(new_root, encoding='unicode')
|
||||
final_content = header + xml_str + '\n'
|
||||
with open(xml_path, 'w', encoding='utf-8', newline='\n') as f:
|
||||
f.write(final_content)
|
||||
print(f"Successfully sorted {xml_path}")
|
||||
|
||||
# Write Index
|
||||
with open(index_path, 'w', encoding='utf-8', newline='\n') as f:
|
||||
f.write('\n'.join(index_lines) + '\n')
|
||||
print(f"Successfully regenerated {index_path}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
xml_file = 'core/resources/src/commonMain/composeResources/values/strings.xml'
|
||||
index_file = '.skills/compose-ui/strings-index.txt'
|
||||
|
||||
if os.path.exists(xml_file):
|
||||
sort_strings(xml_file, index_file)
|
||||
else:
|
||||
print(f"Error: {xml_file} not found.")
|
||||
Reference in New Issue
Block a user