Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .github/workflows/doc-layout.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Doc layout

# Hard gate: new Markdown files must live under docs/ (except root README.md, CLAUDE.md, AGENTS.md).
# Hard gate: new Markdown files must use the locations listed in docs/README.md.
# Design: docs/README.md § Enforcement

on:
Expand Down Expand Up @@ -45,10 +45,8 @@ jobs:
# Root tool-discovery entry points, not documentation. Every LLM harness looks for its
# own filename at the repo ROOT and nowhere else — Claude Code reads CLAUDE.md, Codex /
# Cursor / Copilot read AGENTS.md — so these cannot live under docs/ and still function.
# Both are two-line pointers at docs/OPERATING_INSTRUCTIONS.md and
# docs/OPENLOOP_INSTRUCTIONS.md, which hold the one shared copy of the instructions
# (owner instruction, 2026-08-30: one source of truth across multiple LLMs).
README.md|CLAUDE.md|AGENTS.md)
# The pointers also load the owner's shared Engineering-Prompt.md from the root.
README.md|CLAUDE.md|AGENTS.md|Engineering-Prompt.md)
;;
docs/*)
;;
Expand All @@ -67,7 +65,7 @@ jobs:
done

if [ -n "$VIOLATIONS" ]; then
echo "::error::New Markdown must live under docs/ (except root README.md, CLAUDE.md, AGENTS.md)."
echo "::error::New Markdown must use the allowed locations in docs/README.md."
printf '%b' "$VIOLATIONS"
exit 1
fi
Expand Down
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Read and follow [Engineering-Prompt.md](Engineering-Prompt.md) before starting work in this project.

First Read: `docs/OPERATING_INSTRUCTIONS.md` — how to work here.
Then Read: `docs/OPENLOOP_INSTRUCTIONS.md` — what OpenLoop is.

Expand Down
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Read and follow [Engineering-Prompt.md](Engineering-Prompt.md) before starting work in this project.

First Read: `docs/OPERATING_INSTRUCTIONS.md` — how to work here.
Then Read: `docs/OPENLOOP_INSTRUCTIONS.md` — what OpenLoop is.

Expand Down
125 changes: 125 additions & 0 deletions Engineering-Prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
Before implementing anything, follow a **reuse-first / ecosystem-first engineering approach**.

Your job is not merely to make the feature work. Your job is to solve it using the **smallest, most standard, most maintainable solution that already exists** whenever possible.

## Mandatory reconnaissance before writing code

Before designing or implementing a custom solution:

1. **Inspect the existing codebase**
- Understand the current architecture and conventions.
- Identify existing abstractions, utilities, services, packages, SDKs, helpers, patterns, and extension points that are relevant.
- Prefer extending existing code over creating parallel implementations.
- Check dependency manifests and determine what libraries/SDKs are already installed and what versions are pinned.

2. **Investigate existing SDK/library capabilities**
- Check whether an SDK or package we already use supports the required functionality.
- Do not assume the currently pinned version represents the latest capabilities.
- Check newer versions, release notes, migration guides, API references, generated docs, and examples.
- If a newer SDK version solves the problem cleanly, evaluate upgrading it before implementing the capability ourselves.
- A major-version bump is not automatically disqualifying. Evaluate the actual migration cost and breaking changes.

3. **Search the broader ecosystem**
- Search GitHub for existing implementations, issues, discussions, examples, reference projects, and upstream solutions.
- Check official repositories before random third-party examples.
- Look for maintained packages, SDKs, framework integrations, plugins, extensions, adapters, and tools that already solve the problem.
- Check package registries relevant to the stack: npm, NuGet, PyPI, Go modules, Maven, Cargo, etc.
- Check available ChatGPT/Codex plugins, skills, tools, MCP servers, or connected services when they can provide the capability directly.

4. **Check the platform/framework standard library**
- Before inventing infrastructure, verify whether the language or framework already provides it.
- Prefer standard facilities for HTTP, testing, mocking, serialization, retries, caching, dependency injection, logging, authentication, configuration, concurrency, etc.
- Example: do not create a custom HTTP-client abstraction merely to make tests possible if the language's normal HTTP testing utilities already support the requirement.

## Preferred solution hierarchy

Use this order of preference:

Existing codebase capability
→ Existing dependency capability
→ Upgrade an existing dependency
→ Official SDK/library/package
→ Standard library/framework feature
→ Well-maintained community package
→ Small adapter around one of the above
→ Custom implementation

A custom implementation should be the **last resort**, not the starting point.

## Before choosing custom code

If you believe a custom implementation is necessary, explicitly explain:

- What existing code you inspected.
- Which SDKs/packages you evaluated.
- Whether newer versions contain the capability.
- Which official docs/repositories/GitHub issues you checked.
- Why existing solutions are insufficient.
- Why extending or upgrading an existing dependency is worse.
- What maintenance burden the custom implementation introduces.

If you cannot provide a convincing answer to those questions, **continue researching instead of writing the custom implementation**.

## Avoid accidental infrastructure

Be especially suspicious if your solution starts requiring custom versions of foundational infrastructure such as:

- HTTP clients
- retry frameworks
- authentication clients
- serialization layers
- logging frameworks
- test/mocking frameworks
- dependency injection systems
- caching systems
- database clients
- API clients that duplicate an official SDK

These are strong signals that you may be solving the problem at the wrong abstraction level.

## Optimize for engineering taste, not code volume

Do not reward yourself for writing more code.

Prefer solutions that:

- reduce code ownership
- reduce maintenance burden
- follow existing project conventions
- use battle-tested libraries
- minimize new abstractions
- minimize surface area
- remain easy for another senior engineer to understand
- make future upgrades easier rather than harder

Do not create an abstraction merely because it makes the implementation look architecturally complete.

## Research before implementation

For non-trivial tasks, do not immediately start modifying files.

First produce a short **reconnaissance summary** containing:

**Existing:** What relevant capabilities already exist in the repository.

**Ecosystem:** Relevant SDKs, packages, standard-library features, plugins, skills, or upstream implementations you found.

**Upgrade path:** Whether updating an existing dependency would solve the problem.

**Recommendation:** The simplest approach and why.

**Rejected alternatives:** Any tempting custom approaches and why they are unnecessary.

**Do not begin implementation until the reconnaissance phase is complete.**

## Final sanity check

Immediately before implementing, ask:

> "Am I writing code that someone else has already written, maintained, tested, documented, and packaged for this exact ecosystem?"

If the answer might be yes, investigate that option first.

The goal is:

**Use what exists. Extend before replacing. Upgrade before reimplementing. Wrap before rebuilding. Own as little infrastructure as possible.**
10 changes: 5 additions & 5 deletions docs/DEFINITION_OF_DONE.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ Both have failed repeatedly in CI (PR #161 hit both at once), which is why they
### M1. New Markdown lives under `docs/`

**A brand-new `.md` file goes under `docs/`.** The only exceptions are the allowlist in
[`docs/README.md` § Enforcement](README.md#enforcement) — root `README.md` / `CLAUDE.md` / `AGENTS.md`
[`docs/README.md` § Enforcement](README.md#enforcement) — root `README.md` / `CLAUDE.md` / `AGENTS.md` / `Engineering-Prompt.md`
and the agent-harness paths (`.claude/`, `.cursor/`, `.codex/`, `swarm/`). That list is the
single source of truth; it is enforced by [`.github/workflows/doc-layout.yml`](../.github/workflows/doc-layout.yml)
against `git diff --diff-filter=A`.

- **Do not widen the allowlist to make your file fit.** Move the file into `docs/`. Widening the gate is
an owner decision, requested explicitly and justified in the PR — never a workaround for a red check.
(The one widening so far: root `AGENTS.md`, because each LLM harness auto-discovers only *its* filename
at the repo root. See M3.)
The owner requested root `AGENTS.md` for harness discovery and root `Engineering-Prompt.md` for
shared engineering guidance across projects. See M3.
- Editing an existing root `.md` is fine (the gate only sees *added* files) — but a doc that would be
new today belongs in `docs/` today.
- Check yourself before committing:
Expand Down Expand Up @@ -126,12 +126,12 @@ one newline), **MD022** (blank line above *and below* every heading), **MD032**
The owner drives this repo with several LLMs, so the instructions exist **once** (owner instruction,
2026-08-30): [`docs/OPERATING_INSTRUCTIONS.md`](OPERATING_INSTRUCTIONS.md) (how to work here) and
[`docs/OPENLOOP_INSTRUCTIONS.md`](OPENLOOP_INSTRUCTIONS.md) (what OpenLoop is). Root `CLAUDE.md` and
`AGENTS.md` are byte-identical two-line pointers at those files and carry **no content of their own** —
`AGENTS.md` are byte-identical pointers to the root `Engineering-Prompt.md` and those files, and carry **no content of their own** —
they exist only because each harness auto-discovers its own filename at the repo root.

- **Never fork a per-tool copy** of an instruction file, and never paste content back into a root pointer.
Edit the `docs/` file; every LLM picks the change up.
- Adding a harness that reads a different root filename? Add another two-line pointer *and* the
- Adding a harness that reads a different root filename? Add another pointer *and* the
allowlist entry in `doc-layout.yml` + `docs/README.md` § Enforcement, in the same PR.

### M4. Moved or renamed something? Grep the whole repo for stale references
Expand Down
2 changes: 1 addition & 1 deletion docs/OPENLOOP_INSTRUCTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Show reasoning, not just conclusions. I value breadth and rigor equally — cast

When operating in a specific subfolder that has its own agent instructions, respect that folder's voice and approach. This file provides the defaults; subfolder overrides take precedence.

All project documentation (`.md` files) belongs in the `docs/` directory — not the project root. The only exceptions are `README.md` and the two harness pointers `CLAUDE.md` / `AGENTS.md`, which live at the root by convention. **Folder map and placement rules:** [`docs/README.md`](README.md) (Markdown layout, image assets, gitignored `docs/local/` for private notes).
Project documentation (`.md` files) belongs in `docs/`. Root exceptions are `README.md`, the two harness pointers `CLAUDE.md` / `AGENTS.md`, and the owner's shared `Engineering-Prompt.md`. **Folder map and placement rules:** [`docs/README.md`](README.md) (Markdown layout, image assets, gitignored `docs/local/` for private notes).

## Architecture Snapshot

Expand Down
8 changes: 4 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Documentation layout — OpenLoop

**Single rule:** all project documentation lives under `docs/`. The only exceptions at the repo
root are `README.md`, `CLAUDE.md`, and `AGENTS.md` (convention).
root are `README.md`, `CLAUDE.md`, `AGENTS.md`, and the owner's shared `Engineering-Prompt.md`.

**Agent instructions are shared, not per-tool** (owner instruction, 2026-08-30). The owner works
this repo with several LLMs, so the instructions exist **once**, under `docs/`:
[`OPERATING_INSTRUCTIONS.md`](OPERATING_INSTRUCTIONS.md) (how to work here) and
[`OPENLOOP_INSTRUCTIONS.md`](OPENLOOP_INSTRUCTIONS.md) (what OpenLoop is). Root `CLAUDE.md` and
`AGENTS.md` are two-line pointers at those files and hold no content of their own — each harness only
`AGENTS.md` first link to [`Engineering-Prompt.md`](../Engineering-Prompt.md), then to those files, and hold no content of their own. Each harness only
auto-discovers *its* filename at the repo root, which is why the pointers can't move into `docs/`.
**Never fork a per-tool copy**; edit the `docs/` file and every LLM picks the change up.

Expand Down Expand Up @@ -85,8 +85,8 @@ In-app launcher assets live only under `app/src/main/res/` (see root [`README.md
## Enforcement

1. **Agents:** `CLAUDE.md` mandates reading the core `docs/lessons_learned/` tier and this layout before adding docs.
2. **PR review:** the [`pr-reviewer`](../.claude/skills/pr-reviewer/SKILL.md) skill flags new `.md` outside `docs/` (except root `README.md` / `CLAUDE.md`).
3. **CI — doc layout gate:** [`.github/workflows/doc-layout.yml`](../.github/workflows/doc-layout.yml) fails PRs that **add** new `*.md` outside allowed paths. Allowed today: `docs/`, root `README.md` / `CLAUDE.md` / `AGENTS.md` (tool-discovery entry points — each harness only looks for its own filename at the repo root, so the pointers cannot move; owner instruction, 2026-08-30), `swarm/`, `.claude/`, `.cursor/`, `.codex/` (Cursor and Codex `SKILL.md` packages, same class as `.claude/skills/`).
2. **PR review:** the [`pr-reviewer`](../.claude/skills/pr-reviewer/SKILL.md) skill flags new `.md` outside the allowed locations below.
3. **CI — doc layout gate:** [`.github/workflows/doc-layout.yml`](../.github/workflows/doc-layout.yml) fails PRs that **add** new `*.md` outside allowed paths. Allowed today: `docs/`, root `README.md` / `CLAUDE.md` / `AGENTS.md` (tool-discovery entry points), root `Engineering-Prompt.md` (the owner requires this shared prompt at the same path across projects), `swarm/`, `.claude/`, `.cursor/`, `.codex/` (agent skill packages).
4. **CI / Tier 3 static analysis:** [`STATIC_ANALYSIS.md`](STATIC_ANALYSIS.md) — markdownlint, table alignment, link check, harness skill-tree identity, cspell and JSON validity over the whole tracked tree, hard. Locally the same checks are gates 6–8 of `scripts/pre-pr-sweep.ps1` (tooling lives in `scripts/`, not here — it is not documentation).
5. **Secrets:** `keystore.properties`, `*.jks`, and `docs/local/` are gitignored.

Expand Down
2 changes: 1 addition & 1 deletion docs/STATIC_ANALYSIS.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ broken references on `main`** (not introduced by this work):
### Doc layout gate — GitHub Actions (hard)

**`.github/workflows/doc-layout.yml`** runs on every pull request. It fails if the PR **adds** any
`*.md` file outside `docs/` (allowed exceptions: root `README.md`, `CLAUDE.md`, `AGENTS.md`). Policy:
`*.md` file outside the allowed locations listed in `docs/README.md`. Policy:
[`docs/README.md`](README.md) § Enforcement.

### Hosting Tier 3 — GitHub Actions (hard)
Expand Down