diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e00e853..4cbe60da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Notable changes to house-rules. Versions follow [semantic versioning](https://se ## Unreleased +- A delegated worker never gives the user an offer or a question card: `rules/core.md` § End of every reply (which every session reads; the Offers replacements of `coded-offers` and `model-default-questions` cannot drop it) says it returns the choice, with options and a recommendation, in its final report to its parent, which decides or asks the user. The brief-contents rules in `rules/references/coordination-and-isolation.md` (default rules), `rules/references/multi-agent.md` and the `multi-agent` modifier say to put that in every worker's brief, and the lines that treated a child's question as legitimate (the T3 delegated-task wake and the two-minute check) now treat it as a brief that lacked the rule or a child that broke it; the `question-cards` modifier's answer-a-delegated-card line says it applies only when one was raised despite the rule. - The T3 steps that read a thread or list threads state their own start, `limit` and `maxCharsPerItem`, so they read the same on T3 builds that differ in order and defaults (a read with no `afterPosition` returns the oldest items first on older builds and the newest first on newer ones; pingdotgg/t3code #33428): `rules/references/multi-agent.md` (the child check, the progress and end-of-thread reads, a finished child's result) and `hr-handoff`'s `references/successor-thread.md` (the header read for `projectId`, the list and the read-back after a settle). A header-only read is `limit: 1`, `maxCharsPerItem: 1`, `runLimit: 1`; the end of a thread is read from `afterPosition` max(0, `itemCount` minus 60), highest `position` newest. - `hr-sqlite`'s `references/evidence.md` adds a rerun of three measured rows (planner statistics after `PRAGMA optimize`, `synchronous` FULL against NORMAL, and `backup()` against `VACUUM INTO`) on Node 26.13.1 with SQLite 3.54.1. The first figures stay with their versions; the section says the new host, disk and data differ, so the gaps are not attributable to Node or SQLite. Planner statistics still fixed the query (20.4, 6.7 and 8.3 ms to 0.0059 ms); the `synchronous` gap is 7.5 times on this disk, not 87. - `hr-diagnosing-bugs`' `references/evidence-discipline.md` adds three rules for a chain of causes: label each claim measured, derived or inferred (an inference names the observation or report it rests on), test each causal link on timing, mechanism, magnitude and necessity (a case where the trigger fired without the cause, or a probe that removes it) and treat a refuted link as a dead theory unless a second cause could produce the same effect, and re-measure inherited numbers, with claims about people or ownership held to the same evidence as claims about systems. `SKILL.md` adds a stop rule for tracing a failure back cause by cause: stop at the step that names something you can change that would have prevented it (what produced a state that should never exist, or the code that mishandles a legitimate one), and merge steps past about seven. diff --git a/rules/core.md b/rules/core.md index eee6f30f..8d3c8ab5 100644 --- a/rules/core.md +++ b/rules/core.md @@ -32,6 +32,10 @@ or empty result is not one: diagnose, then retry or go around. Risky or irreversible actions, like publishing or pushing to a shared branch, need the user's confirmation unless already directed. +A delegated worker never gives the user an offer or a question card, so case 2 +does not apply to it: it returns the choice, with options and a recommendation, +in its final report to its parent, which decides or asks the user. + ## Offers Ask the way your host and model normally ask. When your host gives you a diff --git a/rules/modifiers/multi-agent.md b/rules/modifiers/multi-agent.md index fe9167e9..0dbf5889 100644 --- a/rules/modifiers/multi-agent.md +++ b/rules/modifiers/multi-agent.md @@ -16,7 +16,8 @@ schedule, read [the agent-work procedure](../references/multi-agent.md). An incomplete worker report is a checkpoint. A worker with a background command or subagent still running is not done. Verify reports against evidence and use host durations or timestamps for elapsed time. Keep workers from delegating -further unless asked. Never fork a reviewer or panel seat: a fork inherits the +further unless asked. Say in each worker's brief that it never offers or asks the +user (§ End of every reply). Never fork a reviewer or panel seat: a fork inherits the author's reasoning, so it is not independent. Give implementers the task, file boundaries, public APIs and architectural diff --git a/rules/modifiers/question-cards.md b/rules/modifiers/question-cards.md index fb81ab41..8ac306d6 100644 --- a/rules/modifiers/question-cards.md +++ b/rules/modifiers/question-cards.md @@ -40,6 +40,6 @@ chose text only (the opt-out above). hosts it arrives as a new turn. With no such tool, or when the tool fails, send the text offer alone and call no -substitute. When you answer a card a delegated agent raised, key each answer by +substitute. When you answer a card a delegated agent raised despite § End of every reply, key each answer by the question id in the request; some hosts end that agent's first run while its card waits, so wait for the run the answer starts. diff --git a/rules/references/coordination-and-isolation.md b/rules/references/coordination-and-isolation.md index 7f32af77..8ea6a881 100644 --- a/rules/references/coordination-and-isolation.md +++ b/rules/references/coordination-and-isolation.md @@ -25,4 +25,4 @@ directory is your own checkout. Run a long job under a supervisor that outlives the session and reports how it ended (a status record and a message to the thread that owns the job, with the job's output kept somewhere that survives the session), so a session reload or crash does not lose the result: no bare background shell and no detached unit without a reporter; the host supplies the command, and where it supplies none, run the job in the foreground or tell the user what is missing instead of detaching it. -Keep small or tightly coupled tasks local. Use subagents for bounded investigations or reviews; they stay read-only when they share your directory. Delegate implementation only when authorized, in its own worktree. Brief each worker with the user's request in their own words, then your reading of it, plus paths, constraints and what counts as done. Give each item a check that counts the effect (a delete sent exactly once), not "the button works". Number the items of a batch of feedback and give each an owner. Ask for evidence, checks run and open uncertainty. Weigh its evidence without redoing its investigation, but keep the required review and integration checks. Before building on a worker's claim that something is undefined, unused or missing, search the whole repository yourself. +Keep small or tightly coupled tasks local. Use subagents for bounded investigations or reviews; they stay read-only when they share your directory. Delegate implementation only when authorized, in its own worktree. Brief each worker with the user's request in their own words, then your reading of it, plus paths, constraints and what counts as done, and that it never offers or asks the user (§ End of every reply). Give each item a check that counts the effect (a delete sent exactly once), not "the button works". Number the items of a batch of feedback and give each an owner. Ask for evidence, checks run and open uncertainty. Weigh its evidence without redoing its investigation, but keep the required review and integration checks. Before building on a worker's claim that something is undefined, unused or missing, search the whole repository yourself. diff --git a/rules/references/multi-agent.md b/rules/references/multi-agent.md index d23a3587..7438fb9b 100644 --- a/rules/references/multi-agent.md +++ b/rules/references/multi-agent.md @@ -12,7 +12,9 @@ run instead of polling, and keep workers from delegating further unless asked; a fork is no exception. Brief a fresh worker by default: its brief is its only context, so state the -goal, the files and what is ruled out. Where the host offers a fork (a worker +goal, the files and what is ruled out, and that it never offers or asks the user +anything (§ End of every reply): it returns any choice, with options and a +recommendation, in its final report, and you decide or ask the user. Where the host offers a fork (a worker that inherits the whole conversation), use one only when the task depends on so many decisions from the conversation that a brief would be long or lose them; a fork costs more context and time than a brief. Never fork a reviewer or panel @@ -142,8 +144,10 @@ On a host whose delegated tasks run through T3 Code (`delegate_task`), the T3 se ### Reading a T3 delegated task's progress How a parent thread tells whether a task from `delegate_task` is working, waiting -or stuck. Two events wake the parent: the task finishing, and a user question -from the child, which also ends a `mode=wait` call early (`hasPendingQuestion`). +or stuck. Two events wake the parent: the task finishing, and a question +pending in the child (`hasPendingQuestion`), which also ends a `mode=wait` call +early. A brief forbids a child to ask the user, so a pending question means the +brief lacked that rule or the child broke it. An approval request does not send an asynchronous wake. A blocking `mode=wait` returns `pendingApproval` on servers with pingdotgg/t3code #20037. Read the fresh request in the child; that result grants no authority to approve it. @@ -189,8 +193,9 @@ for progress. (`t3_thread_read` with `limit: 1`, `maxCharsPerItem: 1`, `runLimit: 1`) must show `pendingRequestCount` 0 and an `updatedAt` after the start. A count above zero is not by itself a blockage: read the pending requests first (see - `pendingRequestCount` below) and handle a legitimate question instead of - interrupting. Interrupt with `t3_thread_interrupt` only when the child waits + `pendingRequestCount` below) and handle a question by deciding it or asking the + user, then answering it in the child, instead of interrupting; fix the brief. + Interrupt with `t3_thread_interrupt` only when the child waits on an approval nobody will see, or the stall check under "Is it stuck?" (pending requests, then the newest activity) confirms nothing is moving. Say so to the user and relaunch only after fixing the cause. Do not poll beyond this check while