From 265b1fdf2b68be571af4b78cbe0f26b30152ba24 Mon Sep 17 00:00:00 2001 From: Istvan Docsa Date: Tue, 8 Sep 2026 23:43:01 +0200 Subject: [PATCH 1/2] docs: share agent instructions across clients --- AGENTS.md | 12 + CLAUDE.md | 1 + docs/agents/org-rules/linear-surfaces.md | 129 ++++++++++ docs/agents/org-rules/linear.md | 85 +++++++ docs/agents/org-rules/tool-usage.md | 24 ++ docs/agents/organization.md | 308 +++++++++++++++++++++++ 6 files changed, 559 insertions(+) create mode 100644 AGENTS.md create mode 120000 CLAUDE.md create mode 100644 docs/agents/org-rules/linear-surfaces.md create mode 100644 docs/agents/org-rules/linear.md create mode 100644 docs/agents/org-rules/tool-usage.md create mode 100644 docs/agents/organization.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..5367cd5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,12 @@ +# Shared instructions + +Before doing any work, read `docs/agents/organization.md` and +`docs/agents/org-rules/tool-usage.md` in full. These checked-in snapshots make +organization guidance available in standalone clones and worktrees. Before +changing Linear work, also read `docs/agents/org-rules/linear.md`. +Repository-specific instructions below take precedence for this repository. +All paths in this entrypoint and its repository reference are repo-root relative. + +# simulation-github-action + +Read `README.md` and the relevant build/configuration files before changing this repository. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/docs/agents/org-rules/linear-surfaces.md b/docs/agents/org-rules/linear-surfaces.md new file mode 100644 index 0000000..d68a9a0 --- /dev/null +++ b/docs/agents/org-rules/linear-surfaces.md @@ -0,0 +1,129 @@ +# Linear surfaces — the derived copies + +Maintained in `linro-io/linro-io` at `docs/agents/org-rules/linear-surfaces.md`. +In other repositories this is a generated snapshot: update the metarepo source +and refresh with its `bin/sync-agent-guidance`; do not edit the copy independently. + +`docs/agents/org-rules/linear.md` is canonical. This file holds the **exact text** of +the copies that live inside Linear, so a change to the convention is one diff +covering the rule and its copies instead of a rule change plus a promise to +update Linear later. + +Linear's API is **read-only** for agent skills and templates (`list_` and +`get_` exist; there is no `save_`), so each of these is pasted once by a human. +When this file changes, re-paste the block that changed. + +--- + +## 1. Linear Agent Skill — "Issue handling" + +**Where:** Linear → Settings → Agents → Skills → New skill. Name it +`Issue handling`. + +**Why it exists:** it reaches agents on any machine, including ones that never +open the meta repo. Keep it short — it is a pointer with enough substance to be +useful when the repo is not to hand. + +```markdown +How work is tracked in this workspace. The full convention lives in +`docs/agents/org-rules/linear.md` in the linro-io/linro-io meta repo; this is the +short version for when that is not to hand. + +**There is no "epic".** The hierarchy is Initiative → Project → Project +Milestone → Issue → sub-issue. Do not file a parent issue titled `Epic: …`: +it is never meaningfully done, and it duplicates what a project already holds. + +**A workstream is a Project.** Its phases are **Project Milestones**, and every +milestone description states its **gate** — the observable condition that must +hold before the next phase starts. A phase with no gate is a label. + +**Sequencing is blocking relations** (`blocks` / `blockedBy`). Parent/sub-issue +means containment, never order — a tree cannot say "this gates everything +downstream". Sub-issues are for decomposing one issue into parts. + +**Every issue carries** the problem with evidence (`file:line`, an error +string, a measured number — not a restatement of the title), acceptance +criteria, and a *not in scope* line wherever the boundary is load-bearing. + +**Titles say what the change is.** No phase prefixes (`M0 — …`): the phase +lives in the milestone, and a prefix duplicates it and then drifts from it. + +**Before filing, look for an existing ticket.** Link or comment on it rather +than filing a near-duplicate. If an old ticket's design is superseded, say so +in a comment on it. + +**Cancel, never delete.** Deleting breaks every reference from other issues, +comments and PR bodies. Cancel with a pointer to whatever superseded it. + +Branch names come from Linear's `gitBranchName`, so PRs link themselves. +Move to In Review when the PR opens; Done when merged — and, where reaching an +environment is what makes it true, when deployed. +``` + +--- + +## 2. Issue template — Engineering + +**Where:** Linear → Settings → Teams → Engineering → Templates → New issue +template. Name it `Issue`, and set it as the team default so it appears +without being chosen. + +```markdown +## The problem + + + +## Acceptance + + + +## Not in scope + + +``` + +--- + +## 3. Project template — Engineering + +**Where:** Linear → Settings → Teams → Engineering → Templates → New project +template. Name it `Workstream`. + +Linear project templates carry a description and can pre-create milestones. +Create the description below, plus milestone placeholders `M0 · …` through +`M2 · …` (add or delete phases per workstream — the point is that each one +prompts for its gate). + +```markdown +## The problem + + + +## The shape of the fix + + + +## Decisions taken + + + +## Alternatives rejected + + + +## Milestones + + +``` + +--- + +## Keeping these in sync + +The rule file and this file change in the same PR. After merging, re-paste any +block that changed — there is no API to do it for you, and a copy that has +drifted is worse than no copy, because it is quoted with confidence. diff --git a/docs/agents/org-rules/linear.md b/docs/agents/org-rules/linear.md new file mode 100644 index 0000000..5700fbe --- /dev/null +++ b/docs/agents/org-rules/linear.md @@ -0,0 +1,85 @@ +# Linear + +Maintained in `linro-io/linro-io` at `docs/agents/org-rules/linear.md`. +In other repositories this is a generated snapshot: update the metarepo source +and refresh with its `bin/sync-agent-guidance`; do not edit the copy independently. + +How work is tracked. **This file is canonical.** Three derived copies exist so +the convention reaches surfaces the repo cannot: + +| Copy | Reaches | Source | +|---|---|---| +| Linear Agent Skill "Issue handling" | agents on any machine, including ones that never open this repo | `linear-surfaces.md` | +| Engineering issue + project templates | humans and anything creating work in the Linear UI | `linear-surfaces.md` | +| `.claude/skills/file-workstream/` | the multi-ticket procedure, where the traps are | that skill | + +**Change this file first, and update the copies in the same PR.** Three +independent copies of a convention drift — that is exactly how this workspace +ended up with three competing definitions of "epic". + +The two Linear-side copies are pasted by hand: Linear's API is read-only for +agent skills and templates (`list_` / `get_`, no `save_`). Their exact text +lives in `linear-surfaces.md` in this directory, so the copy travels in the +same diff as the rule and re-pasting is mechanical. + +## There is no "epic" + +Linear has no epic object. The hierarchy is **Initiative → Project → Project +Milestone → Issue → sub-issue**. "Epic" is Jira vocabulary; filing one as a +parent issue titled `Epic: …` produces a permanent Backlog issue that is never +meaningfully done, a breadcrumb on every child pointing at a stub, and a second +container duplicating what a project already holds. + +## Shape of a workstream + +- **Project** — the workstream. Holds the write-up, the artifacts and links, a + lead, a start and target date. Note that this workspace's projects mix + long-lived *areas* (API, Frontend, Plugins, Infrastructure, Core Data + Platform) with real *efforts* (PII Data Scrubbing, Marketplace v1, Estate + Enrollment). A new workstream is an effort; do not file one under an area. +- **Project Milestones** — the phases. **Every milestone description carries + its gate**: the observable condition that must hold before the next phase + starts. A phase with no gate is a label, not a milestone. +- **Blocking relations** (`blocks` / `blockedBy`) — sequencing. This is the + only thing that expresses order. +- **Sub-issues** — genuine decomposition of one issue into parts. Never an epic + stand-in. + +**Parent/sub-issue means containment, never order.** A tree cannot say "M1 +gates everything downstream"; a blocking relation can, and it shows on both +issues. + +## Anatomy of an issue + +Every issue carries: + +- **The problem**, with evidence — `file:line`, an error string, a measured + number. Not a restatement of the title. +- **Acceptance criteria** — what is observably true when it is done. +- **Not in scope**, wherever the boundary is load-bearing. This is what stops a + guard ticket quietly becoming a rewrite. + +Titles say what the change is. **No phase prefixes** (`M0 — …`): the phase lives +in the milestone, and a title prefix duplicates it and then drifts from it. + +## Lifecycle + +- **Before filing, look for an existing ticket.** Link or comment on it rather + than filing a near-duplicate; if an old ticket's design is superseded, say so + in a comment on that ticket. +- Branch names come from Linear's `gitBranchName` (`istvandocsa/eng-627-…`), so + the PR links itself to the issue. Do not invent your own. +- **In Review** when the PR opens. **Done** when it is merged — and, for + anything that has to reach an environment to be true, when it is deployed. +- **Cancel, never delete.** A deleted issue breaks every reference to it from + other issues, comments and PR bodies. Cancel it with a pointer to whatever + superseded it. + +## Traps, learned the hard way + +- A parent issue looks like an epic and encodes nothing. If you catch yourself + explaining the sequencing in prose, you wanted blocking relations. +- Structure encoded in a title (a phase prefix, a numbered option) becomes a + second source of truth the moment the real field exists. +- A convention nobody can see at the point of creation decays. That is what the + issue template is for; keep it in sync with this file. diff --git a/docs/agents/org-rules/tool-usage.md b/docs/agents/org-rules/tool-usage.md new file mode 100644 index 0000000..a3c0303 --- /dev/null +++ b/docs/agents/org-rules/tool-usage.md @@ -0,0 +1,24 @@ +# Tool Usage + +Maintained in `linro-io/linro-io` at `docs/agents/org-rules/tool-usage.md`. +In other repositories this is a generated snapshot: update the metarepo source +and refresh with its `bin/sync-agent-guidance`; do not edit the copy independently. + +Use safe, purpose-built CLI tools for searching and file discovery. Never fall back to legacy commands. + +## Search + +- Always use `rg` (ripgrep) instead of `grep` for all text searching +- Use `rg --type` to scope searches by language (e.g., `rg --type go`) +- Use `rg --json` when structured output is needed + +## File Discovery + +- Always use `fd` instead of `find` for all file discovery +- Use `fd --extension` to filter by file type (e.g., `fd --extension tf`) + +## Security + +- Never use `find -exec`, `find -delete`, or `find -ok` +- Never use `xargs` or shell pipes that execute commands +- Never use `grep` directly — `rg` is always available and preferred diff --git a/docs/agents/organization.md b/docs/agents/organization.md new file mode 100644 index 0000000..ddcb6da --- /dev/null +++ b/docs/agents/organization.md @@ -0,0 +1,308 @@ +# Linro + +Maintained in `linro-io/linro-io` at `docs/agents/organization.md`. +In other repositories this is a generated snapshot: update the metarepo source +and refresh with its `bin/sync-agent-guidance`; do not edit the copy independently. + +Cloud inventory and security enforcement platform -- discovers cloud resources, stores them in a columnar data pipeline, and evaluates security checks against the inventory. + +In the metarepo, each repository sub-directory is an independently cloned Git repository. Before working in another repository, read its `AGENTS.md` (or `CLAUDE.md` during rollout). Repository names and cross-repo paths below are relative to the metarepo checkout, not this document or a standalone child clone. In a standalone clone or isolated worktree, locate the owning repository explicitly; never assume `../` contains it. + +## Cross-Repo Data Flow + +Protobuf definitions in `idl/` are the source of truth. Generation targets in `idl/` produce `.proto` files in `api/` (public) and `api-internal/` (internal), Go bindings in `api-go/` / `api-internal-go/`, and TypeScript types in `api-ts/` / `api-internal-ts/`. Generated repos are auto-built from `idl/` commits — never edit them by hand. + +``` +idl/ (protos) ──make gen──▶ api/, api-internal/ (generated .proto) + api-go/, api-internal-go/ ──go module──▶ service/, agent/, plugin-* + api-ts/, api-internal-ts/ ──npm──▶ app-frontend/ + + local-dev/ ──tilt──▶ infra + selected products +``` + +`local-dev/` runs one Tilt session, scoped by two orthogonal choices: + +- **run mode** — *where*: `local` (laptop, Docker Desktop) or `coder` (a remote + workspace on k3d). Detected, then verified against the cluster you are + actually pointed at. +- **stack** — *what*: `infra` | `linro` | `summoner` | `full`. + +`cd local-dev && make dev` is the front door; `make doctor` says what is wrong +before a forty-minute build rather than during one. See `local-dev/AGENTS.md`. + +**`cd local-dev && make guide`** opens `local-dev/docs/local-development.html` +— the single human-facing reference for local development on both legs: +addresses, stacks, the Coder bootstrap, code structure, commands. It is +hand-maintained, so any PR that changes a mode, a stack, an address, the +workspace bootstrap or the command surface updates it too. + +`linro-coder/` holds the remote half: the GCP estate that runs Coder and the +workspace template developers build from. A workspace is one VM running this +same Tilt stack, tailnet-only, on its own hostname with its own Let's Encrypt +certificate. It provisions **no credentials** — deliberately, since the box +runs agents over arbitrary code. See `linro-coder/AGENTS.md`, and note the one +invariant that bites: a terragrunt unit's state key is its directory +*basename*, so renaming one orphans live state. + +### Changing the API + +1. Edit `.proto` files in `idl/public/` (or `idl/internal/` for internal-only APIs) +2. Run `make lint` from `idl/` (see `idl/AGENTS.md` for full workflow) +3. Run `make gen` from `idl/` to regenerate downstream repos +4. Commit + push `idl/`. The downstream `api*` and `api-go*`/`api-ts*` repos rebuild automatically; do not commit generated code there manually. +5. Update `app-frontend/` if TS types changed + +### Go Module Dependency Chain + +``` +api-go (go.linro.dev/api) + ↓ +plugin-sdk → plugin-host → plugin-aws + ↓ ↓ +service ←──────────────────────┘ + ↓ +agent +``` + +Local development uses a `go.work` workspace to resolve inter-module dependencies. Published modules like `go.linro.dev/api` use tagged versions in `go.mod`; unpublished modules (`plugin-sdk`, `plugin-host`) use `replace` directives. + +## Summoner — admin tool for Linro installations + +`summoner/` (Go backend) + `summoner-frontend/` (Next.js) compose the +internal admin tool the linro.io team uses to **summon** and **dismiss** +Linro installations on behalf of customers. Each installation gets its +own `linro-` namespace and `.linro.localhost` host in the +local Tilt cluster (or `.instance.linro.dev` on leeroy-dev — not +wired in the PoC). + +- Lifecycle is Temporal-driven: `SummonInstallationWorkflow` (helm + install linro-infra → linro) and `DismissInstallationWorkflow` + (uninstall linro → linro-infra → delete namespace). +- Permissions are flat: `viewer` < `operator` < `admin`. Login is real + OIDC (authz-code + PKCE) against Dex — `--auth-provider google` (or + `mock` for dev); the dummy operator-picker is gone. +- The summoner depends on the CNPG operator + Traefik being + resident in the cluster — `local-dev` installs both as part of `tilt up`. + +Tracking ticket: **ENG-139 — Linro Summoner PoC**. See +`summoner/AGENTS.md` for the architecture overview. + +## Adding a new plugin + +**Always use `/init-plugin `.** Plugin repos share a tight set of +conventions (`.marketplace` schema, reusable release workflow in +`linro-io/workflows`, ECR push for the demo service, `dev` GitHub +Environment, the `skip-release` label, the matching infra terraform +entries). Scaffolding by hand drifts — the skill writes every file +from the latest canonical templates and prints the remote-wiring +checklist (GitHub repo, `repos.yaml`, `go.work`, infra terraform PR) +so nothing is forgotten. + +See `.claude/skills/init-plugin/SKILL.md` for the full template set +and the remote-wiring steps. + +## Regression tests + +`regression-test/` holds the Playwright end-to-end suite. Two legs share one +spec dir: a **Tilt** leg (disposable local-dev stack, mock login) and a +preflight-gated **live** leg against the persistent `regression-test.linro.app` +install. Almost all new coverage is the live leg's event-sourcing specs — +create a cloud resource, assert it flows into the Linro inventory / a check / +the UI. + +**Always read `regression-test/AGENTS.md` before writing specs**, and use +**`/add-live-regression-spec`** to add one. The live leg has tight conventions +that drift when hand-rolled: a manifest-driven preflight gate, four +definition-driven test-type harnesses (`defineInventoryRoundTrip` / +`defineResourceUpdateLoop` / `defineViolationLoop` / `defineUpdateScenario`), an +IAM permission fence on every GCP resource (`linro-regr-*` name prefix; only +name-embedding resource types are fenceable), a park-on-known-bug pattern +(`fixme` + `LIVE_RUN_FIXME=1` to verify a deployed fix), and a shared-env rule +(read-only or self-cleaning, per-run unique names, janitors). The skill encodes +the harness-choice decision tree, the fence wiring, and the local verification +loop. + +## Release baseline + +Every ECR-image-publishing service (`service`, `app-frontend`, +`marketplace`, `marketplace-{admin-,}frontend`, `simulator-service`, +`sensor`), every plugin (`plugin-aws`, `plugin-azure`, `plugin-gcp`, +`plugin-hetzner`, `plugin-kubernetes`), and every plugin-tooling +library (`plugin-host`, `plugin-sdk`) share one release-flow +contract: + +| Trigger | Behaviour | +|-------------------------------|----------------------------------------------------------------| +| `push` to `main` | Auto-release. Bump component from the merged PR's `release:bump_*` label, default patch. | +| `push` with `.github`-only diff | Suppressed via `paths-ignore: ['.github/**']`. | +| PR label `skip-release` | Suppressed. | +| PR label `release:bump_minor` | Minor bump on merge. | +| PR label `release:bump_major` | Major bump on merge. Major beats minor when both labels present. | +| `workflow_dispatch` | Always releases. `version` input: `vX.Y.Z`, `BUMP`, `BUMP_PATCH`, `BUMP_MINOR`, or `BUMP_MAJOR`. | + +Services and plugin-tooling libraries delegate to +`linro-io/workflows/.github/workflows/service-release.yml@main` +(generic "create-a-tagged-release"). Plugins delegate to +`plugin-release.yml` in the same hub repo (cross-compile per +platform from `.marketplace`, attach tarballs atomically, Slack +notify). Each caller repo's `cut-release.yml` is a thin wrapper. The +release itself is created with a GitHub App token so +`release: published` fires the caller's `staging-ecr-release.yml` (which +builds + pushes the ECR image) — GITHUB_TOKEN-created releases are +silently filtered by GitHub. + +Sensor is the only hybrid: it ships cross-compiled tarballs **and** an +ECR image. It keeps an inline `cut-release.yml` (it can't call +`service-release.yml` because the atomic-release-with-binaries +constraint of Immutable Releases requires its own `release-binaries.yml`) +but follows the same trigger + label contract. + +See `linro-io/workflows/README.md` for the workflow contracts. + +## UUIDs -- Always UUIDv7 + +Every UUID generated in this codebase MUST be UUIDv7 unless one of these exceptions applies: + +1. **`_linro_id`** -- generated via `linroid/v1.GenerateResource` / `GenerateComponent`. These are deterministic UUIDv8s derived from plugin/service/type/scope/key. Never replace with UUIDv7. +2. The user explicitly requests a different version with a documented reason. + +UUIDv7 is time-ordered: natural creation-time ordering, monotonic primary keys, better B-tree locality, easier debugging. Random UUIDs (v4) hurt index performance and lose the temporal signal. + +**Go usage:** +- `github.com/gofrs/uuid/v5` -- `uuid.NewV7()` (returns `(UUID, error)`) +- `github.com/google/uuid` v1.6+ -- `uuid.NewV7()` (returns `(UUID, error)`) +- **Never** use `uuid.New()`, `uuid.NewRandom()`, `uuid.Must(uuid.NewRandom())`, `uuid.NewV4()` -- these all produce UUIDv4. + +**SQL defaults:** PostgreSQL columns must use `DEFAULT uuidv7()`, never `gen_random_uuid()` or `uuid_generate_v4()`. + +**When reviewing new code, treat any non-v7 UUID generation as a bug.** + +## CI runners — GitHub-hosted (cloud) is the default + +New and migrated workflows run on **GitHub-hosted** runners +(`ubuntu-latest`, or `ubuntu-24.04` / `ubuntu-24.04-arm` for the +per-arch ECR build legs). Go caching uses `actions/setup-go` with +`cache: true` — the action keys the cache by `go.sum`, so no +per-runner path juggling. This is the policy the `init-plugin` +templates encode; follow them as the canonical reference. + +Rationale: the self-hosted `linro-ghr-*` fleet ("leeroy") is a single +point of failure — when it went down (2026-07 power outage) every CI +and release job hung `queued`, blocking builds during a demo. Cloud +runners decouple CI from that fleet. The shared reusable workflows in +`linro-io/workflows` (`service-release.yml`, `plugin-release.yml`, +`license-check.yml`) are already `ubuntu-latest`, so every caller's +release path runs on cloud regardless of the caller's own CI runner. + +**Do NOT reintroduce the retired self-hosted per-runner Go cache step** +(`GOCACHE`/`GOMODCACHE=/opt/actions-runner/cache/...$RUNNER_NAME`). It +only made sense on the shared-disk `linro-ghr-*` hosts (4 runners per +host racing one GOMODCACHE root) and is dead weight — and unwritable — +on hosted runners. + +### Migration status + the exceptions that STAY self-hosted + +Migration to cloud is in progress (many repos still carry +`runs-on: self-hosted` and are being converted repo-by-repo). Three +categories legitimately remain self-hosted — do not blind-flip them: + +- **`regression-test`** — its Tilt-based jobs need `[self-hosted, big]`; + they OOM on a standard hosted runner. +- **`chart` `deploy-*.yml` / `demolish.yml` / `rebuild.yml`** — they + `helm upgrade` against k3s/EKS apiservers reachable only over the + tailnet (`*.ts.net`). Cloud-migrating these needs a + `tailscale/github-action` connect step + a Tailscale OAuth/auth-key + secret first. +- **Anything that touches a PRIVATE repo or the GitHub API** — including + `actions/checkout`, `actions/download-artifact`, and any `gh` call. The + org's **IP allow list** refuses hosted runners: + + ``` + Although you appear to have the correct authorization credentials, the + `linro-io` organization has an IP allow list enabled, and your IP address + is not permitted to access this resource. + ``` + + This is the exception most likely to be missed, because the obvious test + — "does this job need cloud credentials or the tailnet?" — returns *no* + and is the wrong question. The allow list gates **GitHub itself**, so a + job holding nothing but `secrets.GITHUB_TOKEN` still cannot read its own + repo's artifacts from `ubuntu-latest`. It has been missed twice in + `linro-io/infra` (`terraform.yml`'s checkout, then + `terraform-pr-comment.yml`, which failed on **every run** from the day it + was added and never once posted a comment). The public-repo release + workflows below are fine only because their targets are public. +- Anything else that reaches a tailnet-only host or a runner-local tool. + +Before migrating anything to hosted, check it against the allow list +exception first: scan the workflow with +`rg 'checkout|download-artifact|gh ' .github/workflows`. If any of them touches a private repo, it stays self-hosted. + +When you DO migrate a Go workflow: `self-hosted`→`ubuntu-latest`, +per-arch ECR legs→`ubuntu-24.04` / `ubuntu-24.04-arm`, drop the +per-runner cache step, set `actions/setup-go` `cache: true`, and watch +the first CI run — hosted module-mode builds surface any incomplete +`go.sum` (missing `/go.mod` hash lines) that a warm self-hosted cache +was masking (`GOWORK=off go mod download all` to repair). + +## Linear + +Work is tracked in Linear, and **the convention is not obvious from the +workspace** — it has drifted before. Read `docs/agents/org-rules/linear.md` before +filing, restructuring or closing anything. + +The short version: Linear has no "epic". A workstream is a **Project**, its +phases are **Project Milestones** (each carrying its gate), and sequencing is +**blocking relations** — never a parent issue, which encodes containment and +nothing else. Every issue carries the problem with `file:line` evidence, +acceptance criteria, and a *not in scope* line where the boundary matters. +Cancel superseded issues, never delete them. + +`/file-workstream` scaffolds a multi-ticket workstream to that shape. The rule +file is canonical; the Linear Agent Skill and the Engineering issue/project +templates are copies of it and change in the same PR. + +## `.entire/` never reaches a PR or main + +Every sub-repo working tree grows an untracked `.entire/` directory: the +Entire session recorder's local metadata. (The `entire/checkpoints/v1` ref it +pushes alongside every `git push` is its own ref and is fine.) The directory +is local tooling state, not project content. **It must never be staged, never +appear in a PR, and never be merged to main.** It has slipped in twice through +a bare `git add -A` (the simulator-service#29 squash, idl#152), each needing a +scrub commit afterwards. + +Do NOT add it to any repo's `.gitignore` either — it stays untracked and +visible, not ignored. Hygiene instead: + +- Stage by path (`git add `); never `git add -A` / `git add .` in a + sub-repo. +- Before every commit, `git status --short` must show `.entire/` only as `??`. +- Before opening or merging a PR, `gh pr diff --name-only` must contain + no `.entire/` path. A PR that carries one is not mergeable until the paths + are removed from the branch. + +The one PR that may name `.entire/` is a **cleanup PR for a repo that already +tracks it**: its whole diff is the removal, adding nothing and changing +nothing. It carries no `.gitignore` entry — after it lands the directory is +untracked and visible again, which is the state being restored. Everything +above is about a PR that adds or changes those paths. + +**That cleanup untracks; it never deletes.** The directory holds the local +session recordings, which are worth keeping and are read by tooling — so the +only command is + +```bash +git rm -r --cached .entire # index only; the files stay on disk +``` + +Never `git rm -r .entire`, `rm -rf .entire`, or a `git clean` that reaches it: +those destroy session history that exists nowhere else. "Remove it from the +repo" always means remove it from the INDEX. + +## Tool Usage + +- Always use Context7 MCP for library/API documentation +- Always use `rg` (ripgrep) instead of `grep` +- Always use `fd` instead of `find` +- Never use `grep`, `find -exec`, `find -delete`, `xargs`, or shell pipes that execute commands From 933e73b93308853e6bfa0c1aeb82345a9b17e3c7 Mon Sep 17 00:00:00 2001 From: Istvan Docsa Date: Tue, 8 Sep 2026 23:45:18 +0200 Subject: [PATCH 2/2] docs: address instruction review feedback --- docs/agents/org-rules/tool-usage.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/agents/org-rules/tool-usage.md b/docs/agents/org-rules/tool-usage.md index a3c0303..a5087a2 100644 --- a/docs/agents/org-rules/tool-usage.md +++ b/docs/agents/org-rules/tool-usage.md @@ -14,7 +14,9 @@ Use safe, purpose-built CLI tools for searching and file discovery. Never fall b ## File Discovery -- Always use `fd` instead of `find` for all file discovery +- Always use `fd` instead of `find` for all file discovery. Add `--hidden` + when hidden paths are in scope and `--no-ignore` when ignored paths must + intentionally be checked. - Use `fd --extension` to filter by file type (e.g., `fd --extension tf`) ## Security