diff --git a/HOW_WE_WORK.md b/HOW_WE_WORK.md index fd75c90d11..b6682339fc 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; 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) | +| 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 reply-drafting discussion records unstaged and refuses messages mentioning a drafted/posted reply; citing an issue for a fix is fine (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/rules/INDEX.md b/rules/INDEX.md index a8e3f765b7..0f7684f322 100644 --- a/rules/INDEX.md +++ b/rules/INDEX.md @@ -144,4 +144,4 @@ R118 | Tool stop: SIGINT, wait, then restore | - | active | PhaseEnd_Phase37 can 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 +R120 | Issue reply drafts are never committed or mentioned in commit text | - | active | developer 2026-09-30 diff --git a/rules/R120.md b/rules/R120.md index d48bf27bb8..a40615348b 100644 --- a/rules/R120.md +++ b/rules/R120.md @@ -1,12 +1,11 @@ -# R120 — GitHub issue discussions are never committed or named in commit logs +# R120 — Issue reply drafts are never committed or mentioned in commit text 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. +**Rule.** Replies we draft on the maintainer's behalf to a GitHub issue, PR or reporter, and discussion records that exist only to ingest a reporter's message and draft a reply, are never committed, and no commit message, plan note, log or summary says a reply was drafted or posted. Fix work prompted by an issue is fine: the fix, its task, and commit messages citing the issue number or URL as the reason are committed normally. -**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. +**Why.** The repository is public. Outward text is written by the maintainer, like a developer, per `docs/gen3-standards.md`; an agent's reply draft is not that text, and a committed draft or a note that one was drafted would publish it as ours. 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. +- A `discuss` agent whose topic is reading a reporter's message and drafting a reply writes its record and the draft under `.run/` (gitignored), never under `phase-ends/`. +- `tools/commit_task.sh` leaves unstaged a discussion record carrying an `Outward: yes` line or a reply/reporter topic, and refuses a commit message that mentions a drafted or posted reply, comment or response. +- A reply-drafting record already committed is untracked with `git rm --cached` and gitignored; history is rewritten only on the developer's decision, on a clean tree. diff --git a/tools/commit_task.sh b/tools/commit_task.sh index 494a0eaf73..7f876159cb 100644 --- a/tools/commit_task.sh +++ b/tools/commit_task.sh @@ -44,10 +44,12 @@ 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)" +# R120: reply drafts to an issue/PR/reporter are never mentioned in a commit message, and +# reply-drafting discussion records (`Outward: yes`, or a reply/reporter topic) are never committed. +# A fix that cites an issue number or URL is fine. +REPLY='(\b(draft(ed|s)?|post(ed|s)?)\b.{0,40}\b(repl(y|ies)|comment|response)\b|\b(repl(y|ies)|response)\b.{0,40}\b(issue|PR|pull request|reporter)\b|\bissue[-_ ]?#?[0-9]*[-_ ]repl(y|ies)\b)' +OUTWARD="(^Outward: *yes|^# D[0-9]+ .*\b(repl(y|ies)|reporter)\b|$REPLY)" +printf '%s' "$FULL" | grep -qiE "$REPLY" && refuse "message mentions a drafted/posted reply (R120)" ROOT="$(find_root)" cd "$ROOT" || refuse "cannot cd to $ROOT" @@ -106,11 +108,11 @@ 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). +# R120: a reply-drafting 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)" + echo "left out: $f (reply-drafting discussion record; R120 keeps it local)" fi done