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
11 changes: 11 additions & 0 deletions .abcd/development/agents/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ over the brief's earlier `1.0.0`-at-close expectation). The four M6 synthesis
agents below entered at `0.1.0`, wired to their `abcd disembark` verbs and
unmeasured; `lifeboat-oracle` has since become `lifeboat-reviewer` at `0.1.1`.

## 2026-10-10 (iss-2610100626211810 — a question's chip sets the mode)

### question-drafter 0.1.1

PATCH: its generated asking-rules block now says a question's chip sets the
mode when the question is asked and the answer sets it back to managed, so a
question needs no `abcd mode` before it, and keeps `abcd mode` for a stop that
is not a question. The drafter's own behaviour is unchanged: it heads each
question with the chip naming its addressee, as before. Unmeasured, in the
`0.x` band.

## 2026-10-07 (iss-2610070637562567 — abcd's questions are drafted to fit)

### question-drafter 0.1.0
Expand Down
12 changes: 6 additions & 6 deletions .abcd/development/brief/04-surfaces/01-ahoy.md
Original file line number Diff line number Diff line change
Expand Up @@ -449,15 +449,15 @@ carries the prompt-router entries it expects. Neither install nor uninstall ever
mutates it: the manifest is plugin-static. A missing or malformed manifest
surfaces as a non-resolvable diagnostic.

The shipped manifest wires six event types, and every event command is a
resolving shim rather than a plain binary call. Four of them self-provision.
`UserPromptSubmit`, `PreToolUse` and `PreCompact` each attempt
The shipped manifest wires seven event types, and every event command is a
resolving shim rather than a plain binary call. Five of them self-provision.
`UserPromptSubmit`, `PreToolUse`, `PostToolUse` and `PreCompact` each attempt
`hooks/bootstrap.sh` only when the plugin-root binary is missing, recording the
try in a `.bootstrap.attempt` marker that throttles the next one to a ten-minute
window. `UserPromptSubmit`, the hook that runs on every message, declares a
120-second `timeout`, the time a salvage on a slow link has before the host
cancels it; `PreToolUse` and `PreCompact` declare none and take the host's
ten-minute default, so a slow first download finishes there. `SessionStart`
cancels it; `PreToolUse`, `PostToolUse` and `PreCompact` declare none and take
the host's ten-minute default, so a slow first download finishes there. `SessionStart`
declares 240 seconds, the script's worst case with room to spare, and
`SessionEnd` and `SubagentStop` declare none. Every event that runs the script,
`SessionStart` included, names a `statusMessage` the host shows as its spinner
Expand All @@ -470,7 +470,7 @@ the binary in place the script's own fast path costs a file test and does the
provisioning housekeeping that keeps the next plugin update served from the
local cache rather than the network, and it is the one place a binary that no
longer matches its provenance record is called out. It stamps the same marker,
so the three throttled events see a recent try, and reads no throttle of its
so the four throttled events see a recent try, and reads no throttle of its
own. `SessionEnd` and `SubagentStop` are the deliberate exceptions and download
nothing: both fire where the host cancels a slow hook rather than wait — one as
the session is going away, the other inside a live session as a sub-agent
Expand Down
22 changes: 12 additions & 10 deletions .abcd/development/brief/04-surfaces/08-abcd.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,18 @@ spc-2609212139593041). The badge reads exactly one of its three labels and
never the bare tool name, and its colour ends at the badge: the closing
sequence restores the default foreground and background and nothing else, so
the rest of the row keeps whatever styling the host gives it. The two moments
the badge must change are two moments the hooks already see. The agent sets
the state with `abcd mode` when it stops to ask, naming whom it addresses; the
guard hook, on the host's question tool, refuses abcd's own question (one
headed in abcd's chip grammar, [`17-guard.md`](17-guard.md)) while the state
reads managed, naming `abcd mode product-thinker` and `abcd mode facilitator`,
and when it admits one it writes a `question_open` marker beside the state in
`.abcd/.work.local/`. The next human message is the answer: the prompt hook
finds the marker, resets the state to managed, clears the marker and says so in
one line on stderr. With no marker the prompt hook changes nothing, so a state
the human set by hand survives the message they type next. A repository abcd
the badge must change are two moments the hooks already see. When the
guard hook, on the host's question tool, admits abcd's own question (one headed
in abcd's chip grammar, [`17-guard.md`](17-guard.md)), it sets the state from
the chip's role, naming whom the question is for, and writes a `question_open`
marker beside the state in `.abcd/.work.local/`; a chipped question is never
refused on the mode. The answer resets it: the question tool's `PostToolUse`
hook, when the answer comes back, or the prompt hook on the next human message
where the host runs no `PostToolUse`, finds the marker, resets the state to
managed, clears the marker and says so in one line on stderr. With no marker
neither hook changes anything, so a state the human set by hand survives the
message they type next. At a stop that is not a question the agent sets the
state itself with `abcd mode`, naming whom it addresses. A repository abcd
does not manage, or one without the local tier, has no badge, and its
questions are not gated.

Expand Down
62 changes: 37 additions & 25 deletions .abcd/development/brief/04-surfaces/17-guard.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ consulting the hazard registry. It decodes the tool's questions into the field
view of `internal/core/question` (the host's JSON key names stay in the
surface) and decides whether the question is abcd's: a header in abcd's chip
grammar, which only abcd's interview pages are taught to write, or a mode
naming somebody, which only `abcd mode` sets and the prompt hook resets on the
next human message (itd-201 decision 10). Any other question is another tool's
naming somebody, which only `abcd mode` and this gate set and the answer resets
(itd-201 decision 10). Any other question is another tool's
and runs, unchecked and unmarked, exit 0, wherever it is asked. That includes a
question with no abcd chip asked while the mode reads managed, in a managed
checkout too: the gate cannot tell an abcd question that forgot its chip from
Expand All @@ -127,8 +127,9 @@ chip.
abcd's question is held to the field limits (`question.CheckLimits` over
`question.Default`) wherever the hook runs, managed or not: the setup interview
asks before a repository is managed, and the limits need no store. The
addressee the product thinker's register rule reads is the mode's where a mode
store exists, and the chip's role word where none does; the binary's verb list
addressee the product thinker's register rule reads is each tab's chip role
for a chipped question, since the mode the gate then sets follows the chip,
and the mode's for a question without a chip; the binary's verb list
is read from the command tree and passed in. The row limit is estimated with
the host's frame measured at 80 by 24, and a side preview on any option is
refused, because the host hides every option's description while a preview
Expand All @@ -152,8 +153,12 @@ sets no `permissionDecision`, which would bypass the host's own permission
flow, and never tells the agent to ask again, because the person may already
have answered. A refusal for that question was a redraft of a question the
person was ready to answer, and a tab cut at the foot of a short window costs
less. Beside any other finding, or while the mode gate refuses, the rows
finding is named in the deny with the rest. A question with no abcd chip,
less. Beside any other finding, the rows finding is named in the deny but is not one of the parts to fix
(iss-2610100626327722): the head line counts only the findings that refuse,
and the rows findings follow them, bounded the same way, under one line saying
the rows limit does not refuse on its own and the question would have been
shown. Listed among the parts to fix, it read as a cause, and the agent cut a
question the gate would have shown. A question with no abcd chip,
abcd's only because the mode names somebody, carries one line under the head
line saying so, naming the mode's person, so an agent whose question another
tool wrote does not loop on it. The hook refuses and never
Expand All @@ -166,25 +171,32 @@ and a question tool fails open in the question's wording; a payload whose tool
cannot be read fails open naming no tool. Neither echoes the decoder's text,
which can name a Go type.

In a repository abcd manages, abcd's question asked while `abcd mode` reads
managed is also refused with the host's deny. Alone, the refusal is one
line naming the two settings, `abcd mode product-thinker` and `abcd mode
facilitator`, so the agent says whom it is asking before it asks and the
status-line badge shows it; beside field findings, that line follows them. Once
the state names somebody the question runs, and the hook writes a
`question_open` marker in `.abcd/.work.local/`; the rules loader's prompt hook
resets the state to managed on the next human message and clears the marker.
Where the badge does not show, the mode gate does not run. A state file or
marker the gate cannot read or write is not a decision: the question runs and
the hook says so on exit 1, the same fail-open-loud contract below. So is a
tier `abcd mode` cannot write — a read-only mount, a directory the session's
user does not own: the refusal's remedy could not run there, so the gate probes
that the verb could set the state before it refuses, and where it could not,
the mode refuses nothing and only field findings, whose remedy is the agent's
own, can refuse; with none, the question runs on exit 1.
The probe is a file created in the tier and removed again; one the remove could
not reach, because the tier turned unwritable in between or the process died,
is swept by the next probe. The manifest's pre-tool-use matcher names the
In a repository abcd manages, abcd's question is never refused on the mode
(iss-2610100626211810). Its chip already names whom it is for, and refusing it
while the mode read managed refused an interview intermittently, whenever the
mode had been reset between two questions. So when the gate admits a question
carrying abcd's chip, it derives the state from the chip's role and sets it:
`Product` names the product thinker, and `Tech` and `Setup` name the technical
facilitator. `Setup` is the setup interview's chip, whose questions (the
repository's visibility, its keys, the oracles it connects) are about how abcd
is installed and run, the facilitator's half; a call whose tabs name both
people sets the product thinker. A chip naming someone other than the mode
names re-sets the mode, because the status line names whom the question on
screen is for. The gate writes a `question_open` marker in
`.abcd/.work.local/` first and sets the state second, so a failure between the
two leaves a marker whose reset costs nothing rather than a parked state with
nothing left to reset it. The answer resets the state to managed and clears the
marker: the plugin's `PostToolUse` hook on the question tool runs the reset when the
answer comes back, and the rules loader's prompt
hook runs the same reset on the next human message, the fallback for a host
that does not run `PostToolUse`; whichever runs first clears the marker, so
the other changes nothing. `abcd mode` remains the way to record whose answer
is owed at a stop that is not a question. A question without abcd's chip while
the mode names somebody is held to the field limits and marked open, and sets
nothing. Where the badge does not show, the mode is neither read nor set. A
state file or marker the gate cannot read or write, a read-only tier among
them, is not a decision: the question runs and the hook says so on exit 1, the
same fail-open-loud contract below. The manifest's pre-tool-use matcher names the
shell tool and the question tool, and nothing else.

## Fail-open-loud
Expand Down
13 changes: 9 additions & 4 deletions .abcd/development/brief/05-internals/03-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1068,15 +1068,16 @@ checksums; its build strings are printed instructions to the operator for the ca
it cannot provision. `SessionStart` runs one chained command rather than siblings,
because siblings would run in parallel and share one stdin.

`SessionStart`, `UserPromptSubmit`, `PreToolUse` and `PreCompact` are the events
that reach `bootstrap.sh` at all. The last three self-provision only when the
`SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse` and `PreCompact`
are the events that reach `bootstrap.sh` at all. The last four self-provision
only when the
plugin-root binary is missing, throttled by a `.bootstrap.attempt` marker within a
ten-minute window, and then fall back to a PATH-resolved abcd that must be
absolute, outside the working directory, in a directory and a file that are not
world-writable, and recorded as this
machine's own, before failing loudly. `UserPromptSubmit`, which runs on every
message, declares a 120-second `timeout`; `PreToolUse` and `PreCompact` declare
none and take the host's ten-minute default; `SessionStart` declares 240 seconds,
message, declares a 120-second `timeout`; `PreToolUse`, `PostToolUse` and
`PreCompact` declare none and take the host's ten-minute default; `SessionStart` declares 240 seconds,
and the transcript hooks declare none. Every event that runs `bootstrap.sh`
names a `statusMessage`, the host's spinner text while the hook runs, because the
salvage sends the script's output nowhere; the text states no duration, since
Expand All @@ -1095,6 +1096,10 @@ BLOCKING code on that event.
`SubagentStop` carries `hook subagent-stop`, which stages a finished sub-agent's
transcript beside it with the lineage the harness payload and its per-agent sidecar
supply. `SessionStart` drains both through the fail-closed redaction path.
`PostToolUse` is matched to the question tool alone and carries `hook
question-answered`, which resets the mode to managed when an answer comes back
to a question the guard marked open (iss-2610100626211810); the prompt hook
runs the same reset on the next message, for a host that does not run it.

**The plugin-internal development namespace** (committed in private repos,
gitignored in public) holds, at its root, the config file and the per-surface
Expand Down
7 changes: 4 additions & 3 deletions .abcd/development/brief/glossary/core/product-thinker.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ The **product thinker** decides *what*: which intents are pursued, what their ac
criteria promise, which proposal is adopted, and every ruling the record carries. `abcd intent
plan <itd-N>` is their sign-off act ([plan](plan.md)), and the planning interview's questions
are theirs. They answer on a surface of their own, so a stop that waits on them is announced:
`abcd mode product-thinker` parks the loop on them, and the status line reads `waiting on the
product thinker` until they answer.
a question's `Product` chip, or `abcd mode product-thinker` at a stop that is not a question,
parks the loop on them, and the status line reads `waiting on the product thinker` until they
answer.

The product thinker owns two things in the record: the brief, which says what the product
is, and the intents, which say what is to be built and in what order. Specs and the issue
Expand Down Expand Up @@ -48,7 +49,7 @@ Where a sentence genuinely means either person, it says "the person" or names bo
## Examples

- "Adopting a proposal is the product thinker's move."
- "Set `abcd mode product-thinker`, then ask the product thinker once, in their own words."
- "Ask the product thinker once, under a `Product` chip, in their own words."

## Related terms

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ versions: null
The **technical facilitator** decides *how*: the person at the terminal running the agents, who
operates the gates, merges, CI, hooks and installs, and addresses the mechanism and the record
ids that the [product thinker](product-thinker.md) is spared. A stop that waits on them is
announced as one: `abcd mode facilitator` parks the loop on them, and the status line reads
`waiting on the technical facilitator` until they answer.
announced as one: a question's `Tech` or `Setup` chip, or `abcd mode facilitator` at a stop
that is not a question, parks the loop on them, and the status line reads `waiting on the
technical facilitator` until they answer.

itd-97 (a draft) holds that **the facilitator is a mode, not a person**. A project runs duo,
with a human technical facilitator beside the product thinker, or solo, where abcd itself
Expand All @@ -41,7 +42,7 @@ person" or names both.
## Examples

- "abcd writes what is missing and never replaces what the technical facilitator put there."
- "Set `abcd mode facilitator`, ask the technical facilitator first, then pipe the answer."
- "Ask the technical facilitator first, under a `Tech` chip, then pipe the answer."

## Related terms

Expand Down
5 changes: 5 additions & 0 deletions .abcd/development/release/surface.json
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,11 @@
"hidden": false,
"flags": []
},
{
"path": "abcd hook question-answered",
"hidden": false,
"flags": []
},
{
"path": "abcd hook session-end",
"hidden": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,13 @@ Builds on and reuses:
forced by `TERM=dumb`, and `term.RawSession`, whose restore runs on every
exit. The menu asks through it and holds no keyboard code of its own.
- The mode store and its question marker: `mode.ReadAt` and `mode.SetAt`
(`store.go`, lines 70 and 109), `mode.MarkQuestionOpen`,
`mode.ResetOnAnswer` and `mode.CanSet` (`question.go`, lines 57, 114
and 165).
- The session's status rules, unchanged: the guard refuses a chip-headed
question while the mode reads managed (`questionGate`,
`guard_question.go`, line 82, naming `abcd mode` in `questionRefusal`,
line 52), marks it open when it admits one (line 137), and the prompt hook
resets it on the answer (`resetModeOnAnswer`, line 275).
(`store.go`), `mode.MarkQuestionOpen` and `mode.ResetOnAnswer`
(`question.go`).
- The session's status rules, unchanged: when the guard admits a
chip-headed question it marks it open and sets the mode from the chip's
role (`questionGate`, `guard_question.go`), and the question tool's
PostToolUse hook resets it when the answer returns, with the prompt hook's
reset as the fallback (iss-2610100626211810).
- The build's start: `loop.Start` (`loop.go`, line 263), its runner read
(`loadRunners`, `build.go`, line 927), and its refusal, `loop.Refusal`
(`refusal.go`, line 15), whose `Check` names the pre-start check
Expand Down Expand Up @@ -202,8 +201,9 @@ alone, writes nothing, and emits no escape byte (B3; decision 10):
drawn on stderr, as the answer loop draws every question;
- neither `--json` nor `--format markdown` nor `--no-menu` is passed;
- the off setting does not say off;
- the repository is managed (`ahoy.Managed`) and its local tier can take the
write (`mode.CanSet`).
- the repository is managed (`ahoy.Managed`) and has its local tier
(`mode.HasTier`); a write the tier then refuses is reported, never a
refusal of the board.

A new call in `internal/core/mode` holds the status for a question abcd asks
itself:
Expand Down
Loading
Loading