From d1acd2228491778b396a78dc180a3469ee39d313 Mon Sep 17 00:00:00 2001 From: Juhana Ilmoniemi Date: Mon, 11 May 2026 12:10:55 +0300 Subject: [PATCH] chore(docs): freeze PROJECT-MEMORY.md + lessons.md; route per-ticket content to codebase/.md Same fix as pyrycode/pyrycode PR #284 (just merged). See that PR and agent-dispatcher-v2 PRs #56 + #63 for the full rationale. Changes: - docs/PROJECT-MEMORY.md: file-level READ-ONLY-FOR-AGENTS notice matching the new "Never Update" rules in pyrycode-relay-agents PR #1. "What's built" freeze strengthened; "Patterns established" gets its own freeze marker. - docs/lessons.md: frozen, with intro pointing to per-ticket codebase/.md "Lessons learned" sections. - docs/knowledge/codebase/README.md: extended to absorb patterns + lessons; updated "Why" section to cover all three failure modes (concurrent / stale-branch / cross-phase). Companion agent CLAUDE.md changes already shipped in pyrycode-relay-agents PR #1 (sole-writer rules). --- docs/PROJECT-MEMORY.md | 8 ++++++-- docs/knowledge/codebase/README.md | 13 +++++++++---- docs/lessons.md | 8 ++++++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/docs/PROJECT-MEMORY.md b/docs/PROJECT-MEMORY.md index 005f0b4..10df6ed 100644 --- a/docs/PROJECT-MEMORY.md +++ b/docs/PROJECT-MEMORY.md @@ -2,9 +2,11 @@ Stateless WebSocket router between mobile clients and pyry binaries. Internet-exposed; adversarial input is the default assumption. Authoritative wire spec lives in `pyrycode/pyrycode/docs/protocol-mobile.md`. +> **READ-ONLY FOR AGENTS (as of 2026-05-11).** All five pipeline agents have explicit "Never Update docs/PROJECT-MEMORY.md" rules. Per-ticket content (implementation, patterns, lessons) goes in [`docs/knowledge/codebase/.md`](knowledge/codebase/). Humans maintain this file directly. + ## What's built -> **Convention (2026-05-10 onwards):** Per-ticket implementation summaries live in [`docs/knowledge/codebase/.md`](knowledge/codebase/), one file per ticket. The table below is pre-2026-05-10 history — frozen, kept for context. See [`docs/knowledge/codebase/README.md`](knowledge/codebase/README.md) for the convention rationale. +> **FROZEN.** Pre-2026-05-10 history. Per-ticket implementation summaries live in [`docs/knowledge/codebase/.md`](knowledge/codebase/). The table below is kept for context — do not append. | Area | Status | Where | |---|---|---| @@ -25,7 +27,9 @@ Stateless WebSocket router between mobile clients and pyry binaries. Internet-ex | `conn_id` generation scheme | Not started | — | | Threat model doc — operational surface (deploy, supply chain, DoS, log hygiene, cert handling, TLS, error leakage) | Done (#11) | `docs/threat-model.md` | -## Patterns established +## Patterns established (frozen 2026-05-11) + +> **FROZEN.** Pre-2026-05-11 patterns. New per-ticket patterns live in `docs/knowledge/codebase/.md`. Do not append here. - **Sentinel errors, branched via `errors.Is`** for validation failures at protocol boundaries. New routing-layer code follows the `Err...` naming and wraps with `fmt.Errorf("…: %w", err, sentinel)` when adding context. - **Opacity by type.** Inner-frame payloads are carried as `json.RawMessage`. The relay never deserialises payloads; the type makes that hard to violate accidentally. diff --git a/docs/knowledge/codebase/README.md b/docs/knowledge/codebase/README.md index e570125..3141d43 100644 --- a/docs/knowledge/codebase/README.md +++ b/docs/knowledge/codebase/README.md @@ -1,19 +1,24 @@ # Per-Ticket Codebase Notes -One file per ticket: `.md`. Each file describes what was built for that ticket — the bullets that historically went into `docs/PROJECT-MEMORY.md`'s "What's Built" section. +One file per ticket: `.md`. Each file describes what was built for that ticket — **implementation summary, patterns established, AND lessons learned** all live in this per-ticket file. ## Convention - **Filename**: `.md` (e.g. `5.md`, `21.md`). Numeric only — no prefix, no description in the filename. - **One file per ticket.** Never edit a sibling ticket's file. -- **Never modify `docs/PROJECT-MEMORY.md`'s "What's Built" section.** It holds frozen pre-2026-05-10 history; new work lives here. +- **Never modify `docs/PROJECT-MEMORY.md`.** All sections in that file are frozen as of 2026-05-11. New work lives here. +- **Never append to `docs/lessons.md`.** Frozen 2026-05-11. New lessons surface as a "Lessons learned" section inside the relevant `.md`. - **Directory listing IS the index.** `ls docs/knowledge/codebase/` sorted is reverse-chronological-ish (issue numbers monotonic). No separate index file to maintain. ## Why -Parallel docs agents writing to the same line in `PROJECT-MEMORY.md`'s "What's Built" caused recurring merge conflicts in the canonical pyrycode pipeline (2026-05-09 Phase 3 batch — 3 stuck PRs; 2026-05-10 — 2 more stuck PRs). Per-ticket files eliminate the hot line entirely — two concurrent docs runs never touch the same file. +Shared-append docs (whether `PROJECT-MEMORY.md`'s sections or `lessons.md`) cause recurring merge conflicts via three failure modes: -Pyrycode-relay's pipeline is younger but inherits the same convention for consistency, so the docs agent prompt is portable and the failure mode never surfaces here. +- **Concurrent docs** — two cycles' documentation agents both append at the same anchor → add/add conflict. Fixed by `serial: true` in v1 dispatcher `2d6b4ee`. +- **Stale-branch + marched-forward main** — feature/B appends based on B's snapshot, while feature/A merges with its own appended section first. When B tries to merge, B has no record of A's entry → conflict. `serial: true` doesn't fix this; only rebase does. +- **Cross-phase bleeding** — developer writes to PROJECT-MEMORY.md in feat commits (not just documentation), bypassing the doc-phase serial protection entirely. + +Incidents this convention prevents: 2026-05-09 pyrycode Phase 3 batch (3 PRs stuck), 2026-05-10 pyrycode (#260/PR #266, #255/PR #259), 2026-05-11 v2 pipeline (4 stranded PRs on `docs/PROJECT-MEMORY.md`). Per-ticket files eliminate the hot line entirely — two cycles never touch the same file, stale-branch conflicts impossible by construction. See `pyrycode/agent-dispatcher#1` for the rollout history. diff --git a/docs/lessons.md b/docs/lessons.md index e40f6ca..7c94f13 100644 --- a/docs/lessons.md +++ b/docs/lessons.md @@ -1,6 +1,10 @@ -# Lessons +# Lessons (frozen) -Gotchas worth carrying forward. Each entry: what bit us (or nearly did), and what we do about it. +**Frozen 2026-05-11.** This file is historical reference only. New lessons go into the relevant ticket's `docs/knowledge/codebase/.md` under a "Lessons learned" section. + +The pre-2026-05-11 entries below were collected before the per-ticket file convention. They remain unchanged so existing cross-references still resolve. Future tickets do not append here — the per-ticket file convention eliminates the shared-append conflict surface (same fix shape as `PROJECT-MEMORY.md`'s sections, frozen the same day). + +--- ## `time.Timer.Stop()` returns false if the func has already started — a mutex alone won't save you