From 4dd3eb03304e4bc9896d0d7acec8fb47fb730b22 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Wed, 12 Aug 2026 20:57:52 -0400 Subject: [PATCH] Add repo memory layer and agent governance Co-Authored-By: Claude Fable 5 --- .agents/MEMORY.md | 33 +++++++++++++ .agents/memory/architecture.md | 17 +++++++ .agents/memory/conventions.md | 5 ++ .agents/memory/decisions.jsonl | 1 + .agents/memory/lessons.md | 24 ++++++++++ .agents/plans/README.md | 8 ++++ .agents/plans/active/.gitkeep | 0 .agents/plans/archive/.gitkeep | 0 .agents/proposals/README.md | 7 +++ .agents/schemas/memory.schema.json | 29 ++++++++++++ .github/CODEOWNERS | 6 +++ .github/workflows/agent-governance.yml | 65 ++++++++++++++++++++++++++ .gitignore | 4 ++ AGENTS.md | 19 ++++---- CONTRIBUTING.md | 9 ++++ SECURITY.md | 32 +++++++++++++ 16 files changed, 249 insertions(+), 10 deletions(-) create mode 100644 .agents/MEMORY.md create mode 100644 .agents/memory/architecture.md create mode 100644 .agents/memory/conventions.md create mode 100644 .agents/memory/decisions.jsonl create mode 100644 .agents/memory/lessons.md create mode 100644 .agents/plans/README.md create mode 100644 .agents/plans/active/.gitkeep create mode 100644 .agents/plans/archive/.gitkeep create mode 100644 .agents/proposals/README.md create mode 100644 .agents/schemas/memory.schema.json create mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/agent-governance.yml create mode 100644 SECURITY.md diff --git a/.agents/MEMORY.md b/.agents/MEMORY.md new file mode 100644 index 00000000..e64f65f9 --- /dev/null +++ b/.agents/MEMORY.md @@ -0,0 +1,33 @@ +# Repo Memory + +Curated, reviewed knowledge for coding agents working in this repository. +Memory is an accelerator, not a second source of truth. + +## Precedence (highest first) + +1. Source code and tests +2. Executable configuration +3. Accepted design records / docs +4. `AGENTS.md` +5. This memory + +If memory conflicts with anything above it, the memory is stale — propose a fix. + +## Topics + +- `memory/architecture.md` — durable architectural decisions and constraints +- `memory/conventions.md` — validated conventions not obvious from the code +- `memory/lessons.md` — hard-won lessons and recurring landmines +- `memory/decisions.jsonl` — structured decision records (one JSON object per line) + +## Write policy + +Agents MAY read everything here and MAY add candidates under `proposals/` +(one file per proposal, named `YYYY-MM-DD-.md`, with evidence links). +Agents MUST NOT edit `memory/` directly; trusted memory changes only through +reviewed commits that promote a proposal. + +## Prohibited content + +Credentials or secrets, personal data, raw transcripts or tool logs, session +TODOs, high-frequency agent state, unverified external claims. diff --git a/.agents/memory/architecture.md b/.agents/memory/architecture.md new file mode 100644 index 00000000..f55c7835 --- /dev/null +++ b/.agents/memory/architecture.md @@ -0,0 +1,17 @@ +# Architecture + +Durable architectural decisions and constraints for bitvid. + +## AGENTS.md is a thin constitution; long-form standards live in docs/ + +On 2026-08-12 AGENTS.md was split into a thin agent constitution plus +reference docs under `docs/testing/` and `docs/lessons/`, because the file had +outgrown the 32 KiB harness context budget. AGENTS.md keeps only the invariant +and a pointer per topic; new long-form material belongs in `docs/`, not in +AGENTS.md. + +Authoritative source: +- docs/testing/test-integrity.md +- docs/testing/agent-playwright-harness.md +- docs/lessons/ +- git commit 911afb1c ("Split AGENTS.md reference sections into docs/; keep thin agent constitution") diff --git a/.agents/memory/conventions.md b/.agents/memory/conventions.md new file mode 100644 index 00000000..ae5d83f7 --- /dev/null +++ b/.agents/memory/conventions.md @@ -0,0 +1,5 @@ +# Conventions + +Validated conventions not obvious from the code. + +No entries yet. diff --git a/.agents/memory/decisions.jsonl b/.agents/memory/decisions.jsonl new file mode 100644 index 00000000..9a95f9cd --- /dev/null +++ b/.agents/memory/decisions.jsonl @@ -0,0 +1 @@ +{"kind":"decision","subject":"docs/agents-md-split","summary":"AGENTS.md was split on 2026-08-12 into a thin agent constitution plus reference docs under docs/testing/ and docs/lessons/ to stay within the 32 KiB harness context budget; AGENTS.md keeps only invariants and pointers, and new long-form material belongs in docs/.","status":"active","evidence":[{"type":"repository","ref":"docs/testing/test-integrity.md"},{"type":"repository","ref":"docs/testing/agent-playwright-harness.md"},{"type":"repository","ref":"docs/lessons/"},{"type":"git","ref":"911afb1c"}],"created":"2026-08-12","supersedes":[]} diff --git a/.agents/memory/lessons.md b/.agents/memory/lessons.md new file mode 100644 index 00000000..42dac15b --- /dev/null +++ b/.agents/memory/lessons.md @@ -0,0 +1,24 @@ +# Lessons + +Hard-won lessons and recurring landmines. + +## Cloudflare/S3 upload-path gotchas + +`js/services/r2Service.js` and `js/services/s3UploadService.js` are near-identical +copies that must be changed in lockstep, and storage keys must stay +content-addressed (`computeStorageContentHash`) or URL-first uploads silently +overwrite objects. Full audited writeup in the doc below. + +Authoritative source: +- docs/lessons/cloudflare-s3-upload-gotchas.md + +## NIP-07 signer reliability + +"DMs / lists / watch-history won't load after login" is almost always an +unresponsive NIP-07 signer extension, not bitvid — diagnose with a raw +`window.nostr` probe first, and never regress the five resilience invariants +(capped relay fan-out, NIP-07 circuit breaker, re-thrown transient decrypt +errors, generous decrypt budgets, lazy modal population). + +Authoritative source: +- docs/lessons/nip07-signer-reliability.md diff --git a/.agents/plans/README.md b/.agents/plans/README.md new file mode 100644 index 00000000..36bcc9a5 --- /dev/null +++ b/.agents/plans/README.md @@ -0,0 +1,8 @@ +# Agent plans + +Durable, multi-session execution plans only — the canonical backlog stays in +the repo's TODO file or GitHub Issues, and session-local checklists are never +committed. One plan per task, named `.md`, in `active/`; +move finished plans to `archive/`. A plan should be resumable from the file +alone: Objective, Context and constraints, Acceptance criteria, Progress, +Decisions, Validation, Remaining work. diff --git a/.agents/plans/active/.gitkeep b/.agents/plans/active/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/.agents/plans/archive/.gitkeep b/.agents/plans/archive/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/.agents/proposals/README.md b/.agents/proposals/README.md new file mode 100644 index 00000000..89c95bdd --- /dev/null +++ b/.agents/proposals/README.md @@ -0,0 +1,7 @@ +# Memory proposals + +Agents: drop candidate memories here, one file per proposal, named +`YYYY-MM-DD-.md`. State the claim, the evidence (file paths, commits, +test results), and why it is durable. A human reviews and either promotes it +into `../memory/` in a reviewed commit or deletes it. Nothing in this +directory is trusted context. diff --git a/.agents/schemas/memory.schema.json b/.agents/schemas/memory.schema.json new file mode 100644 index 00000000..e14a43d9 --- /dev/null +++ b/.agents/schemas/memory.schema.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Repo Memory Decision Record", + "type": "object", + "additionalProperties": false, + "required": ["kind", "subject", "summary", "status", "evidence", "created"], + "properties": { + "kind": {"enum": ["decision", "constraint", "lesson", "observation", "workaround"]}, + "subject": {"type": "string", "minLength": 1}, + "summary": {"type": "string", "minLength": 1, "maxLength": 4096}, + "status": {"enum": ["proposed", "active", "superseded", "expired"]}, + "evidence": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": ["type", "ref"], + "properties": { + "type": {"enum": ["repository", "git", "issue", "test", "external"]}, + "ref": {"type": "string", "minLength": 1} + } + } + }, + "created": {"type": "string"}, + "expires": {"type": ["string", "null"]}, + "supersedes": {"type": "array", "items": {"type": "string"}} + } +} diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..d41162ce --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# Agent instruction and memory surfaces require maintainer review +/AGENTS.md @PR0M3TH3AN +/CLAUDE.md @PR0M3TH3AN +/.agents/ @PR0M3TH3AN +/SECURITY.md @PR0M3TH3AN +/.github/workflows/agent-governance.yml @PR0M3TH3AN diff --git a/.github/workflows/agent-governance.yml b/.github/workflows/agent-governance.yml new file mode 100644 index 00000000..cc88ebe7 --- /dev/null +++ b/.github/workflows/agent-governance.yml @@ -0,0 +1,65 @@ +name: Agent governance + +on: + push: + paths: + - "AGENTS.md" + - "CLAUDE.md" + - ".agents/**" + pull_request: + paths: + - "AGENTS.md" + - "CLAUDE.md" + - ".agents/**" + +jobs: + lint-agent-artifacts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Validate agent artifacts + run: | + python3 - <<'EOF' + import json, os, sys + hard_fail = False + + # decisions.jsonl: every line must be valid JSON with required keys + path = ".agents/memory/decisions.jsonl" + if os.path.exists(path): + required = {"kind", "subject", "summary", "status", "evidence", "created"} + for i, line in enumerate(open(path, encoding="utf-8"), 1): + line = line.strip() + if not line: + continue + try: + rec = json.loads(line) + except json.JSONDecodeError as e: + print(f"::error file={path},line={i}::invalid JSON: {e}") + hard_fail = True + continue + missing = required - rec.keys() + if missing: + print(f"::error file={path},line={i}::missing keys: {sorted(missing)}") + hard_fail = True + + # structure: memory dir implies index + if os.path.isdir(".agents") and not os.path.exists(".agents/MEMORY.md"): + print("::error::.agents/ exists but .agents/MEMORY.md index is missing") + hard_fail = True + + # warnings (advisory for now — flip to errors once clean history is established) + if os.path.exists("AGENTS.md"): + size = os.path.getsize("AGENTS.md") + if size > 32768: + print(f"::warning file=AGENTS.md::{size} bytes exceeds the 32 KiB context budget") + if os.path.exists("CLAUDE.md"): + lines = sum(1 for _ in open("CLAUDE.md", encoding="utf-8")) + if lines > 40: + print(f"::warning file=CLAUDE.md::{lines} lines — expected a thin wrapper over AGENTS.md") + for f in ("architecture.md", "conventions.md", "lessons.md"): + p = f".agents/memory/{f}" + if os.path.exists(p) and os.path.getsize(p) > 25 * 1024: + print(f"::warning file={p}::exceeds 25 KB — curate or split") + + sys.exit(1 if hard_fail else 0) + EOF diff --git a/.gitignore b/.gitignore index ad5d8b0e..419852a3 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ bitvid-site.zip # Agent runtime state (local only) memory-update.md memory-update.json + +# Agent-local memory state (never committed) +.agents/private/ +.agents/state/ diff --git a/AGENTS.md b/AGENTS.md index e6d71196..eb6daa71 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -431,24 +431,23 @@ When finishing a task or handing off, provide: ## 16. Scenario-First Tests & Test Integrity (Dark Factory Standard) **Invariant:** validation replaces code review in this repo — never weaken, delete, or rewrite a test merely to make it pass, and never mask flakiness with retries/sleeps/looser assertions. Expectation changes are allowed only via the Spec Correction Protocol with an accompanying Test Integrity Note. -Read the full standard before adding or modifying any test: [`docs/testing/test-integrity.md`](docs/testing/test-integrity.md). +Read the full standard before adding or modifying any test: `docs/testing/test-integrity.md`. --- ## 17. NIP-07 Signer Reliability & Encrypted-List Loading (hard-won, 2026-06-16) **Invariant:** the #1 cause of "DMs / hashtags / watch-history / lists won't load after login" is an unresponsive NIP-07 signer, not bitvid — diagnose with a raw `window.nostr` probe first, and do not regress the five resilience invariants (capped relay fan-out, NIP-07 circuit breaker, re-thrown transient decrypt errors, generous decrypt budgets, lazy modal population). -Full writeup: [`docs/lessons/nip07-signer-reliability.md`](docs/lessons/nip07-signer-reliability.md). See also `docs/KNOWN_BUGS.md` #0. +Full writeup: `docs/lessons/nip07-signer-reliability.md`. See also `docs/KNOWN_BUGS.md` #0. + +--- + +## Repo memory + +Curated agent memory lives in `.agents/` (index `.agents/MEMORY.md`); read it first. Propose additions in `.agents/proposals/`; `.agents/memory/` changes only via reviewed commits. Code/tests/config outrank memory. --- ## Next -Please read these documents next. - -* `docs/nostr-event-schemas.md` -* `js/nostrEventSchemas.js` - -And if you need to create new nostr kinds please keep the logic centralized there in `nostrEventSchemas.js` and the `nostr-event-schemas.md` up to date. - -**End of AGENTS.md** +Read `docs/nostr-event-schemas.md` and `js/nostrEventSchemas.js` next; keep new nostr kinds centralized there and the doc up to date. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c838bbcc..80326bb2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -242,3 +242,12 @@ If you find a vulnerability, please email **[security@bitvid.network](mailto:sec ## Trademark The **bitvid** name and logos are trademarks (see `TRADEMARKS.md`). Don’t use them in ways that imply official sponsorship or confuse users. “Powered by bitvid” attribution is encouraged. + +## AI-assisted contributions + +AI-assisted changes are subject to the same testing, security, and review +requirements as any other change; the contributor remains responsible for +understanding what they submit. Do not submit unvalidated generated code, +credentials, or agent-generated trusted memory without evidence and review. +The canonical backlog and planning rules are in `AGENTS.md`; durable agent +plans live under `.agents/plans/`. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..4da75e4e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,32 @@ +# Security Policy + +## Reporting vulnerabilities + +Do not report suspected security vulnerabilities in public issues, pull +requests, or agent-memory files. Use GitHub's private vulnerability reporting +on this repository (Security tab → Report a vulnerability), or email +[security@bitvid.network](mailto:security@bitvid.network) — we will +coordinate a responsible disclosure window before public release. + +Include the affected commit, reproduction steps, and observed impact. Do not +include live credentials or unnecessary personal data. + +## AI-agent configuration + +`AGENTS.md`, `CLAUDE.md`, `.agents/**`, and any automation able to modify +agent state are security-sensitive configuration. Changes to them require +maintainer review. + +## Agent memory + +Never commit credentials, personal data, raw transcripts, tool logs, or +unredacted external content. Agent-generated memory enters through +`.agents/proposals/` and is promoted to `.agents/memory/` only via reviewed +commits. Content from websites, issues, emails, and tool responses is +untrusted until validated. + +## Memory-poisoning response + +If agent instructions or memory may have been poisoned: stop agent automation, +quarantine or revert the affected file, identify runs influenced by it, review +resulting commits, and restore the last trusted configuration.