diff --git a/.gitignore b/.gitignore index 8f9a80ff41..18aaa39333 100644 --- a/.gitignore +++ b/.gitignore @@ -594,3 +594,6 @@ unsloth_compiled_cache/ # Project Architect 3.0 .run/ __pycache__/ + +# R120: outward-thread discussion records stay local (untracked 2026-09-30) +phase-ends/current/discussions/D1.md diff --git a/HOW_WE_WORK.md b/HOW_WE_WORK.md index 68a1741433..fd75c90d11 100644 --- a/HOW_WE_WORK.md +++ b/HOW_WE_WORK.md @@ -36,7 +36,7 @@ PY = /usr/bin/python3 | cookbook_add | `bash tools/cookbook_add.sh` | add a cookbook entry and its index line | | phaseend_index | `PY tools/phaseend_index.py` | assemble, lint and archive a PhaseEnd | | genend_index | `PY tools/genend_index.py` | assemble and lint a GenerationEnd | -| commit_task | `bash tools/commit_task.sh` | the only commit path; explicit paths, no trailers, never pushes | +| commit_task | `bash tools/commit_task.sh` | the only commit path; explicit paths, no trailers, never pushes; auto-stages phase-ends/current/{tasks,logs,research,discussions,RECAP.md,TASK_PROGRESS.md}, but leaves outward-thread discussion records unstaged and refuses messages naming an issue/PR (R120) | | run | `bash tools/run.sh` | any command that may print >40 lines; `--bg` / `--wait` for long compute | | Every script under `tools/` (plus the two report make-targets), grouped by purpose — one line each. Deep HOW-TO is **not | `Every script under `tools/` (plus the two report make-targets), grouped by purpose — one line each. Deep HOW-TO is **not` | Every script under `tools/` (plus the two report make-targets), grouped by purpose — one line each. Deep HOW-TO is **not | diff --git a/phase-ends/current/discussions/D1.md b/phase-ends/current/discussions/D1.md deleted file mode 100644 index 17fd4673b4..0000000000 --- a/phase-ends/current/discussions/D1.md +++ /dev/null @@ -1,14 +0,0 @@ -# D1 — - (2026-09-29, session router) -Status: executed - -## Decisions -- (one line each) - -## Plan edits -- (plan_edit.py commands; executed: yes/no) - -## Open -- (unresolved items) - -## Deferred -- deferred: → diff --git a/rules/INDEX.md b/rules/INDEX.md index f93215b7e8..a8e3f765b7 100644 --- a/rules/INDEX.md +++ b/rules/INDEX.md @@ -143,3 +143,5 @@ R105 | No carry-audit section means audit blocked | - | active | PhaseEnd_Phase3 R118 | Tool stop: SIGINT, wait, then restore | - | active | PhaseEnd_Phase37 candidate, ratified 2026-09-29 R119 | Snapshot/refresh helpers refuse empty or shrunken input | - | active | PhaseEnd_Phase37 candidate, ratified 2026-09-29 + +R120 | GitHub issue discussions are never committed or named in commit logs | - | active | developer 2026-09-30 diff --git a/rules/R120.md b/rules/R120.md new file mode 100644 index 0000000000..d48bf27bb8 --- /dev/null +++ b/rules/R120.md @@ -0,0 +1,12 @@ +# R120 — GitHub issue discussions are never committed or named in commit logs +id: R120 · group: - · status: active · tags: - · origin: developer 2026-09-30 · added: 2026-09-30 + +**Rule.** Discussions of outward threads (GitHub issues and pull requests on this project or any other: the reporter's questions, our drafted replies, the reporter's handle, thread URLs or numbers) are never committed and never named in a commit message. + +**Why.** The repository is public. Outward text is written by the maintainer, like a developer, per `docs/gen3-standards.md`; an agent's drafts and analysis of a thread are not that text. An issue thread holds the reporter's own words and identity, which are not ours to republish in history. History cannot be un-published once pushed. + +**How.** +- A `discuss` agent on an outward-thread topic writes its record and any draft reply under `.run/` (gitignored), never under `phase-ends/`. +- A discussion record that does land in `phase-ends/*/discussions/` and names an issue/PR number or URL, or carries an `Outward: yes` line, is left unstaged by `tools/commit_task.sh`; the helper also refuses a commit message naming an issue/PR number or URL. +- Plan titles, plan change notes, logs and task summaries describe the technical work only (e.g. "formats.md corrections"), never the thread that prompted it. +- A record already committed is untracked with `git rm --cached` and gitignored; history is rewritten only on the developer's decision. diff --git a/tools/commit_task.sh b/tools/commit_task.sh index 7ee4f814b8..494a0eaf73 100644 --- a/tools/commit_task.sh +++ b/tools/commit_task.sh @@ -44,6 +44,10 @@ case "$MSG" in "$TASK:"*|"$TASK "*) FULL="$MSG";; *) FULL="$TASK: $MSG";; esac +# R120: outward threads (issue/PR number or URL, or an `Outward: yes` line in a discussion record) +# are never named in a commit message and their discussion records are never committed. +OUTWARD='(github\.com/[^ ]*/(issues|pull)/[0-9]|\b(issue|PR|pull request) ?#?[0-9]+\b|^Outward: *yes)' +printf '%s' "$FULL" | grep -qiE "$OUTWARD" && refuse "message names an outward thread (R120)" ROOT="$(find_root)" cd "$ROOT" || refuse "cannot cd to $ROOT" @@ -102,6 +106,14 @@ for f in $(git diff --cached --name-only -- "$PE/current/logs" "$PE/current/task fi done +# R120: an outward-thread discussion record stays unstaged in the tree (see OUTWARD above). +for f in $(git diff --cached --name-only --diff-filter=AM -- "$PE/current/discussions"); do + if [ -f "$f" ] && grep -qiE "$OUTWARD" -- "$f"; then + git reset -q -- "$f" || refuse "git reset $f failed" + echo "left out: $f (outward-thread discussion record; R120 keeps it local)" + fi +done + if git diff --cached --quiet; then refuse "nothing staged for $TASK" fi