diff --git a/.github/AI_POLICY.md b/AI_POLICY.md similarity index 100% rename from .github/AI_POLICY.md rename to AI_POLICY.md diff --git a/.github/CONTRIBUTING.md b/CONTRIBUTING.md similarity index 100% rename from .github/CONTRIBUTING.md rename to CONTRIBUTING.md diff --git a/active.md b/active.md index b02c1fdf..884719c1 100644 --- a/active.md +++ b/active.md @@ -61,4 +61,3 @@ paper is public, and replace the placeholder `**Supports:**` bullet with real claims. - repos: - PyAutoMemory: feature/vincken-2026-bib-placeholder - - PyAutoMemory: feature/vincken-2026-bib-placeholder diff --git a/docs/pyautobrain/spawn_spec.md b/docs/pyautobrain/spawn_spec.md index 12258403..d96102d4 100644 --- a/docs/pyautobrain/spawn_spec.md +++ b/docs/pyautobrain/spawn_spec.md @@ -35,7 +35,7 @@ deliberately, never silently shipped into a template. | 1b | `tests/**` | KEEP verbatim (generator machinery, same class as rule 1; Memory's table already does this). The privacy test in particular must travel with the generator it guards — a spawned org that inherits `spawn.py` without `test_spawn_privacy.py` can reintroduce the rule-5 leak (issue #118) silently | | 2 | `REFERENCE.md`, `AGENTS.md`, `CLAUDE.md`, `LICENSE`, `ROUTING.md`, `.gitignore` | KEEP verbatim | | 3 | `README.md` | KEEP verbatim (already generic post-Phase-1) | -| 3b | `.github/AI_POLICY.md`, `.github/CONTRIBUTING.md` (moved under `.github/` in the 2026-08 root declutter, #248 — GitHub resolves community-health files there) | KEEP with owner substitution — both are org-wide pointer docs: generic prose that names the owning org and links the canonical copy inside that org's `PyAutoScientist`. They take the same `PyAutoLabs` → `YOURORG` substitution as rule 9 rather than a verbatim KEEP; verbatim would stamp a literal "Contributing to PyAutoLabs" into a template spawned for another org | +| 3b | `AI_POLICY.md`, `CONTRIBUTING.md` (root — the 2026-08 `.github/` declutter of #248 was undone on 2026-08-20, #253: dashboards are the primary interface now, so root scannability no longer justifies the split placement) | KEEP with owner substitution — both are org-wide pointer docs: generic prose that names the owning org and links the canonical copy inside that org's `PyAutoScientist`. They take the same `PyAutoLabs` → `YOURORG` substitution as rule 9 rather than a verbatim KEEP; verbatim would stamp a literal "Contributing to PyAutoLabs" into a template spawned for another org | | 4 | `repos.yaml` | SUBSTITUTE → the **template body map**: the five organ rows kept with `github:` owner replaced by `YOURORG`; all live satellite rows replaced by the PyAutoProject family rows (`PyAutoProject` category `library`, `autoproject_workspace` category `workspace`, `autoproject_workspace_test` category `workspace_test`) + a commented-out `autoproject_assistant` row ("uncomment when the clone agent seeds it") | | 5 | `active.md`, `planned.md`, `parked.md`, `condemned.md`, `ideas.md`, `queue.md` | EMPTY → header line + schema pointer comment only (e.g. `# Active Tasks` + ``). **The header is GENERATED, never read from the live file** — `planned.md` and `ideas.md` carry no H1 at all, so "keep line 1" yields a registry entry (issue #118), and a heading-shape test cannot save it either: a task slug written as an H2 is a structurally valid heading. Each file's title lives in `EMPTY_TITLES`; an EMPTY-ruled file with no entry is an UNMATCHED-class human decision, not a guess | | 5b | `autonomy_log.md` | SPECIAL → the ledger's schema header (H1, the prose explaining the log, the `Outcome ∈ …` legend, the table header row and separator), held as the `AUTONOMY_LOG_TEMPLATE` asset. Not rule 5: it is `SPECIAL`, not in `EMPTY_TITLES`, and carries prose and a table rather than a title plus schema-pointer comment. Like rule 5 it is **GENERATED, never parsed** (issue #123): the old implementation copied lines until one started with `\|---`, so a row inserted above the separator was copied, and a cosmetically reformatted separator (`\| --- \|`) meant the break never fired — 231 live task records into a public repo. The canary scan is no backstop: a leaked row with no dataset or person token scans clean. A test asserts the live ledger still starts with the constant, so generating cannot silently go stale | @@ -57,7 +57,7 @@ deliberately, never silently shipped into a template. | # | Pattern | Action | |---|---------|--------| | 1 | `bibliography/README.md`, `scripts/`, `tests/`, `Makefile`, `LICENSE`, `AGENTS.md`, `CLAUDE.md`, `.gitignore` | KEEP verbatim (tooling + schema + policy — scripts/tests are the citation-validation + knowledge-board tooling the Makefile drives; the former `bibliography/*.py` pattern matched nothing and was retired in #32) | -| 1b | `.github/AI_POLICY.md`, `.github/CONTRIBUTING.md` (moved under `.github/` in the 2026-08 root declutter, #32 — matches the other organs) | KEEP with owner substitution — same org-wide pointer docs as the Mind table's rule 3b | +| 1b | `AI_POLICY.md`, `CONTRIBUTING.md` (root — the #32 `.github/` move undone with the Mind's, #253) | KEEP with owner substitution — same org-wide pointer docs as the Mind table's rule 3b | | 2 | `bibliography/*.bib` and any bibliography data files | EMPTY → file kept with header comment ("populated by your literature") | | 3 | `wiki/CLAUDE.md` (the shared schema) | KEEP verbatim — since the wiki/ restructure (PyAutoMemory#24) the schema is a single domain-neutral file at `wiki/CLAUDE.md`, kept canary-clean at the source (its examples carry no instance tokens), so spawn no longer maintains a duplicate schema asset | | 4 | `wiki/*` (all live sub-wikis, all pages) | DROP; generate instead ONE `wiki/example/` containing a slim scope-only `CLAUDE.md` (the schema is inherited from rule 3, not copied), an `index.md` skeleton listing zero sources, and one `sources/EXAMPLE_stub.md` demonstrating the stub format (hand-written once, stored inside spawn as a heredoc/template asset — not copied from live content) | diff --git a/scripts/spawn.py b/scripts/spawn.py index d992d584..1a2bc135 100644 --- a/scripts/spawn.py +++ b/scripts/spawn.py @@ -77,7 +77,7 @@ # template spawned for somebody else's org. They live under .github/ (the # 2026-08 root declutter, #248) — GitHub resolves community-health files # there, and the Mind's root stays the task ledger. - (".github/AI_POLICY.md", "KEEP_SUB"), (".github/CONTRIBUTING.md", "KEEP_SUB"), + ("AI_POLICY.md", "KEEP_SUB"), ("CONTRIBUTING.md", "KEEP_SUB"), ("repos.yaml", "SPECIAL:body_map"), ("active.md", "EMPTY"), ("planned.md", "EMPTY"), ("epics.md", "EMPTY"), ("parked.md", "EMPTY"), ("condemned.md", "EMPTY"), ("ideas.md", "EMPTY"), ("queue.md", "EMPTY"), @@ -146,7 +146,7 @@ ("AGENTS.md", "KEEP"), ("CLAUDE.md", "KEEP"), (".gitignore", "KEEP"), # Same org-wide pointer docs as MIND_RULES — owner substitution; under # .github/ since the 2026-08 root declutter (all five organs match). - (".github/AI_POLICY.md", "KEEP_SUB"), (".github/CONTRIBUTING.md", "KEEP_SUB"), + ("AI_POLICY.md", "KEEP_SUB"), ("CONTRIBUTING.md", "KEEP_SUB"), ("bibliography/*", "EMPTY"), # Same fail-closed discipline as MIND_RULES (spec rule 9d). validate.yml is # self-contained — no schedule, no secrets, no sibling repos — so it clears diff --git a/tests/test_spawn_privacy.py b/tests/test_spawn_privacy.py index 87351372..535f5267 100644 --- a/tests/test_spawn_privacy.py +++ b/tests/test_spawn_privacy.py @@ -349,8 +349,8 @@ def fake_workspace(tmp_path): "README.md": "# Mind\n", "AGENTS.md": "# Agents\n", "REFERENCE.md": "# Ref\n", "ROUTING.md": "# Routing\n", "CLAUDE.md": "# Claude\n", "LICENSE": "MIT\n", ".gitignore": "tmp/\n", - ".github/AI_POLICY.md": "PyAutoLabs policy\n", - ".github/CONTRIBUTING.md": "Contributing to PyAutoLabs\n", + "AI_POLICY.md": "PyAutoLabs policy\n", + "CONTRIBUTING.md": "Contributing to PyAutoLabs\n", "repos.yaml": f"repos:\n {LIVE_MARKER}: x\n", "scripts/status.sh": "echo hi\n", "complete/AGENTS.md": "# schema\n", @@ -371,8 +371,8 @@ def fake_workspace(tmp_path): "README.md": f"# Memory\n{LIVE_MARKER}\n", "AGENTS.md": "# Agents\n", "CLAUDE.md": "# Claude\n", "LICENSE": "MIT\n", ".gitignore": "tmp/\n", "Makefile": "all:\n", - ".github/AI_POLICY.md": "PyAutoLabs policy\n", - ".github/CONTRIBUTING.md": "Contributing to PyAutoLabs\n", + "AI_POLICY.md": "PyAutoLabs policy\n", + "CONTRIBUTING.md": "Contributing to PyAutoLabs\n", "bibliography/refs.bib": f"@article{{{LIVE_MARKER}2018}}\n", "bibliography/aliases.yaml": f"{LIVE_MARKER}: x\n", "bibliography/README.md": "# Bib\n", diff --git a/tests/test_spawn_template_contract.py b/tests/test_spawn_template_contract.py index 46867e7c..79184898 100644 --- a/tests/test_spawn_template_contract.py +++ b/tests/test_spawn_template_contract.py @@ -66,7 +66,7 @@ def _fake_repo(root, files): "README.md": "# Mind\n", "AGENTS.md": "# A\n", "CLAUDE.md": "# C\n", "REFERENCE.md": "# R\n", "ROUTING.md": "# Ro\n", "LICENSE": "MIT\n", ".gitignore": "tmp/\n", - ".github/AI_POLICY.md": "p\n", ".github/CONTRIBUTING.md": "c\n", + "AI_POLICY.md": "p\n", "CONTRIBUTING.md": "c\n", "repos.yaml": "repos: {}\n", "active.md": "# Active Tasks\n", "planned.md": "# Planned\n", "parked.md": "# Parked\n", "condemned.md": "# Condemned\n", @@ -208,7 +208,7 @@ def test_a_new_mind_workflow_is_a_human_decision(tmp_path): MINIMAL_MEMORY = { "README.md": "# Mem\n", "AGENTS.md": "# A\n", "CLAUDE.md": "# C\n", "LICENSE": "MIT\n", ".gitignore": "tmp/\n", "Makefile": "all:\n", - ".github/AI_POLICY.md": "p\n", ".github/CONTRIBUTING.md": "c\n", + "AI_POLICY.md": "p\n", "CONTRIBUTING.md": "c\n", "index.md": "# Index\n", "reading-queue.md": "# Reading queue\n", "bibliography/README.md": "# Bib\n", "wiki/CLAUDE.md": "# schema\n",