Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/devteam/dashboard/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@
.ctx li, .qcard .d li, .qcard .e li { margin: 2px 0; }
.ctx code, .qcard h4 code { font: 12px var(--mono); }
.qcard .rewritten { color: var(--red-fg); font-weight: 600; margin: 0 0 8px; }
.qcard .again { margin: 0 0 8px; }
.choices { display: grid; gap: 6px; margin: 10px 0 8px; }
.choice { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: 4px 10px; align-items: start; text-align: left; height: auto; margin: 0; padding: 10px 12px; border-radius: 8px; border: 1px solid var(--line-2); background: var(--surface); color: var(--fg); font-weight: 400; cursor: pointer; }
.choice:hover { background: var(--hover); opacity: 1; }
Expand Down Expand Up @@ -1243,6 +1244,7 @@ <h3 style="margin-top:14px">Observations</h3>
${rankWhy(q)}
${q.thread && !copy ? `<div class="meta from-thread">From a thread: <a class="linkish" href="#talk/${encodeURIComponent(q.thread)}">${esc(q.thread_title || 'a conversation with the supervisor')}</a></div>` : ''}
${q.rewritten ? '<p class="rewritten">This question changed after you answered it, so that answer no longer counts. Read it again before you answer: the supervisor\'s log was rewritten, which it should never do.</p>' : ''}
${q.new_because ? `<p class="again"><b>Asked again because:</b> ${esc(q.new_because)}</p>` : ''}
<h4>${qinline(q.question, q.links)}</h4>
${q.context ? `<div class="ctx">${qblock(q.context, q.links)}</div>` : ''}
${(q.links || []).length ? `<div class="links"><span class="muted small">Look at:</span>${q.links.map(linkOf).join('')}</div>` : ''}
Expand Down Expand Up @@ -1476,6 +1478,7 @@ <h4>${qinline(q.question, q.links)}</h4>
${rankWhy(q)}
${q.thread ? `<div class="meta from-thread">From a thread: <a class="linkish" href="#talk/${encodeURIComponent(q.thread)}">${esc(q.thread_title || 'a conversation with the supervisor')}</a></div>` : ''}
${q.rewritten ? '<p class="rewritten">This question changed after you answered it, so that answer no longer counts. Read it again before you answer: the supervisor\'s log was rewritten, which it should never do.</p>' : ''}
${q.new_because ? `<p class="again"><b>Asked again because:</b> ${esc(q.new_because)}</p>` : ''}
<h4>${qinline(q.question, q.links)}</h4>
${q.context ? `<div class="ctx">${qblock(q.context, q.links)}</div>` : ''}
<div class="meta rv-pins">${rv.data ? `${esc(rv.data.rows)} rows${rv.data.proposals ? `, ${esc(rv.data.proposals)} with a proposal` : ''} · ` : ''}page <code>${esc(String(rv.page?.sha256 ?? '').slice(0, 12))}</code> ${ok ? '<span class="badge good">verified</span>' : `<span class="badge high">${esc(q.result_status || 'missing')}</span>`}${rv.allow_partial ? ' · partial answers allowed' : ''}${pr && pr.total ? ` · <span class="badge ${pr.done >= pr.total ? 'good' : 'medium'}">${esc(pr.done)} of ${esc(pr.total)} decided</span>` : ''}</div>
Expand Down
2 changes: 1 addition & 1 deletion docs/devteam/governance/constitution.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ A change is a one-way door if reverting it is expensive or impossible once shipp

An additive change is not a one-way door: a new field, a new optional type or value, a new endpoint or tool beside the old ones, nothing existing removed or narrowed. Decide it yourself and log the act; don't ask the owner to confirm it. When the owner has already answered a one-way door for a goal, that answer covers the tickets that implement it (cite it); never ask the same decision again (`process/supervisor.md` §6).

A one-way door needs an owner answer before the ticket's plan is approved (`act --class approve-plan` refuses without one), two independent final reviews, and `risk: high` on the ticket. The answer is a `one-way-door` question asked for the ticket (`--ticket`), or one the owner already answered for a goal the ticket's feature serves (`--goal`, asked while designing): the supervisor cites that one with `act --class approve-plan --approved <qid>`, and the latest approving plan review must say the plan stays inside what the answer covered (`quality.md` §3). An answer for another goal never counts.
A one-way door needs an owner answer before the ticket's plan is approved (`act --class approve-plan` refuses without one), two independent final reviews, and `risk: high` on the ticket. The answer is a `one-way-door` question (`--kind one-way-door`, or any question asked in class `one-way-door`) asked for the ticket (`--ticket`), or one the owner already answered for a goal the ticket's feature serves (`--goal`, asked while designing): the supervisor cites that one with `act --class approve-plan --approved <qid>`, and the latest approving plan review must say the plan stays inside what the answer covered (`quality.md` §3). An answer for another goal never counts.

## 5. Changing the rules

Expand Down
4 changes: 3 additions & 1 deletion docs/devteam/process/supervisor.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ devteam.mjs ask --kind one-way-door --class new-dependency --reasons owner-only

Rules: `--goal <g-id>` on every question that serves a goal, and `--ticket`/`--blocks` for the work it's about, so the goal and the board show it; one decision per question (a goal-definition question lists all of a goal's gaps as a form); lead with the decision; always a recommendation with your confidence; `--default` only when reversible and the class is on rung 2 or above (`ask` refuses it below, on a one-way door and on an owner-only class), applied at the deadline; `--blocks` every ticket that waits; `--class` and `--reasons` always, so the owner sees why it needs them.

**Never ask the owner the same decision twice.** If they have answered it (in the inbox, on the dashboard, or in chat, recorded with `answer --from-chat`), use that answer. When a kit change makes an earlier answer look insufficient, carry it forward instead of re-asking: for a goal change answered before questions recorded their change, `goal set <id> --approved <qid> --change '{…}'` with the change they chose, which is logged as a `carry-answer` act they can correct; for anything else, cite the answer (`--approved`, `--evidence`) and say so in the act. If the kit truly can't take the answer, raise it upstream rather than asking again.
**Never ask the owner a decision they have already made: cite the answer.** Re-asking is a failure, not caution. If they have answered it (in the inbox, on the dashboard, or in chat, recorded with `answer --from-chat`), use that answer. When a kit change makes an earlier answer look insufficient, carry it forward instead of re-asking: for a goal change answered before questions recorded their change, `goal set <id> --approved <qid> --change '{…}'` with the change they chose, which is logged as a `carry-answer` act they can correct; for anything else, cite the answer (`--approved`, `--evidence`) and say so in the act. If the kit truly can't take the answer, raise it upstream rather than asking again.

An earlier owner answer that covers the same decision is cited, never re-asked: `--approved <qid>`, and for a plan under a goal-level one-way door, the plan review's `- Goal-level door: <qid> covers this plan` line. That holds whatever kind or class it was asked as: a question asked in class `one-way-door` is a one-way door (`ask` records it as `--kind one-way-door`, and refuses another kind), so its answer is the one-way-door answer. `ask` refuses a decision (an owner-decision, a one-way door, a request for a secret already asked for) worded like one the owner answered in the same class about the same work (the same ticket, goal or feature), naming the answer to cite; an answer already used for its one call, or in a class that can't approve this one, is only mentioned. Only when something material changed since they answered (new facts, a wider scope, a cost they didn't see) ask again with `--new-because "<what changed>"`; the owner reads it first, as "Asked again because: …". A defaulted or unanswered question is not a decision the owner made, and never blocks one.

**Ask everything that is the owner's.** Every decision you lack the trust to make goes in the inbox, including every question a worker raised that you can't rule on yourself; nothing is held back to keep the inbox short. Never put a question to the owner through your harness's own blocking dialog (a pop-up or multiple-choice prompt that waits for an answer): it freezes your whole loop, so workers' messages, reviews and merges wait behind it, and it never reaches the Inbox. Every question to the owner is an `ask`, even one you also raise in your own session ("run this command, or tell me to …"): a question that exists only in your chat never reaches the Inbox, the dashboard or the owner's notifications, and the ticket it holds up shows as blocked on nothing. Ask it first, then mention it in chat with its id. A goal at its target is one of these: ask `goal-met` (`planning.md` §1), never "mark it met" in chat. Make each one easy to answer: the recommendation first, options, what it blocks, a default where the class allows one. Combine questions only when one answer settles them all. One answer approves one act; a question that settles several acts (two gate changes, a chore and a ticket) names them when asked, `ask --approves <ticket-id|chore-<slug>|plan-<feature>> …`, so the owner's card lists them and the answer approves each once (`merge` the one it names, or `act --refs <it>`) and nothing else. An answer asked without `--approves` can't be stretched over a second act: ask again for it. Trust questions only at a retro. Withdraw what no longer matters (`withdraw <qid> --reason …`). If fewer than half of the questions old enough to answer were answered in 14 days, the metrics raise `inbox-stalled`: remind the owner what is blocked and open a problem.

Expand Down
4 changes: 4 additions & 0 deletions docs/devteam/schema/log.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1463,6 +1463,10 @@
"type": "array",
"description": "The remediation entries a governance-edit question would approve (name, script, sha, entry_hash; ask --remediations). merge lands a change only if it is one of these, exactly."
},
"new_because": {
"type": "string",
"description": "What materially changed since the owner answered the same decision, when a question asks it again (ask --new-because). The owner reads it first: \"Asked again because: …\"."
},
"owner_said": {
"type": "string",
"description": "The owner's words, verbatim, when a question asks again after their no. Checked against the transcript like a chat answer's said."
Expand Down
Loading
Loading