From ec590a08cd62e538c380e0ac9935dc78fc4e8b28 Mon Sep 17 00:00:00 2001 From: Toby Hede Date: Wed, 2 Sep 2026 09:58:03 +1000 Subject: [PATCH] docs(agents): define repository workflow conventions --- AGENTS.md | 4 +++ CLAUDE.md | 16 ++++++++++ CONTEXT-MAP.md | 14 +++++++++ docs/agents/domain.md | 50 ++++++++++++++++++++++++++++++ docs/agents/issue-tracker.md | 60 ++++++++++++++++++++++++++++++++++++ docs/agents/triage-labels.md | 15 +++++++++ packages/eql/AGENTS.md | 5 +++ packages/eql/CONTEXT.md | 31 +++++++++++++++++++ 8 files changed, 195 insertions(+) create mode 100644 CONTEXT-MAP.md create mode 100644 docs/agents/domain.md create mode 100644 docs/agents/issue-tracker.md create mode 100644 docs/agents/triage-labels.md create mode 100644 packages/eql/CONTEXT.md diff --git a/AGENTS.md b/AGENTS.md index 6457c044d..239450d94 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -84,6 +84,10 @@ If these variables are missing, tests that require live encryption will fail or - `packages/bench`: Performance / index-engagement benchmarks (private, not published) - `packages/protect-ffi`: Native FFI bindings to the CipherStash Client SDK (`@cipherstash/protect-ffi`) — the Rust core that `packages/stack` encrypts and decrypts through, absorbed from `cipherstash/protectjs-ffi`. Contains a **nested Cargo workspace** (`crates/`) and six per-platform binary packages under `platforms/*`, each published as `@cipherstash/protect-ffi-` and linked here via `workspace:*`. Also holds the repo's live FFI integration suite at `integration-tests/` — a private workspace member (`@cipherstash/ffi-integration-tests`) enrolled by its own literal entry in `pnpm-workspace.yaml`, needing Docker and credentials, and deliberately carrying **no `test` script** so `pnpm test` cannot reach it. See the "Working on protect-ffi" notes below before touching it — its default `test` and `build` are deliberately Rust-free. - `packages/eql`: The Encrypt Query Language subtree — the SQL bundle that stores and queries encrypted payloads — absorbed from `cipherstash/encrypt-query-language`. **The directory is the subtree root, not the package.** It was imported at a *verbatim prefix* so its repo-root-relative paths (mise tasks, `Doxyfile`, `sync-generated.mjs`) keep resolving, which puts the npm package `@cipherstash/eql` two levels down at `packages/eql/packages/eql` — the same shape as `packages/protect-ffi/platforms/*`, and enrolled the same way, by an explicit `packages/eql/packages/*` glob in `pnpm-workspace.yaml`. The subtree root deliberately carries no `package.json`. Also contains a **nested Cargo workspace** at `packages/eql/crates/` (`eql-bindings`, published in lockstep with the npm package, plus `eql-domains` / `eql-codegen` / `eql-tests-macros`, which are not), a SQLx test crate at `packages/eql/tests/sqlx`, an ~900-line `mise.toml` task surface, its own `AGENTS.md`, and `docs/`. See the "Working on EQL" notes below before touching it. + **Repository ownership:** EQL now lives in `cipherstash/stack`. File and update + EQL issues in this repository, never in the historical + `cipherstash/encrypt-query-language` repository. Old upstream issue and PR + links are provenance only. - `e2e/*`: Cross-package end-to-end tests (package managers, supply chain, Prisma example README) - `examples/*`: Working apps (basic, prisma, supabase-worker) - `docs/plans/*`: Internal design plans. User-facing documentation lives at https://cipherstash.com/docs (not in this repo). diff --git a/CLAUDE.md b/CLAUDE.md index 8e02cb0a2..cd3c0c688 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,6 +6,22 @@ one source of truth. @AGENTS.md +## Agent skills + +### Issue tracker + +Issues are tracked in GitHub Issues for `cipherstash/stack`. See +`docs/agents/issue-tracker.md`. + +### Triage labels + +Use the five default triage labels. See `docs/agents/triage-labels.md`. + +### Domain docs + +Use a multi-context layout rooted at `CONTEXT-MAP.md`, with package-specific +`CONTEXT.md` files added as needed. See `docs/agents/domain.md`. + ## Before you finish Two rules from `AGENTS.md` are the ones most often missed. They are repeated here diff --git a/CONTEXT-MAP.md b/CONTEXT-MAP.md new file mode 100644 index 000000000..bc13f84f2 --- /dev/null +++ b/CONTEXT-MAP.md @@ -0,0 +1,14 @@ +# Context Map + +## Contexts + +- [EQL](./packages/eql/CONTEXT.md) — defines the PostgreSQL objects that store + and query encrypted values. + +## Relationships + +- **EQL → Stack CLI**: EQL ships install and uninstall artifacts; the Stack CLI + applies them and preserves reconstructable database objects across reinstall. +- **EQL → ORM adapters**: EQL defines durable encrypted column domains and + disposable query machinery; adapters create application columns and derived + search indexes against that surface. diff --git a/docs/agents/domain.md b/docs/agents/domain.md new file mode 100644 index 000000000..bf188066c --- /dev/null +++ b/docs/agents/domain.md @@ -0,0 +1,50 @@ +# Domain docs + +How engineering skills should consume this repository's domain documentation. + +## Before exploring + +- Read `CONTEXT-MAP.md` at the repository root when it exists. It points to the + `CONTEXT.md` files relevant to each context. +- Read the context documents relevant to the task. +- Read system-wide ADRs under `docs/adr/` and context-specific ADRs under the + relevant package's `docs/adr/` directory. + +If these files do not exist, proceed silently. Do not propose empty placeholder +documents. The domain-modeling workflow creates them lazily when terminology or +decisions are actually resolved. + +## Multi-context layout + +```text +/ +├── CONTEXT-MAP.md +├── docs/adr/ system-wide decisions +└── packages/ + ├── stack/ + │ ├── CONTEXT.md + │ └── docs/adr/ stack-specific decisions + ├── cli/ + │ ├── CONTEXT.md + │ └── docs/adr/ CLI-specific decisions + └── / + ├── CONTEXT.md + └── docs/adr/ +``` + +Nested subtrees with their own architecture, such as `packages/eql`, may define +further contexts. `CONTEXT-MAP.md` is the authority for locating them. + +## Use the glossary's vocabulary + +When output names a domain concept—in an issue title, proposal, hypothesis, or +test name—use the term defined in the relevant `CONTEXT.md`. Do not drift to a +synonym that the glossary explicitly avoids. + +If a needed concept is absent, reconsider whether the project already has a +different term. If the gap is real, record it for domain modeling. + +## Flag ADR conflicts + +If proposed work contradicts an existing ADR, identify the conflict explicitly +rather than silently overriding the decision. diff --git a/docs/agents/issue-tracker.md b/docs/agents/issue-tracker.md new file mode 100644 index 000000000..c2acf9dfb --- /dev/null +++ b/docs/agents/issue-tracker.md @@ -0,0 +1,60 @@ +# Issue tracker: GitHub + +Issues and specs for this repo live as GitHub issues. Use the `gh` CLI for all +operations. + +## Repository ownership + +All work present in this monorepo is tracked in `cipherstash/stack`, including +the absorbed EQL source under `packages/eql` and protect-ffi under +`packages/protect-ffi`. Their former upstream repositories are historical +sources, not active issue trackers. Never create, move, or update an issue in +`cipherstash/encrypt-query-language` or `cipherstash/protectjs-ffi` for work in +this tree. Create it in `cipherstash/stack` and link historical upstream issues +only as provenance. + +## Conventions + +- **Create an issue**: `gh issue create --title "..." --body "..."`. Use a + heredoc for multi-line bodies. +- **Read an issue**: `gh issue view --comments`, filtering comments by + `jq` and also fetching labels. +- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` + with appropriate `--label` and `--state` filters. +- **Comment on an issue**: `gh issue comment --body "..."`. +- **Apply/remove labels**: `gh issue edit --add-label "..."` or + `--remove-label "..."`. +- **Close**: `gh issue close --comment "..."`. + +Use `--repo cipherstash/stack` explicitly. Do not infer ownership from subtree +history, package names, old issue links, or additional git remotes. + +## Pull requests as a triage surface + +**PRs as a request surface: no.** Set this to `yes` if this repository starts +treating external pull requests as feature requests. + +When enabled, use the corresponding `gh pr` commands. GitHub shares one number +space across issues and pull requests, so resolve an ambiguous `#42` with +`gh pr view 42` and fall back to `gh issue view 42`. + +## Skill operations + +- When a skill says **publish to the issue tracker**, create a GitHub issue. +- When a skill says **fetch the relevant ticket**, run + `gh issue view --comments`. + +## Wayfinding operations + +The map is one issue labelled `wayfinder:map`; its tickets are child issues. + +- Create child tickets as GitHub sub-issues through `gh api`. If sub-issues are + unavailable, use a task list in the map and add `Part of #` to each + child. +- Label children `wayfinder:` where type is `research`, `prototype`, + `grilling`, or `task`. +- Represent blocking with GitHub's native issue dependencies. Fall back to a + `Blocked by: #` line only when dependencies are unavailable. +- Claim work with `gh issue edit --add-assignee @me`. +- Resolve work by commenting with the result, closing the child, and adding its + context pointer to the map's Decisions-so-far section. diff --git a/docs/agents/triage-labels.md b/docs/agents/triage-labels.md new file mode 100644 index 000000000..2d6736b3c --- /dev/null +++ b/docs/agents/triage-labels.md @@ -0,0 +1,15 @@ +# Triage labels + +The engineering skills use five canonical triage roles. This table maps those +roles to this repository's GitHub labels. + +| Canonical role | GitHub label | Meaning | +| --- | --- | --- | +| `needs-triage` | `needs-triage` | Maintainer needs to evaluate the issue | +| `needs-info` | `needs-info` | Waiting on the reporter for more information | +| `ready-for-agent` | `ready-for-agent` | Fully specified and ready for an AFK agent | +| `ready-for-human` | `ready-for-human` | Requires human implementation | +| `wontfix` | `wontfix` | Will not be actioned | + +When a skill names a triage role, use the corresponding GitHub label from this +table. diff --git a/packages/eql/AGENTS.md b/packages/eql/AGENTS.md index 3926339b0..be2deaf7a 100644 --- a/packages/eql/AGENTS.md +++ b/packages/eql/AGENTS.md @@ -1,5 +1,10 @@ # CLAUDE.md +> **Repository ownership:** EQL is maintained in the `cipherstash/stack` +> monorepo. Track all EQL work in `cipherstash/stack` GitHub Issues. The former +> `cipherstash/encrypt-query-language` repository and its issues are historical +> provenance only; do not create or update active work there. + This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Development Commands diff --git a/packages/eql/CONTEXT.md b/packages/eql/CONTEXT.md new file mode 100644 index 000000000..72efae290 --- /dev/null +++ b/packages/eql/CONTEXT.md @@ -0,0 +1,31 @@ +# Encrypt Query Language + +EQL defines the PostgreSQL representation and query surface for searchable +encrypted values. + +## Language + +**Encrypted data**: +Ciphertext and search terms stored in an application table column. Its continued +existence is the primary persistence guarantee. +_Avoid_: EQL machinery, index state + +**Data-bearing domain**: +A durable `public.eql_v3_*` PostgreSQL domain used as an application column type. +It must survive EQL install, uninstall, and reinstall. +_Avoid_: Query domain, EQL schema type + +**EQL machinery**: +Disposable functions, query-operand types, operators, aggregates, and internal +types owned by the `eql_v3` and `eql_v3_internal` schemas. +_Avoid_: Encrypted data + +**Derived search index**: +A reconstructable functional index over EQL machinery. It accelerates encrypted +queries but is not the authoritative copy of encrypted data. +_Avoid_: Encrypted data, durable data + +**Non-reconstructable dependency**: +A customer-owned constraint, policy, view, or other database object whose +meaning cannot be safely inferred and recreated by the EQL installer. +_Avoid_: Derived search index