From 7c4380d416661ee9d401e259f3fa90706482b3b2 Mon Sep 17 00:00:00 2001 From: Lu Nelson Date: Thu, 27 Aug 2026 12:12:24 +0200 Subject: [PATCH 1/5] Cut the agentic guidance layer to a mission charter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the routing/planning apparatus — 12 protocol docs, three control docs, the document index, both arc-close skills, and the two tests that enforced them — with a single compact charter plus a MISSION record. - AGENTS.md: three laws (real throughline first, deepen only under strain, branch = mission), a six-field mission contract, and sharp correctives. - MISSION.md: the current objective, acceptance proof, and stop conditions. - CONTEXT.md trimmed to the live vocabulary; the strategic-control and demo vocabulary sections are retired. - ADRs reframed as hypotheses, not obligations (docs/adr/README.md). - Flue routing table retained as reference under docs/reference/architecture/. --- .../.agents/skills/arc-close/SKILL.md | 8 - .../.claude/skills/arc-close/SKILL.md | 8 - libs/@hashintel/brunch-agent/AGENTS.md | 125 ++--- libs/@hashintel/brunch-agent/CONTEXT.md | 401 ++++++---------- libs/@hashintel/brunch-agent/MISSION.md | 31 ++ libs/@hashintel/brunch-agent/README.md | 25 +- libs/@hashintel/brunch-agent/docs/INDEX.md | 139 ------ .../brunch-agent/docs/adr/README.md | 9 + .../brunch-agent/docs/agents/arc-close.md | 89 ---- .../brunch-agent/docs/agents/documentation.md | 91 ---- .../brunch-agent/docs/agents/domain.md | 45 -- .../brunch-agent/docs/agents/git-workflow.md | 63 --- .../brunch-agent/docs/agents/issue-tracker.md | 152 ------ .../brunch-agent/docs/agents/issue-writing.md | 229 --------- .../brunch-agent/docs/agents/legibility.md | 127 ----- .../docs/agents/partition-worktrees.md | 88 ---- .../brunch-agent/docs/agents/posture.md | 4 - .../brunch-agent/docs/agents/steering.md | 100 ---- .../brunch-agent/docs/agents/triage-labels.md | 17 - .../brunch-agent/docs/control/SPEC-LEDGER.md | 126 ----- .../brunch-agent/docs/control/STEERING.md | 451 ------------------ .../brunch-agent/docs/control/STRATEGY-LOG.md | 446 ----------------- .../architecture}/flue-routing.md | 6 +- .../architecture/control-surfaces.test.ts | 125 ----- .../core/test/architecture/docs-index.test.ts | 257 ---------- 25 files changed, 271 insertions(+), 2891 deletions(-) delete mode 100644 libs/@hashintel/brunch-agent/.agents/skills/arc-close/SKILL.md delete mode 100644 libs/@hashintel/brunch-agent/.claude/skills/arc-close/SKILL.md create mode 100644 libs/@hashintel/brunch-agent/MISSION.md delete mode 100644 libs/@hashintel/brunch-agent/docs/INDEX.md create mode 100644 libs/@hashintel/brunch-agent/docs/adr/README.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/arc-close.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/documentation.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/domain.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/git-workflow.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/issue-tracker.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/issue-writing.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/legibility.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/partition-worktrees.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/posture.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/steering.md delete mode 100644 libs/@hashintel/brunch-agent/docs/agents/triage-labels.md delete mode 100644 libs/@hashintel/brunch-agent/docs/control/SPEC-LEDGER.md delete mode 100644 libs/@hashintel/brunch-agent/docs/control/STEERING.md delete mode 100644 libs/@hashintel/brunch-agent/docs/control/STRATEGY-LOG.md rename libs/@hashintel/brunch-agent/docs/{agents => reference/architecture}/flue-routing.md (98%) delete mode 100644 libs/@hashintel/brunch-agent/packages/core/test/architecture/control-surfaces.test.ts delete mode 100644 libs/@hashintel/brunch-agent/packages/core/test/architecture/docs-index.test.ts diff --git a/libs/@hashintel/brunch-agent/.agents/skills/arc-close/SKILL.md b/libs/@hashintel/brunch-agent/.agents/skills/arc-close/SKILL.md deleted file mode 100644 index d8e12c92901..00000000000 --- a/libs/@hashintel/brunch-agent/.agents/skills/arc-close/SKILL.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: arc-close -description: Runs the mandatory Brunch arc-close control pass before a branch closes a work arc. ---- - -Read `docs/agents/arc-close.md` from the Brunch context root and execute its five steps in order. -This wrapper carries no duplicate procedure. Report the required checks and whether each -conditional control surface changed; never persist a no-op evaluation. diff --git a/libs/@hashintel/brunch-agent/.claude/skills/arc-close/SKILL.md b/libs/@hashintel/brunch-agent/.claude/skills/arc-close/SKILL.md deleted file mode 100644 index d8e12c92901..00000000000 --- a/libs/@hashintel/brunch-agent/.claude/skills/arc-close/SKILL.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: arc-close -description: Runs the mandatory Brunch arc-close control pass before a branch closes a work arc. ---- - -Read `docs/agents/arc-close.md` from the Brunch context root and execute its five steps in order. -This wrapper carries no duplicate procedure. Report the required checks and whether each -conditional control surface changed; never persist a no-op evaluation. diff --git a/libs/@hashintel/brunch-agent/AGENTS.md b/libs/@hashintel/brunch-agent/AGENTS.md index 0c0c58d9ad1..69229bd8e01 100644 --- a/libs/@hashintel/brunch-agent/AGENTS.md +++ b/libs/@hashintel/brunch-agent/AGENTS.md @@ -1,58 +1,71 @@ # Brunch agent -This directory is the Brunch context and agent-session root inside `hashintel/hash`. HASH root -guidance always wins where it conflicts with this file. - -## Scope - -- `packages/core`: substrate- and renderer-independent harness and plugin SDK. -- `packages/binding-*`: substrate bindings; each depends inward on the harness. -- `packages/transport-*`: wire transports; none may depend on a binding. -- `packages/plugin-*`: target plugins; each depends only on the harness. -- `../../../apps/brunch-agent`: remote server, application composition, and local diagnostics. -- `evaluations`: cases, protocols, and oracles; see `evaluations/AGENTS.md` before changing them. - -## Stack - -- Format TypeScript and JSON with HASH-root `oxfmt` (double quotes, 80 columns), not Biome or - Prettier. Brunch Markdown remains excluded. -- `lint:eslint` runs Oxlint with multi-file import analysis, type-aware rules, and compiler - diagnostics. Package `.oxlintrc.json` files extend Brunch presets under - `.config/oxlint/brunch/`. -- `lint:tsc` remains the independent `tsgo --noEmit` type-check gate. -- `test:unit` runs Vitest through `vitest run`; architecture tests remain the topology, Flue - placement, and hermetic-runtime gates. -- Vite 8 builds the libraries and application. - -The context root is not a package-manager root. Do not add a `package.json`, lockfile, nested -workspace configuration, or standalone CI here. Run package tasks through HASH's root Yarn/Turbo -workspace. - -## Before changing Brunch - -1. Read `CONTEXT.md` and the relevant decision under `docs/adr/`. -2. Read the protocol under `docs/agents/` that corresponds to the operation. -3. Preserve the executable package-direction, Flue entrypoint, bundle, and hermetic-runtime gates. - -## Working methods - -- Use Graphite (`gt`) for stack operations; do not use `gh stack` in HASH. -- Issues live in Linear team `FE`, project `brunch-agent`. -- Brunch Markdown is created and maintained by agents; exclude it from `oxfmt` and `markdownlint`. - -Route by trigger; load only the applicable compact protocol: - -- Start or resume without a proof target, or when objectives, pressure, proof, authority, external - gates, frontier value, or arc-close findings change: invoke `/ds-steer`, which consults the Brunch - supplement at `docs/agents/steering.md`. -- Create, mutate, triage, or structure issues: `docs/agents/issue-tracker.md`, - `docs/agents/issue-writing.md`, and `docs/agents/triage-labels.md`. -- Add, move, settle, or index documents: `docs/agents/documentation.md`. -- Change domain terms or accepted context decisions: `docs/agents/domain.md`. -- Make a Flue design choice: `docs/agents/flue-routing.md`. -- Produce a significant agent-authored artifact or proof: `docs/agents/legibility.md`. -- Make an architecture-sensitive move: `docs/agents/posture.md`. -- Operate on branches, stacks, commits, or PRs: `docs/agents/git-workflow.md`. -- Create or refresh worktrees for a recorded partition: `docs/agents/partition-worktrees.md`. -- Close a work arc: run the context-local `arc-close` skill and - `docs/agents/arc-close.md`. +Brunch is the elicitation harness and package family at `libs/@hashintel/brunch-agent`. This +directory is its context root, not a package workspace. HASH root guidance wins where it differs +from this file. + +## The three laws + +1. **Dumbest real implementation first.** Cross the real production boundary end-to-end before + improving anything: use the real entrypoint and wiring, inline what can stay local, and pin + only the invariants and constraints the working path actually exposes. Then re-decide at the + new fog-line instead of running an inherited plan. +2. **Deepen only under observed strain.** An intended design is a hypothesis, not a destination. + Admit the next piece of complexity when the current implementation strains under a present + requirement (duplication diverging, a boundary leaking, an invariant that will not hold + locally), and cut the design when the design itself is what is straining progress. +3. **A branch is a mission, not a ticket.** Every mission carries an imperative that guides and + bounds its work; its evidence-gathering and decisions are judged against that imperative, not + against a plan graph. + +## Mission contract + +When work starts on a branch, state these six things in the branch/PR description (no separate +document): + +- **Imperative** — what must become true, and why now. +- **Throughline** — the real entrypoint or boundary being changed. +- **Proof** — the observable evidence that would establish progress. +- **Constraints** — the few already-earned truths that must stay true. +- **Fog-line** — what is unknown and must not be designed past. +- **Stop or reorient** — evidence that invalidates or changes the route. + +## Correctives + +- Before adding structure, name the production pressure that requires it. +- Work the first unproven boundary; do not build toward the imagined end. +- Real entrypoint or it did not happen; a proof is legible when a human can watch it and decide. +- A ticket is a projection; the mission is the authority. If the ticket stops serving the + imperative, stop and surface the divergence instead of finishing the ticket. +- When evidence changes the route, stop; do not finish the planned neighbourhood. +- When unsure, build the smallest real path that reveals more. +- When things accumulate, subtract before you extend. +- No imperative and proof means it is not a mission yet — do not start it. + +## Retained facts + +- **Toolchain:** format TS/JSON with root `oxfmt`; lint via `lint:eslint` (Oxlint) and + `lint:tsc` (`tsgo --noEmit`); unit tests via `vitest run`; build with Vite 8. Run tasks through + the HASH root Yarn/Turbo workspace — add no `package.json` or lockfile here. +- **Git vs Graphite:** plain `git` for status/diff/add/commit; `gt` for + `create`/`submit`/`restack`/`sync`/`checkout`. Never `gh stack`. Before switching the branch of + a shared worktree, check for in-flight work; use a separate worktree rather than stashing, + resetting, or cleaning anything you did not create. +- **Linear:** team `FE`, project `brunch-agent`. Reading is fine; get explicit approval before + any write (create, edit, comment, state change). +- **Topology gates** (enforced by tests): plugins never import + `@hashintel/brunch-agent/prompts`; transport packages never depend on a binding; bindings + depend inward on core; plugins depend only on core. Evaluation answer keys stay on the + evaluation side, never inside interviewee or elicitor inputs. +- **Posture:** prototype · stakes high — persisted capture data and merge gates must fail loudly, + never corrupt silently · horizon: current milestone. +- **Flue design moments:** see + [`docs/reference/architecture/flue-routing.md`](docs/reference/architecture/flue-routing.md). + +## Authorities vs obligations + +[`docs/specs/`](docs/specs), [`docs/adr/`](docs/adr) (see its [README](docs/adr/README.md)), and +[`docs/evidence/`](docs/evidence) are history and reference: prior design hypotheses and observed +results. They are not marching orders. Re-earn any design you build to; an implemented decision is +evidence, unimplemented design is a hypothesis. A branch may depart from a recorded decision by +noting the divergence in its commit. diff --git a/libs/@hashintel/brunch-agent/CONTEXT.md b/libs/@hashintel/brunch-agent/CONTEXT.md index 30ead60e188..5c95f944ec9 100644 --- a/libs/@hashintel/brunch-agent/CONTEXT.md +++ b/libs/@hashintel/brunch-agent/CONTEXT.md @@ -1,289 +1,186 @@ # Brunch — domain language -Vocabulary for the brunch elicitation system: an architecture generalizing agentic interviewing against pluggable elicitation targets. Hardened during the elicitation-kernel effort (whose spec settled 2026-08-10) and now governing this repo's implementation and the live process-model-elicitation effort alike. (The old title "Elicitation Kernel" fell to the glossary's own rule: "kernel" is a retired shell name.) +Vocabulary for the brunch elicitation system: an architecture generalizing agentic interviewing +against pluggable elicitation targets. + +## Shells + +**Substrate** — the agent framework the system is built on (Flue), including deploy target, +storage-port implementation, artifact delivery, and model/provider. +_Avoid_: harness (for Flue), platform, host. + +**UI** — whatever affords user interaction: rendering, input, reply transport. Not bound to +GUI/TUI; a chat channel qualifies. +_Avoid_: host, frontend, client. + +**Harness** — the generic capability layer: mechanism and orchestration (the conversation loop, +the `ask` API, capture envelope, issue queue, sweep bookkeeping). Injected into plugins as a +narrow context; never owned by them. +_Avoid_: kernel, core (as a prose shell name; the package path `packages/core` is exempt). + +**Plugin** — the innermost shell: target-defining policy, one per **target formalism** and never +per domain. Authored as cells under harness-owned **keys**; receives capabilities by injection; +mechanism stays in the harness. +_Avoid_: extension, pack (a pack is a unit within a plugin). + +**Binding** — the substrate-facing adapter implementing the harness's named substrate-capability +list (tool registration, instruction assembly, persistent state, affordance emission, +suspend-for-reply, private model call) in one substrate's dialect. One per substrate; the harness +imports no substrate, a binding imports both. +_Avoid_: adapter, integration, wrapper. + +## Sessions and durability -## Language +**Target formalism** — the artifact family a plugin projects into (Gherkin, SDCPN, assurance +arguments, BPMN); the unit a plugin is written for. +_Avoid_: target-domain; bare "target" where family vs instance is ambiguous. -### Shells +**Domain** — the operational system the expert knows and the model describes (a packaging line, a +truck fleet). Unknown before the conversation; discovered during it; never a plugin unit, key, +row, or noun in a plugin definition. +_Avoid_: target-domain, use case. + +**Target-document** — the durable unit sessions attach to: one target formalism, its capture +store, and its session history. Its authoritative state is the capture store plus session logs, +never the rendered artifact (renders are derived and disposable). Endures independently of any +session; completion is a derived status, not a write gate. +_Avoid_: spec, workpiece, case, target-output. -**Substrate**: -The agent framework the system is built on — the Pi family, Flue — including the embedding environment's concerns: deploy target, storage-port implementation, artifact delivery, model/provider. (The retired term "host" silently bundled these with interface concerns; they split into substrate and UI. The charter non-goal "harness-agnostic core" predates this glossary and reads "substrate-agnostic".) -_Avoid_: harness (for Pi/Flue), platform, host (for the embedding environment) +**Session** — one substrate conversation: the full log of entries (user, agent, tool calls, +injected state). Per-session state is exactly the evidence log, the swept high-water mark, and the +pending-affordance slot. Sessions go quiet rather than close; any session is resumable. +_Avoid_: sitting, conversation (as a distinct concept). -**UI**: -The interface shell: whatever affords user interaction — rendering, input, reply transport. Not bound to GUI or TUI; a chat channel qualifies. -_Avoid_: host, host-interface, frontend, client +**Capture store** — the durable, session-independent truth of a target-document: captures, +issues, events. Written only by atomic sweep application; statuses and projections derive from it +at read time. -**Harness**: -The middle shell and the essence of the effort: the generic capability layer of the elicitation system — mechanism and orchestration (the conversation loop, the `ask` API, capture envelope, issue queue, sweep bookkeeping). Injected into plugins as a narrow context; never owned by them. -_Avoid_: kernel, core, elicitor (as a shell name — "elicitor" may name the whole system). Exempt name: the package `packages/core` (spec §12.2) — the avoidance applies to "core" as a prose shell name, not to the package path. "Kernel invariants" renamed **harness invariants** (spec §14.1). The former exempt compound "kernel card" is retired with the card (ADR-0006). +**Re-entry briefing** — the state message injected when a session resumes after the world moved: +computed facts only (unswept tail, world-moved delta, open issues, pending affordance). Authored +on behalf of the user in the transcript, distinguished from true user entries in the data model, +and never citable as capture evidence. +_Avoid_: sync message, forced re-sweep. + +## Interaction +**Affordance** — a structured interactive element (question form, choice strip, questionnaire) +emitted into the stream as a rendered enhancement. Not a state machine; its payload is session +evidence like any other entry. +_Avoid_: exchange, exchange pair, terminal. + +**Capture** — extraction of structured evidence (envelope plus plugin-typed payload) from session +entries. Produced by sweeps, never written directly during conversation. +_Avoid_: extraction, harvest. -**Plugin**: -The innermost shell: target-defining policy, one per **target formalism** (`gherkin`, `sdcpn`) and never per domain — the domain is unknown when a conversation starts. Authored as cells under the harness-owned **keys** (ADR-0007): contract data (`ontology`, `schema`, `patterns`), guidance cells, runbook cells, and the `checks` / `tools` machinery, with `project` / `validate` as code (ADR-0005, ADR-0006). A plugin fills cells and adds no key; what it leaves blank, the **repertoire** supplies. Receives harness capabilities by injection; mechanism stays in the harness. -_Avoid_: extension, pack (a pack is a unit _within_ a plugin), domain plugin, scenario plugin +**Sweep** — an idempotent pass over a settled range of session entries that produces captures; +re-sweeping never double-captures. (`apply-sweep` in the capture store names only the atomic +storage half.) -**Binding**: -The substrate-facing adapter between harness and substrate: implements the harness's named substrate-capability list (tool registration, instruction assembly, persistent state, affordance emission, suspend-for-reply, private model call) in one substrate's dialect. One per substrate; the harness imports no substrate, a binding imports both. Bindings vary in size — each absorbs what its substrate lacks or forbids. -_Avoid_: adapter (generic), integration, wrapper +**Settlement** — the agent-judged event marking a range of conversation ready to sweep. Always +range-level. +_Avoid_: exchange completion. -### Sessions & durability +**Interpretation render** — the harness-owned affordance showing current captured state. The +harness frames envelope semantics; the plugin's renderer supplies the content view, with a +plain-JSON default. -**Target formalism**: -The artifact family a plugin projects into (Gherkin scenarios, SDCPNs, assurance arguments, BPMN) — the unit a plugin is written for (ADR-0006). The family half of the former bare "target". -_Avoid_: target-domain (retired — "domain" now names the expert's operational system, below), target-paradigm; bare "target" where family/instance is ambiguous +## Envelope and packs -**Domain**: -The operational system the expert knows and the model describes — a packaging line, a truck fleet, a coating plant. Unknown before the conversation starts and discovered during it; never a plugin unit, a key, a row, or a noun in a plugin definition. -_Avoid_: target-domain, use case (as a synonym), scenario (a scenario is assembled from boundary conditions at simulation time) +**Intermediate representation (IR)** — the elicited conceptual model a target-document +accumulates, the middle of three registers: typed **assertions** (active captures) fold, by a +pure plugin-declared fold, into the **model** (node instances with slot states), which +**projections** consume without rereading the transcript. A derivation, recomputable from active +captures, never a persistence surface. Defining a plugin's IR means writing its kind and +must-know tables. +_Avoid_: knowledge store, domain model (as a stored unit), staging area. -**Target-document**: -The durable unit sessions attach to: one target formalism, its capture store, and its session history. Named by its purpose — its authoritative state is the capture store plus session logs, never the rendered artifact (renders are derived, cacheable, disposable). Endures independently of any session; never locks — completion is a derived status, not a write gate. -_Avoid_: spec (as the unit name), workpiece, case, target-output +**Capture envelope** — the domain-free wrapper around an opaque plugin payload: harness-minted id, +evidence spans, epistemic status, confidence, value-xor-absence, alternatives grouping, one +`supersedes` link. The hourglass waist. Status (`active | superseded | retracted`) derives at read +time. -**Session**: -One substrate conversation — the full log of entries (user, agent, tool calls, injected state messages), matching Pi's session model. Per-session state is exactly: the evidence log, the swept high-water mark, the pending-affordance slot. Sessions go quiet rather than close; any session is resumable against the current state of its target-document. -_Avoid_: sitting, conversation (as a distinct concept) +**Evidence span** — a capture's provenance: a **quoted excerpt** (primary, model-facing citation) +plus a **pointer** (session id + entry range). Anchors only on true user and user-affordance +entries. -**Capture store**: -The durable, session-independent truth of a target-document: captures, issues, events. Written only by atomic sweep application (serialized); statuses and projections derive from it at read time. +**Epistemic status** — `explicit | inferred | tentative | defaulted | external-lookup`: how a +capture's content relates to what the user said. Distinct from confidence; excluded from capture +identity; one per capture. -**Re-entry briefing**: -The state message the harness injects when a session resumes after the world moved: computed facts only — unswept tail, world-moved delta, open issues, pending affordance. Authored on behalf of the user in the transcript (Pi's custom-entry convention) but distinguished from true user entries in the data model, and never citable as capture evidence. -_Avoid_: sync message, forced re-sweep +**Grade** — how narrow a slot value's interpretation space is. Per-slot; distinct from confidence +(`firm | hedged | speculative`). -### Interaction +**Basis** — the provenance carrier for non-user-grounded captures (`declared-default` or +`documented-transformation`), required exactly when epistemic status is `defaulted` / +`external-lookup`; structurally exclusive with evidence spans. -**Affordance**: -A structured interactive element (question form, choice strip, questionnaire) emitted into the conversation stream as a rendered enhancement. Not a state machine — the conversation stays primary, and an affordance's payload is evidence in the session like any other entry. -_Avoid_: exchange, exchange pair, terminal (brunch's retired turn-by-turn ontology) +**Absence state** — a first-class capture value where an answer would be: `unknown-to-user | +not-yet-decided | not-applicable | explicitly-absent | declined | deferred`. Never null. -**Capture**: -Extraction of structured evidence — envelope plus plugin-typed payload — from session entries. Produced by sweeps, never written directly during conversation. -_Avoid_: extraction, harvest +**Supersession** — explicit correction, single-hop over active heads only: the creation-time +`supersedes` link (sweep-time) and the resolution record (issue-time). Superseded captures stay +visible. -**Sweep**: -An idempotent pass over a settled range of session entries that produces captures. Re-sweeping a range never double-captures. Disambiguation: the capture store's `apply-sweep` command names only the storage half — atomically applying a sweep's proposals; the sweep proper is the capture-producing pass, which does not exist yet (FE-1392). +**Resolution record** — the capture-store event that alone closes a `conflicting` issue (and, with +no successor, expresses retraction). Must cite the true user's utterance. -**Settlement**: -The agent-judged event marking a range of conversation (a vein closing) ready to sweep. Always range-level, never per-question. -_Avoid_: exchange completion +**Issue** — typed, stored backpressure: `missing | ambiguous | conflicting | invalid | +unsupported | unmapped | low-confidence`. Produced by plugin ops (payload level) or the harness +(envelope level). Closes only explicitly. -**Interpretation render**: -The harness-owned affordance form showing current captured state — the harness frames envelope semantics; the plugin's renderer definition (typed against its own payload shapes) supplies the content view when provided, with a harness default (plain JSON view) otherwise. -_Avoid_: digest (brunch's form) +**Advisory** — a computed, ephemeral, non-blocking fact surfaced to the agent. Never stored; never +gates anything. -### Envelope & packs +**Pack** — a unit within a plugin: **ProjectionPack** (`project` + `validate`, optional +`reconcile`, annotated shapes, typed loss reports). The guidance-and-runbook cells replaced the +retired ElicitationPack. -**Intermediate representation (IR)**: -The elicited conceptual model a target-document accumulates — the middle of three registers (ADR-0003): typed **assertions** (active captures) are folded by a pure, plugin-declared fold into the **model** (the IR proper — node instances with slot states), which **projections** consume without rereading the transcript. Not a second store — the model is a derivation, recomputable from active captures at any time, never a persistence surface; the rendered artifact is one projection of the model, never the model itself. Defining a plugin's IR means writing its `Kinds` and `Must know` tables (ADR-0006); the fold derives from the kinds' slots. An earlier definition read the capture set itself as the IR (ADR-0003 amends it); a later provisional contract declared typed model-schema / proposal-catalog / fold-table / demand-table objects (ADR-0006 retires that form). -_Avoid_: knowledge store, domain model (as a stored unit), staging area +**Demand row** — one row of a plugin's must-know table: a slot on a kind, its required precision, +whether "not applicable" is accepted, and why the model needs it. Kind-level only. -**Capture envelope**: -The harness-defined, domain-free wrapper around an opaque plugin payload: harness-minted id, evidence spans, epistemic status, confidence, value-xor-absence, alternatives grouping, one `supersedes` link. The hourglass waist. No stored status — envelope status (`active | superseded | retracted`) derives at read time from links and events. +**Pattern** — a discretionary, kind-indexed heuristic under a plugin's `patterns` key: a machine +trigger (declared kind, optionally one unsatisfied demanded slot), `when` text, and an `ask` +question. Never names a domain. -**Evidence span**: -A capture's provenance link: a **quoted excerpt** (primary, the model-facing citation currency) plus a **pointer** (session id + entry range, harness-derived — entry identity is harness-side vocabulary only). Anchors only on true user and user-affordance-payload entries. +**Runbook** — the `kickoff`, `trajectory`, and `close` keys for one **job** (`construct`, +`review and revise`); harness default interleaved with the plugin's cell. `kickoff` produces a +posture; `close` is honest stopping, never the decision to stop. -**Epistemic status**: -`explicit | inferred | tentative | defaulted | external-lookup` — how a capture's content relates to what the user actually said. Distinct from confidence; excluded from capture identity. One status per capture, coupled structurally to the provenance shape (see Basis) — per-field status is unrepresentable by design (FE-1390; FE-1405's central input, consumed without amendment: the structure that wanted per-field status lives below the status, in proposal interiors). +**Key** — one fixed, harness-owned heading of plugin authoring: the harness defines, teaches, and +ships a default; a plugin specialises it in a cell. Four groups: contract data, guidance, runbook, +machinery. Rendered key → harness default → plugin cell. -**Grade**: -How narrow a slot value's interpretation space is — "fewer readings remain." Per-slot orderings read by the fold, promotion, and demands ("this anchor demands the `range` rung"). Never claim strength: that is confidence (`firm | hedged | speculative`, envelope-side, orthogonal by design). Two sources: **form grades** from the standard-interiors library's ladders (e.g. verbal < point < range < quantiles), **composition grades** plugin-declared (e.g. Gherkin's given-only < given-when < full-gwt). Coined by the FE-1405 arc (`docs/specs/plugin-contract.md`, provisional). -_Avoid_: confidence (for narrowing), precision (unqualified) +**Repertoire** — the harness's own filling of every guidance and runbook key, shipped behind +core's guarded `./prompts` subpath, rendered by bindings, never imported by a plugin. Admitted by +evidence, not plausibility. -**Basis**: -The provenance carrier for non-user-grounded captures: `declared-default` or `documented-transformation`, required exactly when epistemic status is `defaulted` / `external-lookup` and structurally exclusive with evidence spans (FE-1390 coined the field for what spec §5/C5 states in prose). -_Avoid_: evidence (for these two statuses — evidence spans cite the user) +**Mechanism type** — how a guidance key works on the interviewer: a **license** permits what the +model would hedge on; a **technique** is a form of question or move; an **attention** key names +what to notice; an **anchor** is a judgment to check against. Each guidance key has exactly one. -**Absence state**: -A first-class capture value where an answer would be: `unknown-to-user | not-yet-decided | not-applicable | explicitly-absent | declined | deferred` (`not-mentioned` is a computed fact, not a sweepable capture). Never collapses to null. -_Avoid_: null, missing (as the stored representation) +**Posture** — the interaction stance `kickoff` produces from the expert's appetite, time, intended +use, and tolerance for proposed assumptions. Varies the trajectory; continuously re-read; never +stored. Not a state machine. -**Supersession**: -The explicit correction mechanism, single-hop over active heads only. Two channels: the creation-time `supersedes` link (sweep-time correction) and the resolution record (issue-time adjudication). Superseded captures stay visible — corrections don't erase history. +**PluginContext** — the narrow injected context through which a plugin receives harness +capabilities. Its entire world at runtime; the four operations stay pure. -**Resolution record**: -The explicit capture-store event that alone closes a `conflicting` issue (and, with no successor capture, expresses retraction). Must cite the true user's utterance as evidence. +**Storage port** — the harness-defined contract for the capture store (atomic sweep application, +envelope invariants as store-level refusals), implemented by the binding. Plugins are +storage-blind. In code its type is `CaptureStore` (`packages/core/src/capture-store.ts`). -**Issue**: -Typed, stored backpressure to the elicitation controller: `missing / ambiguous / conflicting / invalid / unsupported / unmapped / low-confidence`, with factual attributes. Two producers, namespaced: plugin ops (payload level) and the harness itself (envelope level). Closes only explicitly. -_Avoid_: advisory (a different thing, below) +## Simulation and evaluation -**Advisory**: -A computed, ephemeral, non-blocking fact the harness surfaces to the agent (unaccounted ask, unswept tail, world-moved delta). Never stored in the capture store; never gates anything. +**Situation pack** — the interviewee-side bundle defining a user-to-be-simulated: situation, +scenario, persona. Private to whoever plays the user; never authored from or shaped to mirror the +IR. +_Avoid_: fact pack, persona pack. -**Pack**: -A unit within a plugin: **ElicitationPack** (retired as a name under ADR-0007 — the guidance and runbook cells replace it) or **ProjectionPack** (`project` + `validate`, optional `reconcile`, annotated shapes, typed loss reports). Packs are shapes-to-fill plus behavioral guidance, per Principle v2. +**Answer key** — the modeller-side list of facts the reference net needs. Sits on the +elicitor-team side of the wall; never part of the situation pack. -**Demand row**: -One row of a plugin's `schema` key (the `Must know` table under ADR-0006): a slot on a kind, its required precision, whether "not applicable" is accepted, and why the model needs it. Kind-level only — every node of that kind discovered in conversation is checked against it (ADR-0006). -_Avoid_: demand clause, scope expression, objective row - -**Pattern**: -A discretionary, kind-indexed heuristic under a plugin's `patterns` key. Its machine trigger is the declared kind plus, when present, one unsatisfied demanded slot; its `when` text explains when the surfaced candidate applies and its `ask` text gives the resolving question. A trigger the harness cannot narrow to node kind and slot state (a vague quantifier, an expert who does not know) is guidance — a technique or a movement — not a pattern (ADR-0007). The interviewer decides whether to use a surfaced candidate. Never names a domain. -_Avoid_: card, kernel card (retired — ADR-0006 replaced Detects/Goal/Questions/Artifacts cards with pattern rows), technique card - -**Runbook**: -The three runbook keys — `kickoff`, `trajectory`, `close` — for one **job** (`construct`, `review and revise`), the harness default for each interleaved with the plugin's cell. The one place procedure is stated; `kickoff` produces a **posture**, `trajectory` names movements by bias, `close` is honest stopping and never the decision to stop (completion rule 15). Jobs are harness vocabulary; a plugin fills one set of runbook cells per job it supports (ADR-0007). -_Avoid_: mandate (as the unit name), mode, workflow - -**Key**: -One of the fixed, harness-owned headings of plugin authoring (ADR-0007): the harness defines the concept it names, teaches it, and ships a default; a plugin specialises it in a cell written in the harness's terms and never a domain's. Rendered key → harness default → plugin cell. Keys come in four groups — contract data, guidance, runbook, machinery — and the catalogue is a working set until a co-authoring cycle changes none (decision 9). -_Avoid_: heading (for the authoring unit), section, property (unqualified) - -**Repertoire**: -The harness's own filling of every guidance and runbook key — what it can teach any plugin about interviewing — shipped as `packages/repertoire`, rendered by bindings, never imported by a plugin. An entry may declare the value grades it applies to; the harness derives applicability from the plugin's demand rows. Admitted by evidence, not by plausibility; never rescoped without run evidence. -_Avoid_: quiver (retired name), strategy library, kernel - -**Mechanism type**: -How a guidance key works on the interviewer: a **license** permits what the model would otherwise hedge on; a **technique** is a form of question or move; an **attention** key names what to notice; an **anchor** is a stated judgment to check against. Each guidance key has exactly one (ADR-0007 decision 3). - -**Posture**: -The interaction stance `kickoff` produces from the expert's appetite, time, intended use, and tolerance for proposed assumptions — explore, synthesise-and-invite-correction, or propose-and-question-only-high-impact. Varies the trajectory; continuously re-read; never stored (ADR-0007). Not a state machine. -_Avoid_: mode (as a stored state), appetite (for the stance itself) - -**Kernel card**: -Retired (ADR-0006). The pack-content unit of elicitation guidance — Detects / Goal / contrastive Questions / Artifacts, brunch `BEHAVIORAL_KERNELS.md` lineage — is replaced by **pattern** rows and by guidance cells; the harness-shipped **generic strategy quiver** named in spec §11.5 is designed as the **repertoire** (ADR-0007), which is not pattern-shaped. -_Avoid_: card, kernel card (in new writing) - -**PluginContext**: -The narrow injected context through which a plugin receives harness capabilities (the ask API, envelope, issue queue, sweep bookkeeping). The plugin's entire world at runtime; the four operations remain pure (snapshot-in/deltas-out) regardless. - -**Storage port**: -The harness-defined contract for the capture store (atomic sweep application, envelope invariants as store-level refusals), implemented by the binding for its deploy target. Plugins are storage-blind. In code the port's type is `CaptureStore` (`packages/core/src/capture-store.ts`) — grep for that, not for "storage port". Scope includes the **session-log archive** (archive-on-read; spec §9.6): session logs live with the target-document, retained indefinitely — the substrate's conversation store is the live transport copy, never the provenance record. - -### Strategic control - -**Concern**: -A durable question, invariant, risk, assumption, design axis, or obligation that can govern work -across several temporary activities. -_Avoid_: issue (an issue can be one temporary activity acting on a concern) - -**Steering projection**: -A bounded map, issue, proof, or decision activity created to investigate or act on a concern. The -qualified term keeps steering usage distinct from the IR's projection register. -_Avoid_: projection (unqualified in strategic-control prose), concern record - -**Operative force**: -What a governing concern presently requires work to preserve, avoid, test, or account for. -_Avoid_: status, priority - -**Commission**: -The relationship by which a strategic owner gives a map its intended contribution, governing -concerns, and related-map context. -_Avoid_: request, assignment - -**Landing**: -A map's terminal account of its outcome, strategic changes, durable dispositions, affected maps, -and residual uncertainty. Landing precedes reconciliation and does not itself close a commissioned -map or resolve its concerns. -_Avoid_: closure, completion report - -**Journey**: -The causal strategic change between a map's commission and landing that future navigation still -needs, excluding operational chronology. -_Avoid_: history, activity log - -**Move**: -One bounded change within a selected frontier, with its own landing but not necessarily its own -proof. Several moves are **joined** when they are proven together by one named proof (the -`ds-steering` join): they may be built in parallel worktrees, but none is done until the joint -proof runs. G0's wiring, persistence, latency-floor, and legible-surface work are joined moves. -_Avoid_: stream (for work that shares a proof), phase, task, effort (an effort is a checkout) - -**Stream**: -A line of work that runs in parallel with the selected frontier, has its own projection and its -own proof, and neither blocks nor is blocked by the frontier's joint proof. The plugin design loop -and the package-topology ADR are streams beside G0. The epicentre map's older word for the same -thing is "lane"; it is retained there and not used for new writing. -_Avoid_: lane (new writing), workstream, track, effort - -**Partition**: -Brunch execution layout, made after the proof frontier is selected: which **efforts** get -worktrees, their write sets, join points, re-braid points, and base. Moves and streams do not map -one-to-one onto efforts (W1 carries G0.1 and G0.2; the driver retains G0.4). Recorded in -`docs/control/STEERING.md` and revised at every steering pass; it never changes which frontier is -selected. Brunch extension of `/ds-steer` step 5 (`docs/agents/steering.md`). Not Dogsled -vocabulary. -_Avoid_: plan (the partition is one section of the strategic control, not a plan document), -breakdown (that is ticket decomposition, `/ds-write-tickets`), parallelisation - -**Effort**: -The checkout unit of a partition: a worktree with a disjoint write set except at named join -points. It may carry one or more joined moves, or a stream; those remain proof and strategy, not -the effort. Deferred work is not an effort. The partition is recorded in -`docs/control/STEERING.md`. -_Avoid_: stream, move, branch (the effort is the worktree, not its Git ref) - -**Driver**: -The worktree that owns control documents and Linear. Other efforts deposit through issue comments, -commit and PR bodies, and evidence under their own path; the driver reconciles at each landing. -The current HASH clone is the driver until a partition says otherwise. -_Avoid_: main worktree, primary, orchestrator - -**Join point**: -A file, package, or manifest two efforts both write, with the order in which they land. Control -documents and Linear are written only from the driver worktree and are therefore never join points. -_Avoid_: conflict (a join point is planned; a conflict is what happens when it was not) - -**Re-braid**: -The planned moment when diverging effort branches are restacked onto a shared base and conflicts -resolved, before they diverge again. Brunch-local; not a Dogsled term. How long a line may run -unbraided follows how fine the tickets are, not a ticket count. Three relationships stay distinct: -the **proof join** (moves demonstrated together), the **join point** (shared file, landing order), -and the **re-braid** (git-line meeting). -_Avoid_: rebase (the git verb a re-braid uses), sync, integrate, restack checkpoint (the generic -gloss; keep re-braid here) - -**Sequence**: -Ordered goals where each goal's proof is the precondition of the next (G0 → G1 → G2). Ordering -inside a sequence is strategic, not mechanical availability. -_Avoid_: roadmap, phases, streams - -### September demo - -**Demo shell**: -A retired proposal for a one-off September application (FE-1362). ADR-0004 replaced it with two -application-owned surfaces in `hashintel/hash`: `apps/brunch-agent` runs the remote Brunch server, -while `apps/petrinaut-website` owns the user-facing integration. Reusable Brunch and Petrinaut -libraries remain mutually unaware. -_Avoid_: using "demo shell" for the accepted topology - -**Artifact boundary**: -The inter-library contract retained by ADR-0004 and amended by ADR-0005: the plugin projects a -versioned net scaffold plus scenario, code obligations, and loss report; the application realizes -the obligations through Petrinaut's client tools and compiler. Applications may compose both -libraries, but neither reusable library consumes the other. -_Avoid_: file handoff (undersells it), integration (generic) - -**Code obligation**: -A field-addressed requirement emitted with a projection scaffold for TypeScript that cannot be -derived deterministically. It names the semantic intent, available net symbols, supporting capture -ids, and acceptance checks. The sidecar obligation is authoritative; a matching comment in the -draft code field is human- and agent-facing context, not the machine contract. - -**Artifact realization**: -The model-assisted application step that fulfills code obligations through Petrinaut client tools, -repairs against compiler diagnostics, and stops only at deterministic compilation and simulation -gates. It is downstream authoring over a projection, not a fourth IR register or a plugin operation. - -**Revision story**: -The working-hypothesis demo spine (FE-1363; recommended to PM, not ratified): a sped-up recorded elicitation (conversation, interpretation surface, and growing net visible together) plus a bounded live segment in which a few turns elicit a fact forcing a structural revision of the net, run before/after in Petrinaut. -_Avoid_: live demo (unqualified — the live part is one bounded segment, not the format) - -### Simulation & evaluation - -**Situation pack**: -The interviewee-side bundle defining a user-to-be-simulated: situation, scenario, and persona — knowledge and motivations, some facts deliberately coloured by the persona's perspective. Private to the agent (or human) playing the user. Invariant: never authored from, or shaped to mirror, the IR — the elicitor's job is to excavate across that wall. -_Avoid_: fact pack (undersells the persona; collides with the answer key), persona pack (too narrow) - -**Answer key**: -The modeller-side list of facts the reference net needs, derived from the reference model — the evaluation rubric for what an elicitation should have excavated from a situation pack. Satisfies PRO-99's "written list of all facts necessary to make the net". Sits on the elicitor-team side of the wall; never part of the situation pack. -_Avoid_: fact list (ambiguous with situation-pack content) - -**Walking skeleton**: -A build that proves a transport or integration end-to-end on the real substrate (e.g. a real Flue agent + web UI) with stubbed internals. The term names the proof shape, not a disposal policy: the FE-1389 skeleton is retained as a durable CI gate, and its integration test pins runtime semantics nothing else does (do-not-weaken; see the Flue patterns audit). - -**Logic-prototype**: -A prototype that locks down mechanism semantics (e.g. capture sweeps, settlement) in isolation, without the full host substrate. +**Walking skeleton** — a build proving a transport or integration end-to-end on the real substrate +with stubbed internals. + +**Logic-prototype** — a prototype locking down mechanism semantics in isolation, without the full +host substrate. diff --git a/libs/@hashintel/brunch-agent/MISSION.md b/libs/@hashintel/brunch-agent/MISSION.md new file mode 100644 index 00000000000..5d0fa489d28 --- /dev/null +++ b/libs/@hashintel/brunch-agent/MISSION.md @@ -0,0 +1,31 @@ +# Mission + +The current objective, its acceptance proof, and the stop conditions. This is the one mutable +"what now" record; a specific branch's mission contract lives on that branch. + +## Objective + +Construct and review-and-revise, in that order; cold-start construction must be possible. + +## Acceptance proof + +A human conducts a real construct elicitation through the production Brunch server and the +Petrinaut assistant panel; captures persist to a target document owned by a principal and survive +reload; completion accounting is human-readable; every turn records time per purpose. Then a +bounded review-and-revise pass: open an existing source-grounded model, trace one element to its +source utterance, correct it in a few turns, and see a provenance-preserving net delta. + +## Stop or replan + +- A first question takes longer than the provisional target after the latency instrumentation + lands. +- Persistence needs a schema the harness must know. +- The panel needs Brunch-specific code inside `@hashintel/petrinaut`. +- An arc ends with only desk, simulated, or evaluation-side output and no production-path code + changed. + +## Deferred + +The harness-teaching layer (the plugin schema/repertoire machinery of ADR-0007/0008) is excluded +from the first post-reorientation branches; re-include it later in minimum-viable forms as a real +throughline demands. diff --git a/libs/@hashintel/brunch-agent/README.md b/libs/@hashintel/brunch-agent/README.md index 4454cd92d52..ecbf4e44213 100644 --- a/libs/@hashintel/brunch-agent/README.md +++ b/libs/@hashintel/brunch-agent/README.md @@ -1,25 +1,20 @@ # Brunch agent -Brunch is a stateful elicitation harness and package family inside the HASH monorepo. - -This directory is its context and agent-session root, not a package workspace: +Brunch is the stateful elicitation harness and package family at `libs/@hashintel/brunch-agent`. +- [`AGENTS.md`](./AGENTS.md) is the agent charter. +- [`MISSION.md`](./MISSION.md) is the current objective and stop conditions. - [`CONTEXT.md`](./CONTEXT.md) defines the domain language. -- [`docs/adr/`](./docs/adr/) records governing decisions. -- [`docs/specs/elicitation-kernel.md`](docs/specs/elicitation-kernel.md) defines the harness contract. -- [`docs/INDEX.md`](./docs/INDEX.md) indexes Brunch documentation. -- [`docs/control/STEERING.md`](./docs/control/STEERING.md) holds current strategic truth; - [`STRATEGY-LOG.md`](./docs/control/STRATEGY-LOG.md) records material strategic decisions. +- [`docs/specs/`](./docs/specs/) and [`docs/adr/`](./docs/adr/) record the harness contract and + prior design decisions (see [`docs/adr/README.md`](./docs/adr/README.md)). +- [`docs/evidence/`](./docs/evidence/) holds observed results and proofs. - [`packages/core/`](./packages/core/) is `@hashintel/brunch-agent`; its guarded `./prompts` - subpath ships the harness repertoire rendered by bindings and never imported by plugins. + subpath ships the harness repertoire, rendered by bindings and never imported by plugins. - [`packages/binding-flue/`](./packages/binding-flue/) is the Flue binding. - [`packages/transport-aisdk/`](./packages/transport-aisdk/) is the AI SDK transport. -- [`packages/plugin-gherkin/`](./packages/plugin-gherkin/) is the Gherkin target plugin: a - feature-anchored `plugin.yaml` and the verbatim-floor proposal type. -- [`packages/plugin-sdcpn/`](./packages/plugin-sdcpn/) is the SDCPN target plugin: an - objective-anchored `plugin.yaml` and its slot-assertion proposal type. -- [`../../../apps/brunch-agent/`](../../../apps/brunch-agent/) is the remote server and diagnostic - application. +- [`packages/plugin-gherkin/`](./packages/plugin-gherkin/) and + [`packages/plugin-sdcpn/`](./packages/plugin-sdcpn/) are the target plugins. +- [`../../../apps/brunch-agent/`](../../../apps/brunch-agent/) is the server and diagnostics app. HASH's repository root owns package discovery, dependency policy, the lockfile, and the Turbo task graph. diff --git a/libs/@hashintel/brunch-agent/docs/INDEX.md b/libs/@hashintel/brunch-agent/docs/INDEX.md deleted file mode 100644 index ddb1b6adc67..00000000000 --- a/libs/@hashintel/brunch-agent/docs/INDEX.md +++ /dev/null @@ -1,139 +0,0 @@ -# Document index - -One line per document: what it is, where it lives, where it's used. Protocol: -[`docs/agents/documentation.md`](agents/documentation.md). Statuses: `inbox` (awaiting -settlement) · `active` (artifact of a live effort) · `settled` (permanent home) · `superseded` -(retained history replaced by newer canon) · `accepted` (ratified ADR) · `external` (canonical -copy lives outside the repo). - -The authoritative role topology is defined by the documentation protocol. The role-based zones -below are authoritative. Agent protocols are registered through `AGENTS.md`; Brunch's supplement -to `/ds-steer` is [`docs/agents/steering.md`](agents/steering.md); cutting worktrees for a recorded -partition is [`docs/agents/partition-worktrees.md`](agents/partition-worktrees.md). - -## Inbox (awaiting settlement) - -| Document | Status | Date | Digest | Used by | -| ---------------------------- | ------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------ | -| [SDCPN JSON nets](inbox/SDCPNs/) | inbox | 2026-08-24 | Seven valid Petrinaut v1 files: two plain-net gas variants, gas SPN/CPN/DCPN, truck, and semiconductor; a prior `gases-5` reference is unconfirmed and likely erroneous, not part of the corpus | Frontier 0 corpus inventory; settlement/conformance pending | - -## Reference (settled sources) - -| Document | Status | Date | Digest | Used by | -| ----------------------------------------------------------------------------------------------------------- | ------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -| [agentic-elicitation-challenges](reference/agentic-elicitation-challenges-2026-08-06T10-02-41Z.md) | settled | 2026-08-06 | Turn 1 of the founding analysis: four contracts, packs, IR; source of the "capture meaning before representation" principle | elicitation-kernel spec §1 | -| [agentic-elicitation-criteria](reference/agentic-elicitation-criteria-2026-08-06T14-11-18Z.md) | settled | 2026-08-06 | Turn 2: hourglass, five proof obligations, ten invariants, smells, test matrix | elicitation-kernel spec §14 | -| [SDCPN Library - Ideas](reference/SDCPN%20Library%20-%20Ideas.md) | settled | 2026-08-11 | Eight CPS use-case sketches (physical/cyber/events/continuous-state/emergence anatomy), ChatGPT-drafted | FE-1357 map; FE-1363 candidates | -| [hash-sails-public-report.pdf](reference/hash-sails-public-report.pdf) | settled | 2026-08-11 (pub. 2026-01) | SAILS/ARIA public report: Safeguarded AI gatekeeper (world model + safety spec + verifier), biopharma supply-chain research, tacit knowledge as adoption barrier | FE-1357 map (the "why"); FE-1363 cold-chain anchor | -| [voice-implementation-recommendation-pplx](reference/voice-implementation-recommendation-pplx.md) | settled | 2026-08-11 | Perplexity research: voice-adapter options (ElevenLabs/OpenAI/Gemini/xAI) | FE-1359 (superseded in part by its findings) | -| [yannis-dora-lu-transcript](reference/yannis-dora-lu-transcript-2026-08-11.md) | settled | 2026-08-11 | Meeting transcript: no in-house interviewing practice; SDCPN-as-hypothesis aired; baseline-control and priming ideas | expert-meeting-findings note; FE-1360, FE-1361 | -| [amp-analysis-flue-vs-tilde](reference/amp-analysis-flue-vs-tilde.md) | settled | 2026-08-14 | Amp thread export: comparative assessment of the Flue and tilde agent frameworks (development and deployment stories) and its import for this project; verdict: keep Flue, Tilde is a control plane not a runtime | reconciled into flue-architecture-cheatsheet (2026-08-17); source of the pre-remote-exposure gates | -| [2026-08 SDCPNs for cyber-physical systems](reference/2026-08%20SDCPNs%20for%20cyber-physical%20systems.md) | settled | 2026-08 (settled 2026-08-18) | Unattributed draft blog post (image placeholders, typos): five-level SDCPN explainer applied to gas supply, truck fleet, semiconductor fab; arrived during the FE-1405 arc. Read skeptically: good pedagogy, promotional register — concedes its formal guarantees don't apply once continuous/stochastic features are used (open research problem), models carry heavy kernel/guard logic that strains the "formal and inspectable" claim, and Petrinaut's integrator limitation is admitted | Register-3 background (projection-target expressivity) only; not elicitation design input; no consumer yet | - -## Specifications and archived elicitation-kernel record - -| Document | Status | Linear | Digest | -| -------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| [spec.md](specs/elicitation-kernel.md) | settled | linked from FE-1366 (context-canonical) | The elicitation-kernel spec: 14 sections + adjudications; FE-1437 records the HASH package/application charter and ADR-0005 separates pure projection scaffolds from model-assisted executable realization | -| [product-description.md](archive/elicitation-kernel/product-description.md) | settled | none | STE-style product description | -| [product-description-plain.md](archive/elicitation-kernel/product-description-plain.md) | settled | none | Plain-prose rendering of the product description | -| [map.md](archive/elicitation-kernel/map.md) | settled | **mirrored in full**: FE-1366 | Completed wayfinder map | -| [issues/](archive/elicitation-kernel/issues) 01–13 | settled | **mirrored in full**: FE-1367–FE-1379 (relations preserved) | 13 resolved tickets | -| [notes/consistency-prepass](archive/elicitation-kernel/notes/consistency-prepass-2026-08-10.md) | settled | none | Pre-assembly contradiction audit (7 contradictions, adjudicated in spec Appendix A) | -| [plugin-contract-2026-08-25-declarative-draft](archive/specs/plugin-contract-2026-08-25-declarative-draft.md) | superseded | FE-1431; FE-1405 | Archive copy of the pre-ADR-0006 plugin contract: two schemas and two tables, `ScopeExpr`/`where`/`inSupport`, `firesWhen`, `completionAnchor`, typed fold/demand/variant/loss declarations; replaced by the per-formalism plugin file (`specs/plugin-contract.md`, `packages/plugin-sdcpn/plugin.yaml`) | -| [elicitation-completion-2026-08-25-full-draft](archive/specs/elicitation-completion-2026-08-25-full-draft.md) | superseded | FE-1402 | Archive copy of the pre-ADR-0006 completion draft: CPS DemandTable, `where`-scoped presence/slot clauses, completion-anchor matching, full deferral-licensing schemas; replaced by the `evaluateCompletion` invariants in `specs/elicitation-completion.md` | - -## Process-model elicitation artifacts (FE-1357) - -| Document | Status | Linear | Digest | -| -------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [recommendation-demo-vehicle](archive/decisions/superseded/recommendation-demo-vehicle.md) | superseded | linked from FE-1362/1328/1329/1331/1333 | Demo-vehicle recommendation: demo shell + artifact boundary; superseded by ADR-0004 (18 Aug meeting chose in-Petrinaut staging) | -| [petrinaut-integration-spec](specs/petrinaut-integration.md) | active | FE-1433 | Integration spec: elicitor as remote server behind the `aiAssistant` transport; suspension-borne client tools; `transport-aisdk`; principal + owner key; two gating spikes | -| [FE-1434 suspension verdict](evidence/proofs/spikes/fe-1434-suspension-verdict-2026-08-19.md) | active | FE-1434 | Flue 2.0.3 carries a terminating client-tool batch through one durable pending slot and one non-user result signal; 3- and 100-result cases preserve ids in two dispatches | -| [FE-1434 suspension evidence](evidence/proofs/spikes/fe-1434-suspension-evidence-2026-08-19.json) | active | FE-1434 | Deterministic transcript from the faux-provider runtime probe: native tool-result admission refused, signal resume succeeds, returned text is non-user and uncitable | -| [adapter-panel-spike-2026-08-19](evidence/proofs/spikes/fe-1435-adapter-panel-2026-08-19.md) | settled | FE-1435 | Real-panel spike verdict: AI SDK v6 SSE drives Petrinaut text/reasoning, default server-tool summaries, two live-editor client tools in one batched follow-up, and the diagnostics decorator; full POST/SSE transcript frozen as golden fixtures | -| [transport-aisdk-implementation-2026-08-19](evidence/proofs/implementations/fe-1436-transport-aisdk-2026-08-19.md) | settled | FE-1436 | Durable real-panel transport: application `/api/chat` endpoint, substrate-neutral harness reply events, AI SDK v6 encoding, boundary gates, opt-in protocol inspection, and a clean-checkout local Petrinaut launcher | -| [ask-return-implementation-2026-08-19](evidence/proofs/implementations/fe-1449-ask-return-2026-08-19.md) | active | FE-1449 | Ask suspend/return over the wire: the ask leaves as an awaiting client tool, the correlated `{ answer }` submission is admitted against durable history and resumes the conversation; stale/forged/duplicate/non-ask outputs refused before dispatch | -| [notes/grilling-inputs-2026-08-12](archive/planning-inputs/grilling-inputs-2026-08-12.md) | settled | referenced from map | Session carryover: destination trend, facets/motions, Dora-checklist validate table | -| [notes/expert-meeting-prep](archive/meetings/expert-meeting-prep-2026-08-11.md) | settled | referenced from map | Prep brief for the Yannis meeting | -| [notes/expert-meeting-findings](evidence/proofs/research/expert-meeting-findings-2026-08-11.md) | active | referenced from map | Meeting findings: 5 facts, 7 idea seeds, 2 commitments | -| [notes/open-questions-elicitation-design](archive/external-snapshots/open-questions-elicitation-design-2026-08-11.md) | superseded | — | Draft; canonical copy is the [Notion page](https://www.notion.so/hashintel/3b93c81fe024801b89b3cf63a9a6ff20) (`external`) | -| [research/petrinaut-survey](reference/research/petrinaut-survey.md) | active | gisted in FE-1358 resolution | Petrinaut architecture/assistant/format survey + coupling audit | -| [research/voice-feasibility](reference/research/voice-feasibility.md) | active | gisted in FE-1359 resolution | Voice verdict: bolt-on with constraints; T0–T3 tiers | -| [research/elicitation-strategy-literature](reference/research/elicitation/elicitation-strategy-literature.md) | active | gisted in FE-1360 resolution | Literature synthesis, 9 sections, verification-labeled | -| [research/re-interviewing-literature-worker-report](reference/research/elicitation/interviewing-literature-source-catalog.md) | active | noted on FE-1361 | Verbatim instruments: 34-mistake taxonomy, question typologies, LLM-interviewer results | -| [research/frontier-model-elicitor-failure-catalogue](reference/research/elicitation/frontier-model-elicitor-failure-catalogue.md) | active | FE-1407 | Test-oracle list for the harness (reclassified 2026-08-25 as test-bed material, not authority): typed frontier-model failure catalogue from the two baseline transcripts and indexed literature — mechanism, detection signature, accountable layer, bounded prevention claim, and the licensed-deferral boundary | -| [baseline evaluation evidence](evidence/evaluations/process-model-elicitation/baseline/) | active | gisted in FE-1361 resolution; FE-1431 | Baseline-control evidence: frozen conditions 1–2; cycle-one live arms from 2026-08-25 archived under `transcripts/cycle-1/`; cycle-two conditions 4–5 from 2026-08-26 in `transcripts/`; and the scored read-out freezing the plugin key catalogue while routing residual identity, quote-repair, classification, and session-control defects to harness work. Includes the first-run turn latency assessment (`condition-5-turn-latency.md`: 145 s/turn, 97% extraction, actions R0–R5) carried by STEERING; with the executable cases and protocol under `evaluations/` it is the simulated-expert harness for the walking-skeleton run (reclassified 2026-08-25 as test-bed material) | -| [ir-design](specs/intermediate-representation.md) | active | gisted in FE-1364 resolution; amended by FE-1480 | The IR design: Layer A (ratified on worked examples, FE-1397; definition sentence amended by ADR-0003) + the CPS plugin's ten-kind payload, deterministic scaffold and obligation contract (Layer B); executable code is realized downstream under ADR-0005 | -| [ir-worked-examples](evidence/proofs/design/intermediate-representation-worked-examples.md) | active | gisted in FE-1397 | Layer-A validation across Gherkin/CPS/BPMN + assurance: property verdicts, amendments, sublimation findings | -| [ir-design-plain](specs/intermediate-representation-plain.md) | active | strain findings on FE-1401; amended by FE-1480 | Plain-prose rendering of the IR design, including ADR-0005's split between deterministic scaffolding and model-assisted executable realization; notes that `plugin-sdcpn/plugin.yaml` is now the concrete rendering of Layer B | -| [notes/research-patterns-audit](evidence/proofs/audits/research-patterns-audit.md) | active | FE-1401 / card inputs on FE-1403 | Plain-language audit of ~30 research imports in 7 families, evidence-graded, with an 8-point strain appendix | -| [notes/harness-teaching-lineage-audit](evidence/proofs/audits/harness-teaching-lineage-audit.md) | active | FE-1406 (owning issue); input to ADR-0007 | Audit of every prior form of "what the harness teaches" (2026-08-06 → 08-25): fifteen restatements, the vocabulary each used, the layer each chose, and what became of it; finds the §11.5 split rule affirmed at every station and designed at none, the moves never enumerated in canon, and the SDCPN construct runbook mostly harness craft; strain appendix | -| [notes/penciled-directions-2026-08-14](archive/planning-inputs/penciled-directions-2026-08-14.md) | settled | FE-1401 | Penciled directions from the legibility session: 8 items with firming actions + editorial reflections | -| [capture-store-plain](reference/architecture/capture-store.md) | active | strain findings on FE-1401 | STE-leaning rendering of the capture-store semantics (FE-1390/FE-1389) with a load-bearing not-guaranteed section; 8-point strain report incl. two command-reachable unclosable-conflict paths (confirms FE-1419 commits 7/8) and the FE-1405 status-arity answer | -| [notes/deep-read-fe-1389](evidence/proofs/audits/deep-read-fe-1389.md) | active | FE-1401 / findings in FE-1420 | Deep-read of the walking skeleton: builder's account, spec-discharge table (issues 10/13 capabilities discharged; markdown floor contradicted in the UI), 12 findings; source of PR #10's backfilled record | -| [notes/deep-read-fe-1390](evidence/proofs/audits/deep-read-fe-1390.md) | active | FE-1401 / probes on FE-1419 | Deep-read of the capture store: spec-discharge table, write-time tiering assessment (penciled item 7), the FE-1405 status-arity answer, and live-probed confirmation of FE-1419's capture-store claims plus one new aliasing hole; source of PR #11's backfilled record | -| [plugin-contract-spec](specs/plugin-contract.md) | active | FE-1431 (spec issue); decided on FE-1405; amended by FE-1480; reshaped by ADR-0006; amended by ADR-0007 | Per-target-formalism plugin contract as data under harness-owned keys: identity block, contract keys (`ontology`, `schema` with a declared anchor, `patterns`), guidance and runbook cells that add to the repertoire default, `machinery`; `plugin-sdcpn/plugin.yaml` and `plugin-gherkin/plugin.yaml` normative as co-authored siblings, `plugin.schema.json` normative for shape; version binding, `project`/`validate` as code with the ADR-0005 outputs, surviving invariants, gates, open strains, and what ADR-0006 and ADR-0007 retired. | -| [elicitation-completion](specs/elicitation-completion.md) | active | FE-1402; rewritten under ADR-0006 | Nineteen invariants `evaluateCompletion(model, mustKnowRows)` must satisfy, framed as tests: derived boolean plus evidence report, floor as counts, question-relative demand over objective slices, universal active-objective check, status/precision/confidence separation, conservative conflict and divergence failure, stop/delivery/budget as non-inputs, read-time deferral licensing, no new persistence | -| [elicitation-completion-rehearsal](evidence/proofs/design/elicitation-completion-rehearsal.md) | active | FE-1402; inputs FE-1403/FE-1404/FE-1431 | Test-bed material, not authority (reclassified 2026-08-25): manual clause-level replay over all 44 FE-1361 prefixes against the retired domain-keyed CPS DemandTable; golden-fixture candidate for `evaluateCompletion` once re-expressed at kind level | -| [elicitation-completion-plain](evidence/proofs/design/elicitation-completion-plain.md) | active | FE-1402 legibility snapshot | Evidence, not authority (reclassified 2026-08-25): plain-language rendering of the pre-ADR-0006 completion draft and its translation strains; the invariants it explains survive in the rewritten spec | -| [cps-interview-guidance](archive/specs/cps-interview-guidance-2026-08-25.md) | superseded | FE-1403; inputs FE-1404/FE-1406/FE-1431 | Archived 2026-08-25 under ADR-0006: the FE-1403 CPS card set (CPS-Q01–Q05, GEN-Q02, two hint fragments) whose cards became kind-indexed patterns P01–P05, P12 and `Moves` steps in `plugin-sdcpn/plugin.yaml`; banner records the card→pattern mapping and the `domain` mis-tag; retained as test-bed material | -| [cps-interview-guidance-desk-replay](evidence/proofs/design/cps-interview-guidance-desk-replay.md) | active | FE-1403; inputs FE-1404/FE-1406/FE-1431 | Evidence, not authority (reclassified 2026-08-25): manual two-transcript prefix replay of the archived CPS cards — per-card firings, expected evidence deltas, deactivation boundaries, candidate dispositions, research ledger; desk discrimination only | -| [plugin-keys-pressure-review-cycle-1](evidence/proofs/design/plugin-keys-pressure-review-cycle-1.md) | active | FE-1431; FE-1406; FE-1393 | Evidence, not authority: cycle-1 pressure review of the ADR-0007 key catalogue — 100-situation corpus against generality / specificity / flexibility, per-key verdicts, three proposed shape changes for cycle two, seven source contradictions the repertoire resolves silently; input to `packages/core/schema/CHANGELOG.md` | -| [cps-interview-guidance-plain](evidence/proofs/design/cps-interview-guidance-plain.md) | active | FE-1403 legibility snapshot | Evidence, not authority (reclassified 2026-08-25): plain rendering of the archived CPS guidance with translation strains and their dispositions | -| [sdcpn-plugin](../packages/plugin-sdcpn/plugin.yaml) | active | FE-1404 (redefined toward the walking skeleton); supersedes the domain-keyed tables of FE-1402/1403 | The SDCPN plugin definition (`plugin.yaml`): the harness-owned keys of ADR-0007 — `ontology`, `schema` (declared `objective` anchor, floor, must-know rows over the IR spec's ten Layer-B kinds), `patterns`, guidance cells, runbooks for `construct` and `review-and-revise`, `machinery` — domain-neutral by rule; validated against `packages/core/schema/plugin.schema.json`. Companion: [`plugin-gherkin/plugin.yaml`](../packages/plugin-gherkin/plugin.yaml), the feature-anchored second formalism co-authored in the same cycle. | - -## Control, architecture reference, and migration archive - -| Document | Status | Linear | Digest | -| -------------------------------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [hash-monorepo-import-plan](archive/migrations/hash-monorepo-import-plan.md) | settled | FE-1437 | Native HASH assimilation plan: preserved history and child package workspaces under one Brunch context root, explicit authority cutover, exhaustive repository-material disposition, toolchain port, boundary gates, and verification | -| [SPEC-LEDGER](control/SPEC-LEDGER.md) | active until milestone-one closure | FE-1383 | Obligation-level status and evidence ledger for the elicitation-kernel specification; settles when the milestone closes | -| [STEERING](control/STEERING.md) | active | FE-1357 / FE-1476 | One compact mutable strategic control for the current objective, proof frontier, governing concerns, soft edges, gates, beliefs, cuts, stop conditions, and exceptional roots | -| [STRATEGY-LOG](control/STRATEGY-LOG.md) | active append-only | governing IDs referenced by STEERING | Material strategic decisions and supersession history; distinct from accepted architecture ADRs and from status or diary history | -| [flue-architecture-cheatsheet](reference/architecture/flue-architecture-cheatsheet.md) | active | commented on FE-1383; feeds docs/agents/flue-routing.md | Architect's consolidation of all 21 Flue guide pages: direct structured generation uses `harness.prompt`; model-delegated work uses `useSubagent`; three-lane boundary summary and ranked divergence risks; reconciled against installed Flue 2.0.3 source | -| [topology](reference/architecture/topology.md) | active | ratified → ADR-0002; N1 discharged by FE-1422 + FE-1392; local N5 implemented by FE-1391; N3 amended by FE-1437 | Pseudo-style verification of the package/app tree against the three-lane model and spec §12.2: portable ask/sweep protocols, Flue binding wiring, package boundaries, and application-only Brunch–Petrinaut composition | - -## Legibility engineering records and proofs (FE-1401) - -| Document | Status | Linear | Digest | -| ------------------------------------------------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [refactor-queue-2026-08-14](archive/engineering/legibility/refactor-queue-2026-08-14.md) | settled | FE-1419 | Nine-commit refactor queue from an inductive review of open PR comments: capture-store contract closure + verification-oracle integrity; second-order review of the FE-1400 sweep's own countermeasures | -| [flue-patterns-audit-2026-08-17](evidence/proofs/audits/flue-patterns-audit-2026-08-17.md) | active | commented on FE-1383 | Audit of Flue usage against the official docs: substantially canonical; two fragile spots since fixed; its two "undocumented semantics" strain items were later resolved by the cheatsheet's agent-hooks read (documented after all — the pins stay) | -| [flue-entry-projection-source-read-2026-08-18](evidence/proofs/audits/flue-entry-projection-source-read-2026-08-18.md) | active | FE-1391 source gate + FE-1392 refresh oracle; reshapes FE-1386 | Installed Flue 2.0.3 evidence followed through to the public reader/archive and a causal refresh-before-apply oracle; FE-1386 remains one behavioral pin | -| [remediation-plan-2026-08-17](archive/engineering/legibility/remediation-plan-2026-08-17.md) | settled | A1 discharged by FE-1422; A3/B1 by FE-1391; B2/B3 by source read + FE-1392 | Two ledgers from the consolidated sweep. FE-1392 resolves the private-model-call seam with direct `harness.prompt`, while keeping free-text/abandoned accounting in FE-1420 and the compaction pin in FE-1386 | -| [review-remediation-2026-08-18](archive/engineering/legibility/review-remediation-2026-08-18.md) | settled | FE-1432 | Executed queue from the cross-stack review: six lens-backed findings fixed, all 15 residual threads adjudicated and resolved, below-gate findings owned or refused, and three graduation proposals routed to FE-1401's tooling lane | -| [issue-pr-migration-2026-08-20/](archive/migrations/issue-pr-legibility-2026-08-20/) | settled | FE-1451 | Completed legibility migration: byte-exact snapshots of 73 Linear issues and 25 GitHub PRs, reviewed proposals, canonical stored-target hashes, rollback data, a drift-gated validator, and an append-only apply log | - -## Decision records (`docs/adr/`) - -Decisions taken _after_ the elicitation-kernel spec settled. The original spec text remains the -record of what was decided in August; later changes live in ADRs and, when an accepted execution -contract requires the spec to carry the new operating truth, in explicitly dated amendments. - -| Document | Status | Linear | Digest | -| ------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [0001-brunch-is-the-product-name](adr/0001-brunch-is-the-product-name.md) | accepted | FE-1388; package naming amended by FE-1437 | `brunch` remains the product and durable-agent identity: `brunch_*` tools and `brunch-gherkin-elicitor`; FE-1437 replaces the standalone `@brunch/*` scope with HASH's `@hashintel/brunch-agent*` package family | -| [0002-topology-and-placement-rules](adr/0002-topology-and-placement-rules.md) | accepted | FE-1401; FE-1422 is its one code change | The three-lane topology and placement rules N1–N6 ratified; N3 now places remote Brunch and Petrinaut composition only in applications; N2/N5 become boundary gates | -| [0003-three-register-ir](adr/0003-three-register-ir.md) | accepted | FE-1405; amended by FE-1480 | The IR is the elicited conceptual model, derived by a pure fold — three registers (assertions / model / projections); ADR-0005 narrows pure executable projection to deterministic scaffolds and obligation plans before downstream realization | -| [0004-in-petrinaut-staging-and-the-monorepo-import](adr/0004-in-petrinaut-staging-and-the-monorepo-import.md) | accepted | FE-1433; amended by FE-1437; extended by FE-1480 | September demo stages inside demo.petrinaut.org; reusable libraries remain mutually unaware; ADR-0005 extends the application-owned artifact path from projection scaffold and obligations to an executable file through Petrinaut client tools | -| [0005-model-assisted-sdcpn-realization](adr/0005-model-assisted-sdcpn-realization.md) | accepted | FE-1480 | A pure plugin projection emits an SDCPN scaffold, typed code-obligation sidecar, and loss report; the Brunch agent realizes executable TypeScript through Petrinaut client tools and deterministic compile/simulation gates | -| [0006-plugins-per-target-formalism](adr/0006-plugins-per-target-formalism.md) | accepted | design-convergence review 2026-08-25 | Plugins are per target formalism, authored as sectioned Markdown with fixed contract headings and three machine-read tables; domain-neutral by rule; retires the declarative ScopeExpr/firesWhen/DemandTable contract | -| [0007-harness-teaching-meets-plugin-content-at-fixed-keys](adr/0007-harness-teaching-meets-plugin-content-at-fixed-keys.md) | accepted | FE-1406 (owner), FE-1431, FE-1393; accepted 2026-08-25, key catalogue converging (decision 9) | Plugin authoring is a fixed set of harness-owned keys in four groups — contract data (`ontology`, `schema`, `patterns`), guidance typed by mechanism (`lenses`, `techniques`, `movements`, `licenses`, `motifs`, `smells`, `rabbit_holes`, `failure_modes`), per-job runbooks (`kickoff`, `trajectory`, `close`), machinery (`checks`, `tools`) — each rendered key → harness default → plugin cell; the repertoire is `packages/repertoire`; amends ADR-0006 decisions 2 and 5 | -| [0008-repertoire-and-plugin-contract-live-in-core](adr/0008-repertoire-and-plugin-contract-live-in-core.md) | accepted | FE-1507; accepted 2026-08-26 | The repertoire is core-owned prompt data behind `@hashintel/brunch-agent/prompts`; plugins must not import that subpath; the standalone repertoire workspace is removed; amends ADR-0007 decision 8 | - -## External canonical documents - -| Document | Where | Digest | -| --------------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Brunch — September Plan](https://www.notion.so/hashintel/Brunch-September-Plan-3b33c81fe02480a5af6bf3089c3ee640) | Notion | Product leadership's September demo vision | -| [Petri Net business use cases (DB)](https://www.notion.so/hashintel/3893c81fe0248064baa9c13fed48e016) | Notion | Use-case database incl. the spec'd Production Scheduling exemplar | -| [Eliciting process models: open questions](https://www.notion.so/hashintel/3b93c81fe024801b89b3cf63a9a6ff20) | Notion | Team-facing known-unknowns doc, awaiting comments | -| [Cyber-physical process elicitation (Dora, PRO-98)](https://www.notion.so/hashintel/3b93c81fe0248019a7beda9bb31df2c8) | Notion | 14-category elicitation ontology + strategy outline + UX ideas; input claims for FE-1362/63/64 grilling — several categories map to net constructs, several "live only in the intermediate representation" | -| Wayfinder maps FE-1357 (live), FE-1366 (archive) | Linear | Issue-tracker records; see `docs/agents/issue-tracker.md` | - -## Path migration note (2026-08-12) - -`.scratch/` is retired. Historical Linear references to `.scratch/...` and later -`docs/planning/...` locations retain their evidentiary meaning; current repository paths are the -role-based locations indexed above. diff --git a/libs/@hashintel/brunch-agent/docs/adr/README.md b/libs/@hashintel/brunch-agent/docs/adr/README.md new file mode 100644 index 00000000000..e1b1e3fe06b --- /dev/null +++ b/libs/@hashintel/brunch-agent/docs/adr/README.md @@ -0,0 +1,9 @@ +# Decision records (historical) + +These ADRs record design decisions accepted under the prior process. They are now **hypotheses, +not obligations**: unimplemented design is not a roadmap, and a branch may depart from any of +these by noting the divergence in its commit. Implemented decisions are evidence, not authority — +re-earn before building further on them. + +Internal references to retired paths (`docs/control/`, `docs/agents/`, `docs/INDEX.md`) are +historical and not maintained. diff --git a/libs/@hashintel/brunch-agent/docs/agents/arc-close.md b/libs/@hashintel/brunch-agent/docs/agents/arc-close.md deleted file mode 100644 index a6fe04a72ab..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/arc-close.md +++ /dev/null @@ -1,89 +0,0 @@ -# Arc close - -Arc close is the required final control pass before submitting a branch that closes a work arc. -Load the `arc-close` skill and run this protocol; do not rely on remembering its constituent -checks. It complements, rather than replaces, the legibility protocol's close-out rendering for -arcs with significant agent-generated output. - -An arc is closing when a bounded branch or session lands implementation, settles a planning or -design decision, closes or materially changes a Linear issue, or changes a project control -surface. Exploratory work that leaves no durable truth does not require arc close. - -If a conditional pass changes nothing, do not append a dated evaluation or no-op record. Git is -the history of these control surfaces. - -## Required sequence - -### 1. Settle the inbox and reconcile the index - -Always inspect `docs/inbox/` and `docs/INDEX.md` together. - -- Promote settled inbox material to its role-based home under `documentation.md`. Do not add to the - retired `docs/planning/` or `docs/history/` paths. -- Delete source material only when its durable information has been transferred and its - consumption is named. -- Ensure every document under `docs/` except `docs/INDEX.md` and `docs/agents/**` is indexed and - every index entry still resolves. -- Update status, ownership, and digest text when this arc changed their truth. - -### 2. Audit the Linear registry and touched references - -Always run `turbo run linear:graph --filter '@hashintel/brunch-agent' -- --all`. Inspect every -project issue's assignment and every open issue with no parent. - -- Every non-root issue must have a parent. -- Every intentional root must be a recognized map or sweep root under the registry rule, or be - named under **Exceptional roots** in `docs/control/STEERING.md`. -- Subject to [the issue tracker's external-write approval gate](issue-tracker.md#conventions), - repair missing parentage in Linear when the intended owner is unambiguous; otherwise record the - unresolved root in `STEERING.md`. -- Re-read every issue the arc closes or materially changes. Repair stale branch, dependency, - evidence, and document references before closing it, subject to the same approval gate for any - Linear mutation. -- Follow `issue-writing.md`: preserve a root issue's human-owned contract and put agent-maintained - detail inside `🏗️ Agent notes`. - -### 3. Reconcile the spec ledger when affected - -Update `docs/control/SPEC-LEDGER.md` in the same change when the arc builds, disproves, -supersedes, or changes evidence for a milestone-one specification obligation. Change the smallest -affected set of rows; do not add an evaluation narrative. When milestone one closes, settle the -ledger as a terminal record rather than keeping it artificially live. - -### 4. Reconcile the current control when affected - -Reassess `docs/control/STEERING.md` only when exceptional roots, active soft edges, or project-wide -sequencing/strategy materially change. Ordinary blockers, parents, project membership, and ticket -movement remain Linear facts and are not independent steering triggers. - -Use the Linear graph for deterministic facts, then check soft edges, exceptional roots, governing -strategy, gates, and proof frontier. Linear remains canonical for hard blockers, state, assignment, -and hierarchy. If the judgment did not change, leave the control untouched. If a material strategy -trigger fired, validate that the new append-only strategy entry has evidence and supersedes, and -that `STEERING` references it. No-op reconciliation persists nothing. - -### 5. Reconcile steering and proof when triggered - -If a steering trigger fired, invoke `/ds-steer`. It consults the Brunch -[steering supplement](steering.md); do not copy its procedure here. - -If no trigger fired, continue the current proof frontier without a no-op steering update. - -### 6. Repair tense and report - -Read the arc's planning prose in the state that will exist after landing. Remove stale future -tense, provisional labels, temporary pointers, and inaccurate status language. Report which -control surfaces changed and which conditional passes were not applicable; do not persist the -no-op report in those surfaces. - -## Definition of done - -Arc close is complete when: - -1. inbox and index agree with the tree; -2. the Linear orphan audit has no unexplained roots; -3. touched issue references are current; -4. affected spec-ledger rows are current; -5. affected steering soft edges, roots, strategy, gates, and frontier are current; and -6. any triggered steering pass meets `/ds-steer`'s completion criterion; and -7. changed planning prose reads correctly after landing. diff --git a/libs/@hashintel/brunch-agent/docs/agents/documentation.md b/libs/@hashintel/brunch-agent/docs/agents/documentation.md deleted file mode 100644 index 880ba8d3099..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/documentation.md +++ /dev/null @@ -1,91 +0,0 @@ -# Documentation protocol: ingest, promote, index - -This protocol assigns one authority to each kind of durable knowledge. It complements -`issue-tracker.md`, which governs issue facts. `docs/agents/` remains the operating-guidance set, -and `docs/INDEX.md` remains the registry described below. - -## Authoritative topology - -| Location | Role | -| --- | --- | -| `docs/control/` | Current steering, append-only strategy rationale, and the separate obligation ledger | -| `docs/specs/` | Required behavior | -| `docs/adr/` | Accepted decisions | -| `docs/evidence/proofs/` | Immutable observed proof, witness, and implementation snapshots | -| `docs/evidence/evaluations/` | Immutable evaluation runs and readouts | -| `docs/reference/` | Stable explanatory and source material | -| `docs/archive/` | Historical, superseded, or settled material with no current authority | -| `docs/inbox/` | Transient, untriaged intake | -| `evaluations/cases/` | Executable evaluation cases and corpora | -| `evaluations/protocols/` | Executable evaluation procedures | -| `evaluations/oracles/` | Executable checks for validated categorical claims | - -Effort is metadata recorded in the index or document, not a placement rule. Do not create an -effort-shaped documentation tree. - -The role topology is physically authoritative. No document may remain under the retired -`docs/planning/` or `docs/history/` paths. - -External stores hold pointers or tracker facts, never the only repo-owned document. Before moving -or deleting a path referenced from Linear, Notion, or another external store, repair every pointer; -external writes require their own approval. Nothing is deleted until its `INDEX.md` entry records -the disposition. - -## Evidence vocabulary - -- **Case / corpus**: bounded evaluation input, or a reviewed collection from which cases are - selected. It defines what may be presented, not the expected answer. -- **Fixture**: reviewed, versioned setup derived from a case and suitable for a production-path - run. It may provide domain state, never missing product wiring. -- **Run snapshot**: immutable capture of inputs, environment identity, production entrypoint, - outputs, and result for one execution. -- **Oracle**: executable check promoted from a validated categorical claim. Hidden answer keys and - oracles stay behind the information wall and are not interviewee or elicitor inputs. - -An **immutable legibility snapshot** renders the proof in another register and records the strain -found during translation. A **witness record** identifies the claim observed, scenario and build, -witness, date, observation, and verdict. UX, interpretation, live-runtime, and -demo-comprehension claims require one unless explicitly inapplicable. See `legibility.md` for the -render-and-read mechanics. - -## Intake, promotion, and disposition - -1. **Arrive:** transient material enters `docs/inbox/`, timestamped when arrival time matters. -2. **Register:** when first used, add it to `docs/INDEX.md` with status `inbox`. -3. **Review:** identify provenance, consumer, information-wall boundary, and intended authority. -4. **Promote:** - - required behavior goes to `docs/specs/`; - - accepted decisions go to `docs/adr/`; - - observed proof and witness snapshots go to `docs/evidence/proofs/`; - - evaluation run readouts go to `docs/evidence/evaluations/`; - - stable explanations and source material go to `docs/reference/`; - - executable cases, protocols, and oracles go outside docs under `evaluations/`; - - superseded or settled context with no present authority goes to `docs/archive/`. -5. **Reconcile:** update the index and all internal and approved external pointers atomically. - -Promote a validated categorical claim to an oracle when recurrence is plausible, the claim is -mechanizable, and silent regression matters. Keep judgment that cannot be mechanized in protocol -or review guidance. A run snapshot never becomes a mutable control, and a control surface never -accumulates run history. - -## Mutable controls - -`STEERING.md` is the one compact mutable strategic control: current objective, selected proof -frontier, governing concerns, soft edges, cuts, gates, beliefs, exceptional roots, and stop or -replan conditions. Linear's mechanical frontier filters for available work; it does not select the -proof frontier. `STRATEGY-LOG.md` is immutable append-only rationale for material strategic choices; -it is distinct from ADRs, which own accepted architecture. `SPEC-LEDGER.md` remains a separate -conditional obligation control. Link evidence and history instead of copying chronology: Git is the -mutable-control history. Do not add diary or status entries to either strategic control. Linear -owns issue state, hierarchy, assignment, and hard blockers. - -## Index and link rules - -- Every document under `docs/` except `docs/INDEX.md` and `docs/agents/**` has exactly one covering - `docs/INDEX.md` row, and every row resolves. Every agent protocol is reachable from `AGENTS.md`. -- Introduce an issue ID with a gist so prose survives loss of tracker access. Outside control and - tracking surfaces, issue IDs are citations rather than load-bearing facts. -- Reconcile stale tense, status, provenance, and links when an arc changes their truth. -- Drafts are git-ignored ephemera, never indexed or linked from durable records. - -Arc close performs inbox, index, pointer, and control reconciliation; see `arc-close.md`. diff --git a/libs/@hashintel/brunch-agent/docs/agents/domain.md b/libs/@hashintel/brunch-agent/docs/agents/domain.md deleted file mode 100644 index a0a98c58290..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/domain.md +++ /dev/null @@ -1,45 +0,0 @@ -# Domain Docs - -How engineering skills consume Brunch domain documentation inside the HASH monorepo. - -## Before exploring, read these - -- **`CONTEXT.md`** at the Brunch context root -- **`docs/adr/`** — read ADRs that touch the area you're about to work in - -If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `ds-domain-modeling` skill (also reached from the grilling and codebase-deepening flows in the same skill set) creates them lazily when terms or decisions actually get resolved. - -## File structure - -Brunch is one context inside the multi-context HASH repository: - -```text -libs/@hashintel/brunch-agent/ -├── CONTEXT.md -├── docs/adr/ -│ ├── 0001-example-decision.md -│ └── 0002-another-decision.md -└── packages/ - ├── core/ - ├── binding-flue/ - ├── transport-aisdk/ - └── plugin-gherkin/ - -apps/brunch-agent/ # host module governed by this context -``` - -Package seams do not imply separate domain contexts. Add another Brunch `CONTEXT.md` only if the -domain language itself diverges enough to require an explicit context map; do not create one merely -because another binding, transport, plugin, or host appears. - -## Use the glossary's vocabulary - -When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids. - -If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `ds-domain-modeling`). - -## Flag ADR conflicts - -If your output contradicts an existing ADR, surface it explicitly rather than silently overriding: - -> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_ diff --git a/libs/@hashintel/brunch-agent/docs/agents/git-workflow.md b/libs/@hashintel/brunch-agent/docs/agents/git-workflow.md deleted file mode 100644 index 6545a355da4..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/git-workflow.md +++ /dev/null @@ -1,63 +0,0 @@ -# Git workflow: Graphite stacks - -Branches are managed with **Graphite** (`gt`), matching HASH's repository-wide use of Graphite -(its CI runs the Graphite optimizer). The standalone repository's late `gh stack` convention does -not carry over. The unit of branching is the **Linear issue**: every stacked branch answers to at -least one issue, created when work on that issue starts, and a branch may carry several issues -when they are built together (two epicentres that settle one interface, for instance). Work -discovered while resolving an issue (slices, refinements, side-fixes, a pivot it forces) stays on -that issue's branch rather than getting a branch of its own; work with no issue behind it never -gets a branch. Branches predating this convention (and the trunk) may mix multiple issues. - -## git vs gt boundary - -Use **git** for local operations that don't touch the stack: `status` / `diff` / `log`, -`add` / `commit`, `stash`. Use **`gt`** for stack-aware operations: `gt create`, `gt submit`, -`gt restack`, `gt sync`, and `gt checkout`. Raw branch creation or rebasing bypasses Graphite's -stack parentage metadata; commits and reads are safe as plain git (run `gt restack` afterwards -if upstack branches exist). Do not use `gh stack` in `hashintel/hash`. - -## Shared-worktree safety - -A branch switch changes the checkout under every process using that worktree. Before `gt create` -or `gt checkout`, record the current branch and inspect the worktree for unexpected changes or -in-flight agents. If another agent may be active, use a separate worktree instead of switching the -shared one; never stash, reset, clean, or otherwise claim work you did not create. Restore the -branch you found after the stack operation unless the user asks to leave the worktree elsewhere. - -A recorded **partition** gets one reusable worktree per effort; see -[`partition-worktrees.md`](partition-worktrees.md). Those directories outlive a single ticket. -The unit of branching is still the Linear issue: `gt create` inside the effort's worktree when -work on an issue starts. A holding branch is allowed only so a cut-now effort without an issue -yet can occupy a worktree; it is not submitted. Re-braid when the partition declares it, not at -a fixed ticket depth ([`partition-worktrees.md`](partition-worktrees.md)). - -## Naming - -- **Branch**: `{prefix}/{issue-id}-{keywords}` (e.g. `ln/fe-1362-demo-vehicle`). -- **PR title**: `{ISSUE-ID}: {Linear issue title in sentence case}` - (e.g. `FE-1362: Decide the September demo vehicle`). -- PR descriptions are written when tying off a branch, not during active development. They fill - the repository template (`.github/pull_request_template.md`) with the visible-summary / - `🏗️ Agent notes` split applied inside its sections, per `issue-writing.md`. - -## Deposit rule - -Work deposits its own description at authoring time, whatever tool authored it: a commit -carries a body that explains outcome and mechanism (the FE-1400 sweep's messages are the -register), and a branch is not tied off until its PR body says what it establishes. A -semantically heavy branch with an empty message is a defect, not a style choice — prose -backfill is remediation, not workflow (see `legibility.md`). - -## Lifecycle - -```text -gt create {prefix}/fe-XXXX-keywords # new branch stacked on the current one -# ... work ... -git add && git commit # plain git for commits -gt submit # push + create/update the PR when ready -gt sync # after merges: pull trunk, restack, prune -``` - -Trunk is `main`. Link the PR from the Linear issue (or let Linear's GitHub integration attach -it) so the issue records where its work landed. diff --git a/libs/@hashintel/brunch-agent/docs/agents/issue-tracker.md b/libs/@hashintel/brunch-agent/docs/agents/issue-tracker.md deleted file mode 100644 index 930523991b7..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/issue-tracker.md +++ /dev/null @@ -1,152 +0,0 @@ -# Issue tracker: Linear - -Issues for this repo live in **Linear**, worked through the `linear` CLI (see the -`tool-linear-cli` skill). Long-form artifacts — specs, research write-ups, notes — stay in this -repo in the role-based topology defined by `documentation.md`; Linear issues link to them by repo -path (and to Notion/Google docs by URL). The issue is the tracker record; the repo file is the -document. - -How issue titles and bodies are written — the contract/execution-record split, outcome-shaped -titles, plain-prose context — is covered in `issue-writing.md`; it applies to every issue an -agent authors from this repo. - -## Conventions - -**Approval gate:** reading Linear is allowed, but obtain explicit approval before any issue -creation, edit, comment, hierarchy change, state change, project mutation, or other write. Approval -for one named operation does not authorize adjacent mutations. - -- **Default team**: `FE`. **Project**: `brunch-agent`. Every approved new issue is created with - `linear issue create --team FE --project brunch-agent --assignee self`, plus `--parent` when it - is not a root. The exception is a Wayfinder child: create it unassigned so `/ds-wayfind` can claim - it by assigning the driving developer before work. Verify assignee, project, and parent after - creation. Assignment denotes accountable human ownership; on a Wayfinder child it also serves as - the canonical claim. The project is the ownership boundary for this codebase — see the registry - rule below. -- Related work also lives on teams `PRO` (product) and `H` (HASH) — read/reference those freely; - create there only when asked. The legacy `brunch` project holds the old brunch product's - history and is not this codebase's tracker. -- Use `--description-file` / `--body-file` for any multi-line markdown (shell-escaping otherwise - mangles it). -- Triage state is expressed through Linear workflow states and labels (see `triage-labels.md`). -- Comments and conversation history go on the issue as Linear comments, shaped per - `issue-writing.md`'s comment rules: the decision or change in one or two sentences, with - detail in `🏗️ Agent notes`. - -## When a skill says "publish to the issue tracker" - -After explicit approval, create a Linear issue on team `FE`, project `brunch-agent`. If the content -is long-form, place it by its role under `documentation.md` and link the repo path from the issue -description. - -## When a skill says "fetch the relevant ticket" - -`linear issue view ` (e.g. `FE-1333`). The user will normally pass the identifier directly. - -## Editing issue bodies from the CLI - -Bodies carry collapsed `🏗️ Agent notes` sections (`issue-writing.md`), and agents maintain -them by fetching, editing, and pushing the raw description. Fetch immediately before every -write, preserve the human-owned summary, and apply the smallest material change; never push a -stale local copy. Three more facts keep that process safe: - -- **Read the raw description via GraphQL**, never via `issue view` — view prepends a - title/state header that would be pushed back into the body: - - ```bash - linear api --variable id=FE-XXXX <<'GRAPHQL' | jq -r '.data.issue.description' - query($id: String!) { issue(id: $id) { description } } - GRAPHQL - ``` - -- **Linear normalizes markdown on save** (collapsed-section spacing, `-` → `*` bullets). A diff - against your draft is not drift; don't "fix" it. -- **Issue references in Linear bodies and comments are full URLs** - (`https://linear.app/hash/issue/FE-XXXX`), which Linear renders as issue chips — a bare ID - stays dead text. In repo documents the opposite holds: bare IDs with a gloss, per - `documentation.md`. - -## Project updates - -Linear project updates (`linear project-update`) reach a wider audience than issue comments. -They give a plain-prose summary of decisions, confidence changes, risks, and opportunities -since the last update, using the native health field. They contain no working detail, and empty -sections are omitted. Draft one from the changes recorded in issue comments since the last -update. Publish it to the `brunch-agent` project. - -## Wayfinding operations - -Used by `/ds-wayfind`. The **map** is a Linear issue with one **child** sub-issue per ticket. -Linear owns issue facts: state, hierarchy, project membership, assignment, and hard blockers. -`docs/control/STEERING.md` is the strategic control and commissions every Brunch map. The -mechanical frontier filters for available work; `/ds-steer` selects the proof frontier. - -- **Activity kind**: the canonical skills require semantic kind `wayfind` on maps and tickets and - `dogsled:unframed` on child tickets. Those labels are not configured in this Linear workspace. - `/ds-wayfind` therefore routes to `/ds-setup` before creating a new map; loading an existing map - does not authorize metadata backfill. All Linear writes remain approval-gated. -- **Map**: an FE root issue in project `brunch-agent`, labeled `wayfinder → map` (label group - `wayfinder`, children `map` / `research` / `prototype` / `grilling` / `manual-task` — created - 2026-08-11; `manual-task` stands in for the skills' `task` type because the workspace already has - an unrelated "Task" label). The map body is Destination / Strategic context / Notes / Landing - evidence / Decisions so far / Not yet specified / Out of scope. Strategic context is required - and names `STEERING.md` as owner, the intended contribution, governing concerns with operative - meaning, and related maps. -- **Child ticket**: a sub-issue of the map (native parent relation), same team and project, - carrying its `wayfinder → ` label. Its compact decision contract holds Question / Context / - Resolution evidence / Out of scope. -- **Blocking**: Linear's native **blocks / blocked-by** relations. A ticket is unblocked when every - issue blocking it is closed (Done or Canceled). -- **Mechanical frontier**: open, unblocked, unclaimed sub-issues of the map — lowest issue number - first. This is an availability filter, not the strategic proof frontier. Before work, inspect - issue state and any active branch or PR to avoid duplicate execution. -- **Resolve**: post the answer as a comment on the issue, set state **Done**, then append a one-line - gist + link to the map issue's _Decisions so far_ section (edit the map description). -- **Out of scope**: set state **Canceled** and record the gist + reason in the map's _Out of scope_ - section. -- **Landing**: append the `/ds-wayfind` Landing section only after every child is Done or Canceled - and _Not yet specified_ is empty. An empty mechanical frontier is insufficient. The commissioned - map stays open and routes to `/ds-steer`, which reconciles `STEERING.md`, satisfies the root-issue - close contract, and closes the map. Landing or closure changes execution state only; neither - resolves a governing concern. -- Pre-existing product issues (the PM's stubs) are **referenced** from map tickets via _related_ - relations — never duplicated as wayfinder tickets and never closed by the map. A wayfinder - ticket that validates a product issue links to it and records its verdict in the resolution - comment. - -## The registry rule - -**Project membership is the ownership boundary**: an issue belongs to this codebase iff it is -in the `brunch-agent` project. Nothing else — no label, no team, no root-walking — decides -belonging. Within the project, every issue must additionally be **reachable from a root**: either -it is a sub-issue (directly or transitively) of a root map — currently FE-1383 (build) and -FE-1357 (demo + plugin spec) — or a sub-issue of a named sweep ticket (FE-1401-style), or it -_is_ a root and `docs/control/STEERING.md` names it under **Exceptional roots**. An -issue in the project but reachable from no root is captured-then-orphaned, the failure mode this -rule exists to stop. Set the parent at creation (`--parent FE-XXXX`), not in a later sweep. - -Audit (run at arc close, alongside the legibility protocol's consolidation step): - -```shell -turbo run linear:graph --filter '@hashintel/brunch-agent' -- --all -``` - -Check each open row without a `p:` parent against the roots above. An orphan gets a parent or an -explicit root listing in `STEERING.md` — silence is not an option it has. The projection is -project-wide rather than assignment-scoped. The graph also audits every project issue against the -current authenticated user; mismatches require review, never auto-repair. Existing reassignment is -a separate write and remains approval-gated. A shared custom view — "brunch-agent: open without parent" — surfaces -candidate orphans continuously; its only legitimate rows are the roots themselves. - -## Historical note - -Before 2026-08-11 this repo tracked issues as local markdown under `.scratch//` -(map at `map.md`, tickets at `issues/NN-.md`). The completed `elicitation-kernel` effort -remains in that form as the canonical archive (now at `docs/archive/elicitation-kernel/`), and is **mirrored in Linear for team -visibility** as FE-1366 (map) with sub-issues FE-1367–FE-1379, all Done, blocking relations -preserved. New efforts go to Linear directly. - -Between 2026-08-11 and 2026-08-20 lite work was identified by a `lite` label plus the shared -`brunch` project — filters, not ownership, which is how six pre-registry stubs (FE-1328–FE-1334) -ended up orphaned. On 2026-08-20 the `brunch-agent` project was created, all 73 lite issues -moved into it, and the `lite` label was deleted; the project itself is now the boundary. diff --git a/libs/@hashintel/brunch-agent/docs/agents/issue-writing.md b/libs/@hashintel/brunch-agent/docs/agents/issue-writing.md deleted file mode 100644 index ce79711f39a..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/issue-writing.md +++ /dev/null @@ -1,229 +0,0 @@ -# Writing issues and pull requests - -How to write Linear issues and GitHub pull requests for this repo. Adapted from the dogsled -`ds-writing-issues` skill (the "issue contract"); motivated by team feedback that agent-authored -records read as jargon and are not readable by non-engineers. Apply whenever creating or editing -an issue title or body or a pull-request title or description. - -This file governs **structure and house style**. Write the visible layer as **plain technical -prose** for an informed colleague who does not know the implementation. The style is Google -Developer Documentation plus GOV.UK plain English, with INCOSE precision but not INCOSE -formality: complete sentences, short paragraphs, active voice, concrete nouns and direct verbs. -State causal, temporal, and conditional relationships explicitly. Keep sentence structure -simple without simplifying the idea; prefer two clear sentences over one compressed sentence. - -Respect the reader's existing knowledge. Supply the context needed to judge the change, but do -not add named theories, tutorial passages, or persuasive flourishes merely to demonstrate -authority. Walk through the relevant evidence, state the verdict at the strength that evidence -supports, and label opinion as opinion. Trust colleagues to ask when they need more; cut -pre-emptive explanation before cutting facts they need to act. - -Use shared product and system vocabulary, but avoid implementation-specific names unless they -are necessary to explain the behavior. Do not write in telegraphic, checklist, ticket, -changelog, or runbook style. Avoid fragments and labeled fields. Use a list only when readers -need to compare or enumerate parallel items; use prose when the relationship between facts is -the information. - -The org technical-writing skill drafted in -[internal-agents#20](https://github.com/hashintel/internal-agents/pull/20) (GEN-449) supplies the -plain-word and banned-words checks. Search all prose against that list before publishing, -regardless of the PR's merge state; exact machine text is exempt. The list transcribes what -colleagues asked for. - -Every issue serves two audiences: the team, who scan for direction and progress, and the agent, -which needs precise state to continue the work. Don't make one body serve both equally. Give -the issue a **contract** — the human-readable summary — above, and an **execution record** — -the working state — inside a collapsed `🏗️ Agent notes` section below. The human driving the -work owns the summary; agents may draft or update it on that person's behalf. The rhetorical -mode changes by layer: **task language for scanning, explanatory language for understanding, -specification language for execution.** - -## Who carries the contract - -The test is parentage. Every root issue carries the contract. A child issue inherits legibility -from its parent, keeps the shape its driving workflow requires, and carries `dogsled:unframed` so -team-facing views can filter it out. A teammate-authored issue outside this workflow keeps its -author's structure; comment, relate, and record verdicts without rewriting its title or body unless -that author delegates the change. - -Before changing an issue that carries the contract, fetch its current raw body and read the -human-owned summary. -Preserve edits made since the agent last saw it. Change that summary only when acting on behalf -of its owner and only for a material change. Never regenerate it from a stale local draft. - -## Title — the scan layer - -Start with an active verb and name the concrete task, problem, or decision in the fewest words -that remain clear. Examples include "Keep issues easy to scan," "Stop duplicate -notifications," "Decide how agents retrieve planning decisions," and "Map the September demo." -Research, planning, documents, and maps are tasks too; use verbs such as "decide," "test," -"write," "map," or "plan." - -Match the title to the issue's current commitment. If the approach is undecided, name the -problem or decision rather than a favored implementation. Once an approach is agreed and -implementing it is the task, name it directly. Domain terms the wider team already uses -("elicitation," "Petrinaut," "net") belong in a title; internal class, package, framework, and -algorithm names belong only when changing that named mechanism is itself the task. - -Title a bug by its observable symptom, not the hypothesized root cause. Internal work names its -real engineering task rather than inventing an end-user story. - -## Context — the prose layer - -One or two short paragraphs of plain prose at the top of the body, mandatory on every issue that -carries the contract; two to four sentences suffice for a small task. The reader should be able -to recover: -**current state → consequence → intended change → material status or uncertainty.** - -The central rule: **use a list when the list itself is the information; use prose when the -relationship between the facts is the information.** Cause, impact, direction, status, and -uncertainty are relationships — prose. The failure mode is the property-bag (`Problem: … / -Impact: … / Solution: …`); write the explanation instead. Update the context only on a -_material_ change — outcome, scope, status, risk, timing — never on routine progress. - -When an issue comes from user, stakeholder, or teammate feedback, quote their words directly -and link the original conversation when its audience is allowed to read it. A summary can lose -the pain or qualification that made the feedback useful; prefer the source when it is -available. - -## Wayfinder maps - -A map is an aggregating root issue, so it carries both layers: a **plain-prose preamble** -(the context layer, written so a non-engineer understands what the effort is, why, and where it -stands), then, inside `🏗️ Agent notes`, the Wayfinder working sections (Destination / Strategic -context / Notes / Landing evidence / Decisions so far / Not yet specified / Out of scope) as the -execution record. Every Brunch map is commissioned by `docs/control/STEERING.md`, so Strategic -context is required. Append Landing when the route is clear. The map's list-shaped sections are -earned — enumerating many children's state is the information; `Not yet specified` is the map's -one home for known-unknowns. When resolving a ticket updates the map, refresh the preamble's status -sentence in the same edit. At commissioned-map close, `/ds-steer` empties the mutable map sections, -posts an immutable resolution comment that points to both Landing and the reconciled strategic -owner, then closes the root. Each Linear write remains separately approval-gated. - -## The execution record - -The working layer lives inside a `🏗️ Agent notes` section that Linear and GitHub render closed -by default: - -``` -+++ 🏗️ Agent notes - -…working detail… - -+++ -``` - -on Linear; `
🏗️ Agent notes
` on GitHub PR descriptions -and long comments. Linear requires the space after `+++` and a blank line on both sides of the -working detail; its API inserts that whitespace when it is absent. The label is one canonical -string: **copy the complete wrapper from here, never retype it**. The emoji carries a variation -selector, so visually identical labels can have different bytes. Write bare domains as explicit -Markdown links when raw-body fidelity matters; Linear otherwise expands them into link syntax. -The section is **agent-maintained**: agents update it by fetching the raw body, editing, and -pushing back (see `issue-tracker.md` for the safe process), so a human edit inside it can be -overwritten. The human-owned summary outside this section must be preserved unless its owner -has delegated the change. - -The content is optional and schema-free: hold whatever the workflow needs (constraints, -assumption tables, acceptance criteria, asset links). Present when there's something to hold; -never mandatory boilerplate. Technical detail is additive — never deleted merely to simplify -the issue, only moved into `🏗️ Agent notes`. - -## Pull requests - -A pull request uses the same two layers, expressed through the repository's pull-request -template. Its title is `{ISSUE-ID}: {current Linear issue title}` as required by -`git-workflow.md`. Its body **fills `.github/pull_request_template.md`** rather than replacing -it; the layer discipline applies inside the template's sections: - -- **`## 🌟 What is the purpose of this PR?`** is the scan layer: one or two sentences of plain - technical prose that stand alone for a reader arriving from the repository feed — the larger - change this work belongs to, why it is happening, and what this branch establishes within it. - Spell out project-local shorthand on first use; a phrase such as "import gates" is not context - until the body says what is being imported and what the gates protect. -- **`## 🔍 What does this change?`** carries the remaining layers in order: first a - plain-language description of the change, then implementation detail, verification, and stack - mechanics inside the GitHub `🏗️ Agent notes` wrapper shown above. -- Fill the template's other sections (related links, blockers, checklists, known issues, tests) - per their own inline comments; answer the checklists honestly and keep the sections the - template says not to delete. - -The prose rules govern throughout: within each section, write sentences, not `What` / `Why` / -`Testing` label-fragments beyond the headings the template itself provides. - -When reshaping an existing pull request, preserve its detailed record byte-for-byte inside the -wrapper. A title or outer summary may change only to improve the scan layer without changing the -recorded claim or status. - -## Comments - -A comment lands in inboxes and feeds. Write it as a notification you chose to send the team. -Its visible content says what was decided or what changed in confidence, risk, or scope, in one -or two short sentences. Implementation detail about that change goes into a collapsed -`🏗️ Agent notes` section in the comment or the issue body. Two boundaries: - -- **Progress narration is never a comment.** "Tried X, now attempting Y" is working state — it - belongs in the issue body's `🏗️ Agent notes`, edited in place. If nothing was decided and no - belief changed, there is no comment to write. -- **State goes in the body; events go in comments.** Current truth (status, plan, - findings-so-far) is edited into the body, where the next reader looks. Comments are the - chronological record of what happened. - -The resolution comment keeps its length exemption: verdict paragraph first, detail in -`🏗️ Agent notes`. Linear **project updates** reach a wider audience than comments — see -`issue-tracker.md`. - -## One kind of entity - -Investigative work — research, a prototype, a spike — becomes a **sub-issue** holding both the -query and the result. Never a comment thread used as a workspace; never a body checklist as -decomposition. The single exception is the immutable **resolution comment** posted when an -issue closes — a closing act, not a workspace. - -## Ownership direction - -State a fact once; everywhere else links. Within an issue, a plan links to a decision, never -restates it. Across issues, a sub-issue never re-explains a fact its parent's context already -states. Long-form artifacts live in the repo's role-based documentation zones and are linked by -path, per `issue-tracker.md`. - -## Voice and authority - -Match the writing's authority to the author's actual remit. Decisions inside the dev remit — -how something will be built, in what order, on what architecture — are stated plainly in first -person ("I'm rebuilding the core greenfield because…"). Claims owned by someone else — product -shape, a PM's checklist, another team's area — get **recommendation voice**: "I strongly -recommend against X, because…", "the practical considerations don't point this way for the -demo, IMO; I'd rather we…" — never "we've decided X" about a thing that is theirs to decide. -Analytic verdict vocabulary ("contradicted", "redefined", "superseded") belongs in internal -planning records (maps, decision docs, resolution comments on our own tickets); at the -boundary — comments on others' issues, messages to colleagues — it becomes a recommendation -with its reasons. - -## Vocabulary — three tiers - -Apply the technical-writing rules first. Then use these three tiers, judged by whether the -reader resolves the word without a lookup: - -1. **Industry-standard terms** (thread, pipeline, module, interface): free everywhere. -2. **Terms from technical literature**: use in `🏗️ Agent notes` only when no plainer exact phrase - fits. A visible summary may use one only after glossing it at first mention and adding it to - `CONTEXT.md`. -3. **Locally coined terms**: do not coin one for an issue. When an issue inherits one from a - linked source, use it only in `🏗️ Agent notes`. - -Check banned constructions and filler with a string search. Judge other nouns by whether the -reader can resolve them without a lookup. - -## Before publishing - -- **Scan test** — does the title start with an active verb and name the task compactly? -- **Commitment test** — does the title avoid committing to an approach that is still undecided? -- **Prose test** — does the context explain causality, or list fragments? -- **Containment test** — are code-level details inside `🏗️ Agent notes`? -- **Standalone-context test** — can a reader arriving from a feed recover the larger change, its - purpose, and this work's place in it without opening the issue? -- **Word test** — has all prose been searched against the technical-writing banned list, and - does every term of art in the visible summary pass the glossary test? -- **List test** — does every list hold parallel or ordered items? -- **Uncertainty test** — are open questions presented as uncertainty, not fact? diff --git a/libs/@hashintel/brunch-agent/docs/agents/legibility.md b/libs/@hashintel/brunch-agent/docs/agents/legibility.md deleted file mode 100644 index ccb8b82caf8..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/legibility.md +++ /dev/null @@ -1,127 +0,0 @@ -# Legibility protocol: render, read the strain, reconcile - -How work arcs with significant agent-generated output close: produce legibility artifacts that -aid review and re-establish shared understanding between the humans and the agents carrying the -work. Companion to `documentation.md` (which governs where documents live; this file governs -how understanding is checked and kept). - -The protocol serves one thesis, the same one the CI gates and the capture store serve in code: -**no claim without a way for it to fail.** A document read in its own register can nod along -with itself; re-rendered into a different register, every claim must survive translation, and -the places where it doesn't are findings. - -## What counts as legible - -Legibility is measured on the human, not the artifact (Lu, 2026-08-26). A proof is legible when -a person can watch it and decide something afterwards. The bar, in order of preference: - -1. **Observable interactions** — a web or terminal UI where the state changes and the data flow - are visible as they happen, in the style of a logic prototype: the person sees the capture - land, the completion report move, the question appear. -2. **Plain-language account** — what happened, what it shows, what it does not show, written for - a teammate who did not run it. -3. **Recordings** — a screen recording of 1 is evidence; a transcript file alone is not. - -Desk evidence, background or headless test runs, and machine-only-readable artefacts (JSON -stores, raw checkpoints, logs) are kept to a minimum and never stand alone as the proof of a -claim; they support a proof of kind 1–3. Naming this bar has not been enough to hold it — arcs -have drifted to desk proofs and hidden runs while calling them legible — so a move, stream, or arc -whose only evidence is of that kind is **not done**, and the steering supplement's proxy-completion -trigger fires. - -## The move: render and read the strain - -At the close of an arc, re-render its central artifact into another register and instruct the -renderer to report **every place the source resisted plain rendering** — a dangling referent, a -term defined nowhere, a prohibition citing nothing, a causal claim whose causality had to be -inferred. The strain report _is_ the review yield; the rendering itself is a byproduct (often a -useful one — a teammate-readable account). - -Run renderings as fork subagents carrying the strain-report instruction, so the main thread -reviews the findings instead of doing the translation. Instrumenting the collection raises the -yield: the ir-design plain rendering returned seven strain points where an uninstrumented -round-2 read of the FE-1374 spec renderings had found four by accident (each of which fed a -real spec change — the practice predates its name). - -## Review before commit in an orchestrated frontier - -When a thread contributes one step of an ordered proof frontier, its producer stops before commit -with a fixed review packet: the base commit, the exact issue contract, the uncommitted diff, -applicable verification commands and results, and a second-register rendering whose grade the -orchestrator chose for the claim, plus the proof bundle and its evidence references. A reviewer -other than the producer checks every packet component, records each correctness or legibility -finding and its disposition in the thread's review record, and judges the claim validated, -rejected, or narrowed with its consequences for successor work. - -The orchestrator owns the review gate and adjudicates disagreements. A confirmed issue-contract -violation blocks commit until it is fixed or the contract changes in its owning authority and the -packet is reviewed again; it cannot be relabelled as uncertainty. Other findings must be fixed, -refused with evidence, or carried into residual uncertainty with the claim and downstream -consequences narrowed accordingly. Remediation that changes the diff or makes the rendering stale -requires an updated packet, rerun verification, and reviewer confirmation before authorization. -Consolidate the review record into the branch's commit and PR description or the indexed proof -artifact, as appropriate. The commit is the deposit of reviewed understanding, not the checkpoint -at which review begins. - -The orchestrator then deposits the reviewed result and confidence changes in their owning -authorities and derives the next dispatch brief from those deposits before dispatching a successor. -An issue moving state or producing a plausible artifact is not evidence that its claim survived -review. - -## The register dial - -The register is a dial, not a single target. One practice, several grades — pick the cheapest -grade that can still fail: - -- **Plain prose** (Google/GOV.UK style): the default. Catches undefined terms, uncited rules, - compressed allusions. -- **STE grade** (controlled vocabulary, one instruction per sentence): for sources whose claims - are dense or load-bearing enough that plain prose can still paper over them. Costs more; - earns it when the source will govern implementation. -- **Worked examples** (FE-1397's form): re-render a _definition_ into concrete instances and - check what breaks. The strongest grade for type systems and contracts — a definition that - survives three worked designs at different thicknesses has been tested, not admired. - -## Filings are render-and-read material too - -A sweep's own capture — its tickets, its accrual comments, its penciled directions — is itself -a rendering of the session's understanding, and gets the same treatment: expect a challenge -pass over the filings before the arc closes. The FE-1405/FE-1406 round came from re-reading the -first round's own text ("shapes-to-fill" quoted back); the gaps were real and had been deepened -by the filings meant to close them. - -## Point findings may reveal a recurrent class - -A point finding is evidence of a possible fault class, not proof that the whole codebase shares -it. Promote the finding to an audit only when recurrence is plausible, the class is cheaply -searchable, and missed instances could fail silently. Search both the mechanical family and the -ownership boundaries where the same contract may be reimplemented. Keep finding and fixing as -separate steps so a human can confirm the class and scope before repair begins. - -When the class is confirmed, make its categorical part executable as a boundary or regression -check. Put any judgment that cannot be mechanized into review guidance. Do not widen a one-off -finding into a repository sweep merely for symmetry. - -## Consolidation: capture-as-we-go, reconcile-before-landing - -Capture channels (accrual comments, pencil lists, strain appendices, handoffs) guard against -evaporation, not fragmentation. Two rules keep the yield coherent: - -- **Every capture channel names its consolidation target** — accruals reconcile into the - owning control surface, pencils graduate to issues or planning documents, and strain reports - become document fixes. A channel with no named target is a leak with a delay. -- **An arc is not closed until consolidation runs.** The closing step reconciles what the - captures established into the durable artifacts (steering/`STEERING`, ledger, docs, issues) — a - handoff note alone is a deferral, not a deposit. - -## Deposit: work describes itself at authoring time - -Prose backfill is remediation, not workflow. A branch's commit message and PR body carry its -semantics when it lands — the record must not abstain exactly where description is most needed -(FE-1390 landed 1,392 lines with an empty body; the deep-read that repaired it cost more than -writing it at authoring time would have). The same rule for tooling: a skill output written -into `docs/` passes through the documentation protocol — an `INDEX.md` row or an `AGENTS.md` -pointer — like any other document. - -Reflections belong in work products, marked as `> **Reflection:**` blockquotes, distinct from -the captured facts — insight left only in chat evaporates with the context that produced it. diff --git a/libs/@hashintel/brunch-agent/docs/agents/partition-worktrees.md b/libs/@hashintel/brunch-agent/docs/agents/partition-worktrees.md deleted file mode 100644 index 7f299c27b3e..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/partition-worktrees.md +++ /dev/null @@ -1,88 +0,0 @@ -# Partition worktrees - -When `docs/control/STEERING.md` records a **partition**, materialize one durable worktree per -**effort** that can run now. Moves (proof) and streams (strategy) do not map one-to-one onto -efforts (checkouts). Terms are in `CONTEXT.md`. This layout is Brunch-local, not Dogsled -vocabulary. Branch and PR rules stay in `git-workflow.md`. - -Do not create worktrees unprompted during `/ds-steer`. Cut them when the user asks, after the -partition table is current. Deferred work is not an effort; neither is someone else's branch -(name it on a join point instead). - -## Names and location - -Give each effort a **1–2 word** directory name (the effort, not the ticket). Record that name on -the partition. Live path and branch come from `git worktree list` and `gt ls` — do not copy them -into `STEERING.md`. The driver keeps the existing clone (`hash`). Path: a sibling of the HASH -clone, `~/Code/hashintel/hash-`. - -## Cut - -From the **driver** worktree, at its current HEAD. Do not switch the driver's branch. - -When the effort has a Linear issue, the holding branch *is* that issue's first branch: - -```text -git worktree add -b {prefix}/{issue-id}-{name} ~/Code/hashintel/hash- HEAD -``` - -When the partition says cut now and no issue exists yet, a holding branch is allowed so the -worktree can exist. It is not a PR. The first issue retargets it (`gt rename` or `gt create` -inside the worktree) when work starts: - -```text -git worktree add -b {prefix}/wN-{name} ~/Code/hashintel/hash- HEAD -``` - -`git worktree add -b` is the right tool here: `gt create` stacks on the current branch and would -make a linear stack. After the add, track each new branch as a Graphite **sibling** of the driver, -not as a child of the previously added effort: - -```text -gt track {branch} -p {driver-branch} --no-interactive -``` - -`gt ls` should fan out from the driver (`◉─┴─┴─┘`), not a chain. Until the pending stack merges, -the driver branch is the base; after it merges, rebase each effort onto `main`. - -## Re-braid - -Cutting siblings from a common HEAD is the start, not a license to stack further on each line. -**Re-braid** when the partition's re-braid table names it: restack onto the declared shared line, -resolve conflicts, then diverge again. Ticket count is not the measure — a fine-grained chain on -one effort can stay on that line; a coarse ticket that already moved a join point may need a -braid before the next. Do not stop work to wait for a braid that is not due. - -Three relationships stay distinct: the proof join (moves demonstrated together), the join point -(shared file, landing order), and the re-braid (git-line meeting). - -## Local services - -Several worktrees must not each spawn the Brunch server and the Petrinaut panel. The candidate -for a one-shot, idempotent bring-up is [Pitchfork](https://pitchfork.jdx.dev/) (`pitchfork.toml`, -`pitchfork start`; start only if not already running). HASH already uses mise, which is how -Pitchfork is installed. It is not adopted yet: G0.1 still needs a documented command; investigate -Pitchfork there rather than adding a compose entry for local daemons. Agents still do not leave a -foreground `yarn dev` running; `pitchfork start` is a one-shot to try, not a substitute for the -user's already-running services. - -## Reuse - -The directory lasts for the effort. Later tickets on the same effort `gt create` inside that -worktree. Braid first when the partition says to, not because another ticket is starting. Joined -moves may land from separate worktrees; none is done until the joint proof runs from one branch -that contains them all. - -Do not install dependencies until work is about to start in that checkout. Two worktrees cannot -hold the same branch. - -`git worktree add` carries no git-ignored file. Before an effort's first live run, copy the -driver's root `.env.local` (the provider credential) into the new checkout and confirm one model -call succeeds; a 401 from a fresh worktree is this, not the provider. On 2026-08-26 two efforts -lost a run to it. - -## Refresh - -If the partition adds an effort, cut it the same way from current driver HEAD. If it drops one, -leave the worktree until the user asks to remove it (`git worktree remove`). Revise the partition -and re-braid tables in the same driver edit; do not refresh copied paths or branch names. diff --git a/libs/@hashintel/brunch-agent/docs/agents/posture.md b/libs/@hashintel/brunch-agent/docs/agents/posture.md deleted file mode 100644 index b2d08e23220..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/posture.md +++ /dev/null @@ -1,4 +0,0 @@ -posture: prototype - -stakes: high # Persisted capture data and merge gates must fail loudly rather than admit silent corruption. -horizon: current-milestone diff --git a/libs/@hashintel/brunch-agent/docs/agents/steering.md b/libs/@hashintel/brunch-agent/docs/agents/steering.md deleted file mode 100644 index 4bb75c33236..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/steering.md +++ /dev/null @@ -1,100 +0,0 @@ -# Brunch steering supplement - -The `ds-steering` judgment and user-invoked `/ds-steer` procedure own orientation, strategic -reconciliation, proof-frontier choice, minimal control updates, and completion. This supplement -adds only Brunch-specific triggers, metadata, tie-breaking, and execution guidance. `AGENTS.md` -routes steering passes here through `/ds-steer`. - -## Triggers - -The arc driver evaluates steering triggers. Invoke `/ds-steer` when: - -- work starts or resumes without a current proof target; -- the objective, deadline, use case, or pressure changes; -- a proof succeeds or fails; -- authorities conflict; -- an external gate changes or becomes stale; -- the selected frontier loses value; -- a frontier's durable outputs are all desk, simulated, or evaluation-side, with no production-path - code changed by the end of one arc (**proxy completion**); or -- arc close detects strategic drift. - -Ordinary ticket movement is not a steering trigger. Proxy completion recurs under new names — a -tracer, a desk rehearsal, and a preregistered instrument each stood in for the thing it was meant -to exercise and became the definition of done. An evaluation instrument larger than the thing it -evaluates is itself the finding. - -## Brunch control fields - -External gates in `docs/control/STEERING.md` carry **owner**, **source**, **watch trigger**, -**last-checked date**, and **consequence**. After the skills' posture-aware frontier ranking and -canonical tie-breakers, use **deadline pressure** as Brunch's final tie-breaker. - -Linear writes require explicit approval before creation or mutation. - -## Parallel partition (Brunch extension of `/ds-steer` step 5) - -`ds-steer` selects one proof frontier and leaves other available work as "separate work". Brunch -adds a partition step after that choice: execution layout, not a second frontier. Moves (proof) -and streams (strategy) do not map one-to-one onto **efforts** (checkouts). The single frontier -stays; the partition says which checkouts run concurrently and how they rejoin. These terms are -Brunch-local and are not Dogsled vocabulary. - -An **effort** is a worktree with a write set disjoint from every other effort's except at named -**join points**. Record only efforts that can run now — not deferred work, not someone else's -branch. For each: write set, join points and who lands first, base, and a 1–2 word worktree name. -Live path and branch come from `git worktree list` and `gt ls`, not from this table. A separate -**re-braid** table names when diverging lines restack (when, who, onto what). Rules: - -- Control documents (`STEERING`, the ledger, the strategy log, `INDEX`, `CONTEXT`) and Linear are - written only from the **driver** worktree. Efforts deposit through issue comments, commit and PR - bodies, and evidence under their own path; the driver reconciles at each landing through - `/ds-steer` (Reconcile). Every other file an effort would share with another effort is a join - point to name, and shared manifests (`package.json`, `yarn.lock`, Turbo and compose config) are - join points by default. -- Joined moves (one proof) may be built in separate worktrees; none is done until the joint proof - runs from one branch that contains them all. -- Cut effort branches from `main` once the pending stack has merged; until then cut from the - driver branch and rebase at merge. Use Graphite for the stacks. Materialize the table with - [`partition-worktrees.md`](partition-worktrees.md) when the user asks for the checkouts. Skip a - declared re-braid only when restacking now would cost more than restacking later; do not invent - a ticket-count gate. -- Record the partition in `STEERING.md` and revise it at every steering pass. An effort that has - no checkout of its own is a task inside one. Deferred work is not an effort. - -## Guidance for procedures that execute the frontier - -This section governs the procedure `/ds-steer` selects; `/ds-steer` does not execute the frontier. - -Exercise real production entrypoints and wiring. A fixture may supply domain inputs, but it must -not supply product wiring absent from the product. Require both a runnable proof and an immutable -legibility snapshot in another register. UX, interpretation, live-runtime, and demo-comprehension -claims require a human witness unless the claim explicitly records why witness is inapplicable. - -The evidence lifecycle is: - -```text -corpus/case -> reviewed fixture -> production-path run -> immutable run snapshot - -> validated claim -> executable oracle -``` - -Maintain the information wall: hidden answer keys and oracles are evaluation-side material, never -inputs to the interviewee or elicitor under evaluation. - -### Proof-bundle fields - -- claim and bounded scenario; -- production entrypoint and wiring exercised; -- reviewed fixture and provenance; -- runnable command or procedure and result; -- immutable run snapshot path; -- legibility snapshot path and register; -- witness record, or explicit inapplicability; -- observed failures and residual uncertainty; -- validated, rejected, or narrowed claim; -- oracle candidate and promotion decision; and -- successor decisions or dispatch briefs changed by the result, or `none`. - -At selection time, initialize the prospective fields. After independent review, finalize the -result-dependent fields and deposit changed truth in the owning authorities before dispatching a -successor. diff --git a/libs/@hashintel/brunch-agent/docs/agents/triage-labels.md b/libs/@hashintel/brunch-agent/docs/agents/triage-labels.md deleted file mode 100644 index e78b86b996a..00000000000 --- a/libs/@hashintel/brunch-agent/docs/agents/triage-labels.md +++ /dev/null @@ -1,17 +0,0 @@ -# Triage Labels - -The skills speak in terms of five canonical triage roles. This file maps those roles onto -Linear (team `FE`) — using workflow **states** where a state is the natural fit, and labels -only where no state expresses the role. - -| Label in mattpocock/skills | In our tracker (Linear FE) | Meaning | -| -------------------------- | --------------------------------------------- | ---------------------------------------- | -| `needs-triage` | state **Triage** | Maintainer needs to evaluate this issue | -| `needs-info` | label `needs-info` (create on first use) | Waiting on reporter for more information | -| `ready-for-agent` | label `ready-for-agent` (create on first use) | Fully specified, ready for an AFK agent | -| `ready-for-human` | label `ready-for-human` (create on first use) | Requires human implementation | -| `wontfix` | state **Canceled** | Will not be actioned | - -When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the corresponding -state or label from this table. Wayfinder ticket-type labels are separate — see the -`wayfinder` label group in `issue-tracker.md`. diff --git a/libs/@hashintel/brunch-agent/docs/control/SPEC-LEDGER.md b/libs/@hashintel/brunch-agent/docs/control/SPEC-LEDGER.md deleted file mode 100644 index 1efbec2b1e7..00000000000 --- a/libs/@hashintel/brunch-agent/docs/control/SPEC-LEDGER.md +++ /dev/null @@ -1,126 +0,0 @@ -# Milestone-one specification ledger - -This living ledger tracks the elicitation-kernel specification's obligations against the built -system. Code and tests are authoritative; a branch that changes an obligation updates its row in -the same change. Unlike current `STEERING.md`, this document has a terminal lifecycle: it settles as -a record when milestone one closes. - -Status vocabulary: **discharged** (built and proved) · **partial** (built with named gaps) · -**pending** (nothing built) · **superseded** (an ADR changed the obligation) · **orphaned** -(owned by no issue) · **contradicted** (implementation and spec disagree). - -`test/open-gaps.ts` separately mechanizes selected behavioral-proof closures. It overlaps this -ledger deliberately but does not replace its partial, contradicted, superseded, and evidence -states. - -## Architecture & shipping shape (§4, §12) - -| Obligation | Spec | Status | Evidence | -| --------------------------------------------------------------------------------------- | ------------ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Shell separation: plugins→core only; core imports no substrate; binding imports both | §4, §12.2 | **discharged** | boundary gates (FE-1388/FE-1399, `test/boundaries.test.ts`); `workspacePackages()` derives groups from manifest; `plugin-gherkin` imports `@brunch/core` only | -| Package topology | §12.2 | **partial** | `core` (+`testing` subpath), `binding-flue`, `transport-aisdk`, `plugin-gherkin`, `apps/brunch-agent` exist; `plugin-assurance` pending. FE-1437 imported them to their native HASH destinations and preserved the existing dependency boundaries. Topology pin derives from §12.2 itself (FE-1400 `ef00201`); FE-1436 adds the transport-only dependency gate. | -| Core _is_ the harness (mechanism lives in core) | §12.2, §14.2 | **discharged** | FE-1422 moved ask mechanism into `core/ask-protocol`; FE-1392 added range selection, trigger/repair decisions, quote-only prompting, and advisory semantics in `core/sweep-protocol`. `binding-flue` supplies substrate reading and orchestration wiring only | -| Tool naming: identity not function | §12.3 | **superseded → discharged** | ADR-0001 replaces `bl_*` with `brunch_*`; `toolName('ask')` → `brunch_ask`; `elicit_*` ban enforced | -| Valibot at every boundary | §12.4 | **discharged** | core + binding schemas throughout; `transport-aisdk` validates the external UI POST before typed request parsing | -| SDK surface (anchoring, retries, tracing, arbitraries, simulation harness) | §12.4 | **pending** | none built; owned by FE-1393 (FE-1383 slice), export-surface ratification gated on the contract freeze (FE-1387) | -| Host-authored thin agent calling `useElicitation(plugin, session)` | §12.1 | **discharged** | `apps/brunch-agent/src/agents/gherkin-elicitor.ts`; FE-1392 adds host-owned immutable session/document and transport wiring | -| Imported app's four roles (remote server, dev loop, target gallery, probe surface) | §12.5 | **partial** | remote server + dev loop exist; gallery and probe surface remain owned by FE-1385. FE-1437 re-chartered `apps/dev` as HASH's `apps/brunch-agent`; no dedicated demo shell is created. | -| CI smoke: no model key, no network, no flake | §12.5 | **discharged** | faux-provider integration test through real runtime + real Hono app (FE-1389); the smoke workflow itself never executed until FE-1400 `699ebe4` un-killed it (org policy vs. tag-pinned actions). Hermeticity probed, not assumed: explicit `start()` config leaves the dev db untouched across the run (Flue audit, 2026-08-17) | -| Remote-parity constraints (pinned agentName, storage outside plugin, no dynamic agents) | §12.5 | **discharged** | pinned-identity gates (FE-1399/FE-1400); storage port in binding (FE-1390) | -| Version axes | §12.6 | **pending** | named, none implemented — as spec states | - -## Capture envelope (§5) - -| Obligation | Spec | Status | Evidence | -| -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------- | -| Envelope fields: minted id + content dedup key (status excluded), spans, epistemic status, confidence, value XOR absence, alternatives, one `supersedes` | §5 | **discharged** | `packages/core/src/capture-store.ts` (FE-1390); invariants 9/10 pinned by named tests | -| No stored status; derived at read time (C3) | §5 | **discharged** | `deriveCaptureStatus`/`deriveIssueStatus`; tests assert no `status` field persisted | -| Retraction: explicit user-cited event, no successor | §5 | **discharged** | `RetractionEvent` (FE-1390) | -| Pointer **derived by the harness**; model cites quotes, never sequence numbers | §5, §8.2 | **discharged** | FE-1391 split caller `EvidenceQuote` from persisted `EvidenceSpan`: every evidence command accepts verbatim quotes only, resolves once against the session archive, and stores an archive-owned ordinal range; extra pointer/source fields are refused. FE-1464 adds a full-prefix retry proof: a later identical entry preserves the first capture's harness-owned occurrence | -| Confidence qualitative, never a scalar | §5 | **partial** | non-empty string only; `"0.93"` accepted. Vocabulary is settled by the plugin-contract spec as `firm | hedged | speculative`; its proposed store refusal rule for numeric-parsing strings remains to implement | -| Six absence states; `not-mentioned` computed, never stored | §5.1 | **discharged** | `ABSENCE_STATES` (FE-1390) | -| Reserved reply encoding for structured taps (C4) | §5.1 | **pending** | UI sends bare text; absences from this UI are honestly `inferred` | -| One epistemic status per capture | §5 | **discharged**, with named friction | Status is the proposal union's discriminant, coupled to provenance shape — per-field status is unrepresentable, and payload-smuggling it breaks dedup identity. This was FE-1405's central input (deep-read FE-1390, tiering section); the arc consumed it _without_ amendment — one status per capture survives, and the structure that wanted per-field status lives below it in proposal interiors (ADR-0003; harness-owned rather than plugin-declared since ADR-0006) | - -## Operations & validation (§6) - -| Obligation | Spec | Status | Evidence | -| ----------------------------------------------------------------------------------------------- | ---- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `project` + typed loss report/code obligations; `validate`; optional `reconcile`; purity (C2) | §6.1 | **pending** | ADR-0005 settles the pure boundary at the deterministic scaffold and obligation plan, with executable realization downstream. FE-1392 adds only the plugin-declared `statement-noted` verbatim proposal floor; projection operations and realization remain unimplemented. | -| Envelope-level refusals (provenance, XOR, single-hop supersession) | §6.2 | **discharged** | FE-1390 command surface | -| Citations resolve to true user entries | §6.2 | **discharged** | FE-1391 resolves quote-only inputs against archived public messages and refuses injected non-user matches. FE-1392's mounted oracle starts with a quote absent from the archive, permits only non-writing peeks, then proves the refresh adjacent to apply resolves and stores it. | -| Duplicate detection free for flat-record plugins | §6.2 | **partial** | near-identical advisory fires for string payloads only; a flat record gets none | -| Issues typed + namespaced to producer (invariant 6) | §6.3 | **partial** | all seven types, origin variants present; producer self-declared, unauthenticated | -| Advisories computed, ephemeral, never stored | §6.3 | **discharged** | returned in results, never in snapshot (FE-1390) | -| Cadence as policy (§6.4) | §6.4 | **partial** | FE-1392 makes successful sweep the cadence boundary and keeps projection/validation read-time-only, leaving sweep outcome unchanged. Concrete operations remain absent until FE-1393. | - -## Questioning UX (§7) - -| Obligation | Spec | Status | Evidence | -| -------------------------------------------------------------------------------------------- | ---- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| No exchange-pair ontology | §7.1 | **discharged** | affordances as entries; retired vocabulary absent | -| Three baseline forms + questionnaire chaining | §7.2 | **partial** | free-text only, by design (FE-1389); remainder owned by FE-1395 | -| Markdown floor: unknown forms still render | §7.2 | **contradicted** | dev UI `safeParse`s the whole concrete form and renders nothing on failure (`apps/brunch-agent/src/ui/chat.tsx`); needs envelope-only schema. Filed FE-1420 | -| One live affordance; durable identity on tool output part; channel as live-render sugar (C6) | §7.3 | **discharged** | updater-form guard + `output` part + channel write (FE-1389); _retry hole_: a re-executed ask (at-least-once tools) is refused as a duplicate — FE-1420 | -| No instruction interpolation; mechanical reply binding via signal; no echo token (C7) | §7.4 | **discharged** | render-invariant instructions; `affordance-reply-bound` signal (FE-1389); FE-1392's high-water and repair-signal paths run through the mounted lifecycle without instruction-update wakes | -| Transport outcomes `answered / redirected / unanswered` | §7.5 | **pending** | slot clears unconditionally; no outcome recorded. FE-1420 (abandoned asks) | -| Interpretation render | §7.6 | **pending** | open in `test/open-gaps.ts` (FE-1394) | -| Outbound rich / inbound string; UI filters on `purpose`/`display` | §7.7 | **discharged** | FE-1389 | - -## Capture mechanics (§8) - -| Obligation | Spec | Status | Evidence | -| -------------------------------------------------------------- | ---------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Settlement trigger + judgment | §8.1 | **discharged** | FE-1392 computes the unswept true-user tail, guards pending asks and repeated frontiers, permits decline, and injects same-response settlement judgment through awaited `useAgentFinish`. Exercised live in baseline condition 5 (2026-08-25): 11 settlement-triggered sweeps over 12 turns. Open cost finding: the settlement sweep runs on the critical path before the ask is delivered ([latency assessment](../evidence/evaluations/process-model-elicitation/baseline/condition-5-turn-latency.md) R1) | -| Harness-resolved anchoring at sweep application | §8.2 | **discharged** | FE-1391 resolves exact quotes against archived user entries at command application; no match returns a repair hint, multiple matches choose latest with an advisory, and injected non-user matches refuse. Live in condition 5: 3 of 11 batches refused `evidence-quote-not-found` and repaired in-turn, 8 applied. Refusal is per batch, not per proposal — a cost, not a correctness, gap ([latency assessment](../evidence/evaluations/process-model-elicitation/baseline/condition-5-turn-latency.md) R3) | -| Sweep idempotence, evidence-occurrence and content-keyed | §8.3 | **discharged** | FE-1392's durable executor may replay the settled prefix; the mounted oracle proves a repeated proposal skips while an earlier omission applies. FE-1464 proves a later identical entry cannot re-anchor a retry while distinct identical occurrences remain capturable. On refusal the successful high-water stays fixed while the loop guard reopens; the oracle stops once on the repair continuation and proves the range is offered again before succeeding | -| Single-hop supersession over active heads; stale-session guard | §8.4, §9.2 | **discharged** | refusal carries `currentHeadIds` (FE-1390) | -| Resolution records close conflicts; user-cited | §8.5 | **discharged** | FE-1419 (`ln/fe-1419-contract-closure`): conflicts open only over two-plus distinct active captures, referenced captures are pinned until a user-cited resolution frees them, resolutions compare by set equality, and every accepted command round-trips through the persisted parser. The one-reference and supersession-stranding holes are closed and red-proved. The tap-evidence adjudication (contradicted row below) remains open | -| Resolution evidence may be a structured tap | §5.1/C4 vs. §8.5 | **contradicted** (silent adjudication) | `resolve-conflict` rejects `user-affordance-payload` evidence — a user who resolves a conflict by tapping a choice strip cannot close it. Defensible strict reading of §8.5; made without a record. FE-1395's body owns the other half of the same fact (tap-ness must be a transport fact); neither ticket references the other — seam item | -| Unaccounted-ask advisory | §8.6 | **discharged for affordance-bound accounting** | FE-1392 derives ask → bound user entry → capture evidence at read time and returns unmatched asks only as sweep advisories. Free-text accounting and abandoned slots remain FE-1420; no envelope field was added | -| Resume-time sweep reconciliation | §8.7 | **pending** | — | - -## Sessions & durability (§9) - -| Obligation | Spec | Status | Evidence | -| -------------------------------------------------------------------------------- | ---- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Durable target-document, transient sessions, sweep the only bridge | §9.1 | **discharged for the local panel** | FE-1504 mints one stable ui-shell principal in localStorage, sends it on every request, resolves it to one target-document id and principal-scoped session ids, and retains each session log in that document's archive. Reload reuses the principal and target document; a second conversation receives a distinct session over the same document. `brunch-principal.test.ts` and `elicitation-session.test.ts` pin the mapping; the live witness remains on FE-1503. | -| Per-session state = evidence log, swept high-water mark, pending-affordance slot | §9.2 | **discharged** | pending slot (FE-1389), durable session-log archive (FE-1391), and FE-1392's parse-validated high-water/last-judged bookkeeping under one `sweepHighWater` state slot | -| Re-entry briefing; user-visible insertion notice | §9.3 | **pending** | signal carrier proved; no briefing; the one injected signal is filtered out of the UI. Owned by FE-1396 | -| Only the true user's side is evidence; injected entries structurally non-user | §9.4 | **partial** | FE-1391 verifies role/purpose against the public projection, refuses signal/advisory text, and classifies affordance replies only from the harness-owned reply-binding signal. The kickoff remains a machine-authored `user` entry until FE-1420/FE-1385 move it to `useInitialData`; FE-1396 still owns briefing-never-evidence | -| Completion derived, never a gate | §9.5 | **partial** | Built on FE-1497 (#9325): `evaluateCompletion` over the fold of the store onto the plugin's `must_know` rows, the sweep list, and the completion cue, all read-time, none gating a turn. Exercised live in baseline condition 5 (2026-08-25): the report was computed after each of 12 turns and never reached `complete` (46 unsatisfied, 0 unmapped) — the gap is identity in the fold (7 objective nodes for 2 questions, 167 possibly-equivalent advisories), not the derivation. Contract in [`elicitation-completion.md`](../specs/elicitation-completion.md); the FE-1361 prefix replay in [`elicitation-completion-rehearsal.md`](../evidence/proofs/design/elicitation-completion-rehearsal.md) stays a golden-fixture candidate. No progress and stopping remain distinct from completion; durable delivery and deferral licensing (rules 17–19) are deferred behind FE-1480 (see the STEERING gate). | -| Storage port: harness-defined, binding-implemented, plugin-blind (C1) | §9.6 | **discharged for the local target** | core owns capture/archive/anchoring semantics; `binding-flue` owns the JSON-file implementation and treats FE-1504's owner key as opaque; a mismatched owner is refused before read or write. Plugins cannot import the binding (FE-1390 + FE-1391 + FE-1504). | -| Port scope includes the session-log archive | §9.6 | **discharged** | FE-1391 provisions a versioned target-document record containing capture state and session logs, migrates the legacy capture-only shape on mutation, parses both halves on read, identity-versions evolving messages, and retrieves every cited ordinal independently of Flue | -| Compaction vs. durable log | §9.7 | **partial — source-settled, behavioral pin open** | Flue 2.0.3's append-only stream contract and implementation show compaction appends a canonical record, rewrites only model context, preserves the public message projection, and leaves `state_write` reduction untouched. The source-read record reshapes FE-1386 to one upgrade pin; `test/open-gaps.ts` remains until behavioral proof lands | - -## Binding capabilities (§10) - -| Obligation | Spec | Status | Evidence | -| ------------------------------------------------------------------------------------------------- | ---- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Caps 1–5: tool, instructions, persistent state, affordance emission, suspend-for-reply (absorbed) | §10 | **discharged** | all five exercised against the real runtime (FE-1389 integration test) | -| Caps 6–8, incl. entry-projection read | §10 | **discharged** | FE-1391 supplies the public reader/archive. FE-1392 uses direct structured `harness.prompt` inside a durable tool whose peek/extract/refresh/apply boundaries use `step.do`; the mounted runtime pins same-response finish-hook steering and refresh-before-apply | - -## Plugins, packs, dev targets (§11, §13) - -| Obligation | Spec | Status | Evidence | -| -------------------------------------------------------------------------------- | ---------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Plugin ownership: packs, forms, validators | §11.1 | **superseded → partial** | ADR-0006 (2026-08-25) makes a plugin one sectioned Markdown file per target formalism; ADR-0007 (same day) re-forms it as cells under harness-owned keys with the tables as schema-validated data (FE-1431) plus `project`/`validate` code ([`plugin-contract.md`](../specs/plugin-contract.md)); cards became kind-indexed `Patterns`, the completion contract became the `Must know` table. `plugin-gherkin` owns its one FE-1392 proposal declaration/schema and target identity; [`plugin-sdcpn/plugin.yaml`](../../packages/plugin-sdcpn/plugin.yaml) (`sdcpn/2026-08-25.2`) is parsed by `readPluginDefinition` against the core JSON schema, its rows drive the fold and `evaluateCompletion`, and its `slot-assertion` check is the sole machinery; the elicitor ran it live in baseline condition 5. Gherkin's zero-new-keys check remains FE-1393 work | -| Pack form, Principle v2 | §11.2 | **superseded → designed** | ADR-0007 fixes pack form as the key contract (four groups; `plugin.yaml` + JSON schema in core; converging per decision 9); ADR-0006 had fixed it as the heading contract (`Purpose · Kinds · Must know · Patterns · Moves · Deliverable`) with three machine-read tables; Principle v2 still governs the prose sections. No parser or loader exists | -| Smallest honest plugin as a standing bar | §11.3 | **partial** | `statement-noted.test.ts` and the core plugin fixture encode the one-type verbatim floor and reject undeclared parsed/pointer shape; the standing bar must grow with FE-1393's operations | -| Generic strategy quiver | §11.5 | **designed** (ADR-0007) | designed 2026-08-25 as the **repertoire** (`packages/repertoire`, ADR-0007 decisions 3, 6–8); built under FE-1406 in the co-authoring cycle of S-009; the key catalogue converges before it freezes (decision 9) | -| Portfolio + hybrid order: both packs authored before the pack interface freezes | §13 | **superseded → partial** | ADR-0006 makes the interface the heading contract and three table grammars; the SDCPN plugin file is authored (`plugin-sdcpn/plugin.yaml`), the Gherkin file is not. Owned by FE-1387 (FE-1383 slice, backlog); current sequencing puts the SDCPN proof before generic freeze (see `STEERING.md`). Gherkin wiring ahead stays legal while FE-1387 holds the freeze | -| Gherkin validation (parse validity, step lexicon) | §13.1 | **pending** | — | -| Assurance target (Statement record, four edges, five-stratum derivation, ledger) | §13.2–13.3 | **pending** | — | - -## Acceptance material (§14) - -| Obligation | Spec | Status | Evidence | -| --------------------------------------------------------------- | ----- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Invariants 2, 4, 5, 7, 9, 10 | §14.1 | **discharged** | named tests in `capture-store.test.ts` (FE-1390), one hand-written example each | -| Invariant 1 (no value without provenance) | §14.1 | **partial** | structural (span/basis shapes required); pointer truth unverified | -| Invariant 6 (issues namespaced) | §14.1 | **partial** | namespace stored, producer unauthenticated | -| Invariants 3, 8 (projection loss, equivalent projection) | §14.1 | **pending** | no `project` exists | -| Five proof obligations; smallest-honest + second-binding tests | §14.2 | **partial** | smallest-honest holding; FE-1422 repaired the ask protocol's second-binding failure by moving portable mechanism to core. No literal second binding exists yet | -| Gating tests (reprojection, minimal pairs, black-box authoring) | §14.3 | **pending** | — | -| Generation-first fixtures, `arbitraryFromSchema`, `fc.commands` | §14.4 | **pending** | both new suites are hand-written examples; no fast-check anywhere. Owned by FE-1384 (FE-1383 slice, backlog) | -| Open verification items tracked with homes | §14.5 | **discharged** (as a mechanism) | `test/open-gaps.ts` deletes claims only with behavioral proof. FE-1392's mounted lifecycle closes `history-refresh-before-sweep` causally and exercises its high-water/repair writes without an instruction wake, closing `wake-wart-write-paths` | diff --git a/libs/@hashintel/brunch-agent/docs/control/STEERING.md b/libs/@hashintel/brunch-agent/docs/control/STEERING.md deleted file mode 100644 index f1c0be710e8..00000000000 --- a/libs/@hashintel/brunch-agent/docs/control/STEERING.md +++ /dev/null @@ -1,451 +0,0 @@ -# Brunch steering - -This is Brunch's one mutable current strategic control. Linear owns issue facts; -[specifications](../specs/), [ADRs](../adr/), and [the ledger](SPEC-LEDGER.md) own their truths. - -## Objective and acceptance proof - -Two jobs are in scope — **construct** and **review-and-revise** — and cold-start construction must -be possible ([S-011](STRATEGY-LOG.md#s-011), amending S-001's framing). The proof order is fixed: -construct through the production path first, review-and-revise on top of it. Whether each job -needs its own comprehensive runbook is an assumption under test, not an accepted fact; early -passes over the plugin schema suggest the jobs share most of one. - -**Proof 0 — the black triangle.** From a checkout, documented commands bring up the Brunch server -and the Petrinaut assistant panel on local dev services; the panel's assistant is the production -SDCPN elicitor; a human conducts a real construct elicitation; captures persist to a target -document owned by a principal and survive reload; completion accounting is human-readable; every -turn records time per purpose. This is the precondition of the acceptance run, the September -demo's step 1 made real rather than fixtured, and the surface the voice-mode work attaches to. -Projection: [FE-1503](https://linear.app/hash/issue/FE-1503). - -**Proof 2 — the acceptance run.** A bounded CPS review-and-revise loop through the production -Brunch and Petrinaut path: a reviewer opens an existing source-grounded model and net, traces one -element to the source utterance, corrects it in three to five turns, and sees a -provenance-preserving net delta handed to the optimisation flow. Acceptance is one -screen-recordable deployed run, surviving reload, through the real HTTP handler, -session binding, sweep, fold, deterministic projection scaffold, model-assisted client-tool -realization, compilation, and optimisation handoff. The changed element traces to a sweep-produced -superseding capture while an unrelated region stays stable. Preserve runnable and legibility -evidence under [proof evidence](../evidence/proofs/). - -## Governing concerns - -- [ADR-0003](../adr/0003-three-register-ir.md) — the elicited model is a pure fold between - assertions and projections; operative force: read paths make no new semantic judgments and every - model part traces to captures. -- [ADR-0005](../adr/0005-model-assisted-sdcpn-realization.md) — deterministic projection ends at a - scaffold and typed obligations; operative force: executable TypeScript is authored downstream - through Petrinaut and passes compile and simulation gates. -- [ADR-0006](../adr/0006-plugins-per-target-formalism.md) — each plugin serves one target formalism - and no domain; operative force: the production SDCPN slice, not a generic or domain-keyed - contract, sets the exercised interface. -- [ADR-0007](../adr/0007-harness-teaching-meets-plugin-content-at-fixed-keys.md) — harness-owned - fixed keys join defaults to plugin cells; operative force: cycle two froze the catalogue, which - reopens only when run evidence forces a key change, while FE-1393 tests gherkin generality. -- [ADR-0008](../adr/0008-repertoire-and-plugin-contract-live-in-core.md) — repertoire defaults are - core-owned prompt data behind a guarded subpath; operative force: plugins never import - `@hashintel/brunch-agent/prompts`, the root remains the plugin SDK, and no broader core - reorganisation follows from this package correction. -- [S-001](STRATEGY-LOG.md#s-001) — review-and-revise is the current proof, not permanent scope; - operative force: cold-start work does not gate the bounded correction run unless the use case - changes. -- [S-004](STRATEGY-LOG.md#s-004) — code-bearing projections split into deterministic scaffolds and - model-assisted realization; operative force: executable claims require Petrinaut client tools, - compilation, and simulation. -- [S-007](STRATEGY-LOG.md#s-007) — the production vertical slice, not another design instrument, - answers the remaining design questions; operative force: every arc must change or directly - exercise production-path code. -- [S-008](STRATEGY-LOG.md#s-008) — harness teaching is package and schema topology rather than - free-floating prose; operative force: rescoping requires run evidence and keeps the declared - boundaries executable. -- [S-009](STRATEGY-LOG.md#s-009) — the key catalogue converges by co-authoring both plugins; - operative force: schema, repertoire, SDCPN, and gherkin advance together until a cycle changes no - key. -- [S-010](STRATEGY-LOG.md#s-010) — the shipped harness's facts replace the shadow classifier; - operative force: conditions 4 and 5 are the live arms and no text proxy decides what the harness - can report directly. -- **One production read model** — fold, completion, cue, and later correction share one derived - path; operative force: no correction-side parallel model. Source: [ADR-0003](../adr/0003-three-register-ir.md). - Steering projection: FE-1497 (controller read path). -- **Formalism-first contract pressure** — the first SDCPN implementation, not another generic - design, establishes the exercised seam; operative force: domain knowledge stays in the plugin. - Source: [ADR-0006](../adr/0006-plugins-per-target-formalism.md). Steering projection: - FE-1482 (SDCPN plugin skeleton). -- **Live-loop viability** — the production harness conducts an elicitation but does not yet - converge one within viable latency; operative force: measure per-purpose time and address - identity before strengthening the completion claim. Source: [condition-5 evidence](../evidence/evaluations/process-model-elicitation/baseline/transcripts/). - Steering projection: FE-1404 (condition-5 skeleton run). -- **Completion remains invariant-driven** — the production fold, not a domain-keyed instrument, - supplies the completion state; operative force: preserve the accepted invariant set as executable - tests. Source: [elicitation completion](../specs/elicitation-completion.md). Steering projection: - FE-1402 (completion contract). -- **Failure detection stays an oracle, not authority** — the catalogue tests production evidence; - operative force: apply it after the latency spike without letting evaluation material select the - strategy. Source: [failure catalogue](../reference/research/elicitation/frontier-model-elicitor-failure-catalogue.md). - Steering projection: FE-1407 (failure catalogue). -- **Reply transactions survive retries and abandonment** — duplicate or stale replies must not - bind or apply; operative force: this safety floor precedes external client tools. Source: - [elicitation-kernel spec](../specs/elicitation-kernel.md). Steering projection: - FE-1420 (retry and abandonment safety). -- **Machine results remain correlated and non-user** — client-tool results retain field identity - without becoming evidence; operative force: executable realization stays gated on the round - trip. Source: [Petrinaut integration spec](../specs/petrinaut-integration.md). Steering projection: - FE-1438 (client-tool return). -- **Review sessions survive reload without crossing principals** — durability and privacy are one - boundary; operative force: the reviewer proof cannot claim continuity until both hold. Source: - [Petrinaut integration spec](../specs/petrinaut-integration.md). Steering projection: - FE-1439 (durable private sessions). -- **Artifact elements remain source-traceable** — generated structure points back to supporting - captures; operative force: provenance reads precede targeted correction. Source: - [ADR-0003](../adr/0003-three-register-ir.md). Steering projection: - FE-1478 (provenance read). -- **Realization stays field-local** — typed obligations become executable without unrelated - resynthesis; operative force: Petrinaut diagnostics and deterministic gates bound every repair. - Source: [ADR-0005](../adr/0005-model-assisted-sdcpn-realization.md). Steering projection: - FE-1480 (field-local realization). -- **Correction preserves unaffected structure** — targeted re-elicitation joins semantic and - reviewer work; operative force: supersede the changed capture while an unrelated region remains - stable. Source: [objective](#objective-and-acceptance-proof). Steering projection: - FE-1479 (targeted correction). -- **Plugin authoring is executable topology** — schema and key reader replace prose conventions; - operative force: the surface stays smaller than the parser it retires. Source: - [ADR-0007](../adr/0007-harness-teaching-meets-plugin-content-at-fixed-keys.md). Steering projection: - FE-1431 (plugin authoring surface). -- **Harness teaching has one owner** — repertoire defaults fill every guidance and runbook key; - operative force: plugins specialize those keys without importing harness method. Source: - [ADR-0008](../adr/0008-repertoire-and-plugin-contract-live-in-core.md) and - [S-008](STRATEGY-LOG.md#s-008). Steering projection: - FE-1406 (harness repertoire). -- **A second formalism tests generality after the tracer** — gherkin pressures the settled SDCPN - surface; operative force: it follows the production slice and adds no harness-owned key. Source: - [S-009](STRATEGY-LOG.md#s-009). Steering projection: - FE-1393 (gherkin generality check). -- **The delivery surface must become visible early** — the watched use case and voice consumer - require a stable Petrinaut boundary; operative force: end-to-end visibility precedes layer-local - optimization, while use-case confirmation may reframe Proof 1. Source: [September Plan](https://www.notion.so/hashintel/Brunch-September-Plan-3b33c81fe02480a5af6bf3089c3ee640). - Steering projection: FE-1476 (September delivery). -- **The generality case needs recoverable provenance** — the truck-fleet source artifact is absent - from the repository; operative force: until it returns, the case carries no dossier-backed - provenance claim. Source: [S-007](STRATEGY-LOG.md#s-007). Steering projection: FE-1382 - (truck-fleet dossier). -- **Legibility is measured on the human** — a proof is an observable interaction with visible - state change and data flow, a plain-language account, or a recording of one; operative force: - desk evidence, hidden runs, and machine-only artefacts never stand alone, and a move or stream - with only such evidence is not done. Source: [legibility protocol](../agents/legibility.md#what-counts-as-legible). - Steering projection: FE-1503 (the joint proof). -- **The plugin API is a design in flux** — two questions stay open: is the key schema a viable, - understandable way to specify a domain plugin, and does it come together as effective prompt- - and context-engineering material. Cycle two (2026-08-26) froze the catalogue under ADR-0007 - decision 9 — no key added, merged, or dropped; the third-formalism sketch fills cells only — but - three key *shapes* changed in that same cycle (`patterns[].slot`, `precision` any-of, repertoire - `for_precision`) and gherkin has been rendered and validated, never interviewed; operative force: - the freeze is the authoring interface's stability, not the generality proof — FE-1393's gherkin - interview is the remaining test, and any key change it forces reopens the catalogue via the - schema `CHANGELOG`. Source: - [ADR-0007](../adr/0007-harness-teaching-meets-plugin-content-at-fixed-keys.md) decision 9, - [S-011](STRATEGY-LOG.md#s-011), [cycle-two readout](../evidence/evaluations/process-model-elicitation/baseline/readout.md). - Steering projection: FE-1393. -- **Tools are pinned as current truth against intent** — see [the inventory](#tool-inventory--current-truth-and-intent); - operative force: no tool is added, renamed, or promised in prose outside that table. Source: - [S-011](STRATEGY-LOG.md#s-011), [Petrinaut integration spec](../specs/petrinaut-integration.md). - Steering projection: FE-1477 (routing), FE-1438 (client tools), FE-1480 (realization). -- **The voice edge attaches at `/api/chat`** — H-6763's prototype bridges finalized speech turns - into the existing AI SDK transport and consumes `brunch_ask`, keeping Brunch authoritative for - history, questions, captures, and provenance; operative force: the `/api/chat` UI-message stream, - the `brunch_ask` schema, and the principal identity are the stable surface and change only with - notice; provider code stays in `apps/petrinaut-website`. Source: - [ADR-0004](../adr/0004-in-petrinaut-staging-and-the-monorepo-import.md) decision 3, the H-6763 - prototype plan (branch `kostandin/h-6763-…`). Steering projection: H-6763 (Kostandin). - -## Selected frontier: G0 — the black triangle - -**Claim:** the shortest route to both proofs is the full end-to-end flow through every production -layer, made to work poorly before any layer is made to work well. Reaching it exposes the real -gaps, fixes the surface the team and the voice-mode work build against, and turns the harness's -facts into something a human can watch. - -**Contribution:** Proof 0; the September demo's step 1 as a real elicitation; the first -human-witnessed measurement of per-turn latency; the persistence model (principal → document → -sessions) exercised from a real surface for the first time. - -**Evidence consumed:** the condition-5 run and its [latency assessment](../evidence/evaluations/process-model-elicitation/baseline/condition-5-turn-latency.md); -[ledger §9.1](SPEC-LEDGER.md#sessions--durability-9); the wiring gap assessment below; the H-6763 -prototype's attach point. - -**Cut:** no deployment, no client-side net tools, no realization, no Postgres, no gherkin, no -voice code in Brunch packages beyond the transport bridge, no claim about elicitation quality or -convergence. SQLite and per-document JSON remain the local implementation. - -**Projection:** [FE-1503](https://linear.app/hash/issue/FE-1503), child of FE-1476; decomposed by -`/ds-write-tickets`. - -**Moves joined at Proof 0** — buildable in parallel worktrees, done only when the one human run -proves them together ([CONTEXT](../../CONTEXT.md#strategic-control) "Move"; [S-011](STRATEGY-LOG.md#s-011) decision 3): - -| Move | Lands as | Owning issue | -| --- | --- | --- | -| **G0.1 Wiring** | Implemented on W1: `/api/chat` routes to the SDCPN elicitor and `yarn dev:brunch` starts Brunch with the real panel. The Proof 0 re-braid and human run remain. | FE-1504 (Done) | -| **G0.2 Persistence modelled** | Implemented on W1: the ui-shell principal resolves to one target document and principal-scoped sessions; the store refuses another owner. The live reload witness remains in Proof 0. | FE-1504 (Done), FE-1439 | -| **G0.3 Latency floor** | R0: `durationMs` per purpose and OpenTelemetry spans on every turn; a human-witnessed number replaces the inferred split | FE-1505, FE-1404 | -| **G0.4 Legible surface** | captures, sweep results, and completion readable during a live panel session; the attach contract stated in the Petrinaut integration spec with a changes-with-notice rule. Depends on G0.1–G0.2 landing; built on W1, stacked on FE-1504's branch (reassigned from the driver this pass: it consumes W1's code and write set, and the driver branch is the tip of the plugin PR) | FE-1506 | - -**Current move: the Proof 0 human run.** All four G0 moves are implemented — FE-1504 and FE-1506 -on W1 (FE-1506 Done, repository verification passed outside the sandbox), FE-1505's R0 timing on W2 -— and none is done as a move until one human elicitation from one branch proves them together. The -run outranks everything mechanically available because it is the objective's precondition and the -first evidence with a person as witness; W2's condition-5 figure and P1's gherkin proof run beside -it. Tracker residue: FE-1504 was Done and is now In progress with a closing comment in place — it -should return to Done (Linear mutation, approval pending). - -**Streams beside G0** — parallel, separately proven, blocking nothing: - -| Stream | Strategic warrant, claim, and proof | Projection / owner | Material coordination | Stop or replan | -| --- | --- | --- | --- | --- | -| **P1 Plugin design loop** | ADR-0007 and S-009 require the key catalogue to be earned through both plugins and live runs. Cycle two ran both arms (condition 4: 24 turns to the hard stop; condition 5: 12 turns, 166 captures, 51 nodes, 0 unmapped, 93 unsatisfied) and froze the catalogue; FE-1431 is Done. Remaining proof: FE-1393 — a short gherkin interview yields a parse-valid `.feature` file and a per-key readout with zero new keys. | FE-1393 (FE-1406 reconciled by ADR-0008's completed move) / Lu | FE-1393 starts from a branch containing W4's guarded prompts move and deposits any repertoire finding in the schema `CHANGELOG`. No G0 coordination. | A run needs a new heading, domain content, or another prose-only rescope: reconcile ADR-0006/0007 before continuing. | -| **Voice edge** | H-6763 is an external September commitment: a provider-owned voice session must feed finalized turns into Brunch and resume a real `brunch_ask` without making provider history authoritative. | H-6763 / Kostandin | The `/api/chat` stream, `brunch_ask`, and principal are the join surface; FE-1506 records their changes-with-notice contract. | Provider needs leak into Brunch packages or require a Petrinaut-library-specific elicitor path: stop at ADR-0004. | - -**Stop or replan for G0:** a first question takes longer than the provisional 10 s after R0 and -R1 — the isolating spike becomes blocking; the panel needs Brunch-specific code inside -`@hashintel/petrinaut` — ADR-0004 boundary, stop; persistence modelling needs a schema the harness -must know — §9.6 port breach, stop; a move or stream lands with desk-only evidence — not done. - -### Parallel partition (2026-08-26) - -Execution layout, per the [steering supplement](../agents/steering.md#parallel-partition-brunch-extension-of-ds-steer-step-5) -and [`partition-worktrees.md`](../agents/partition-worktrees.md). The driver owns control -documents and Linear and carries no move. Kostandin's H-6763 is not an effort here; W1's join -points name it. The latency spike is deferred and is not an effort; G0's stop condition still -names it. An effort blocked on a gate stays an effort; only the driver drops a row, at a pass. - -| Effort | Carries | Projection | Write set | Join points (who lands first) | Base | Worktree | -| --- | --- | --- | --- | --- | --- | --- | -| **W1** | G0.1, G0.2, G0.4 (all implemented; FE-1506 Done; awaiting the Proof 0 run) | FE-1503's run, from the re-braided line | as before plus the panel or dev-diagnostics read of captures, sweep results, and completion; `docs/specs/petrinaut-integration.md` (attach contract) | with **Voice**: `petrinaut-chat.ts`, `local-dev-origins.ts`, `local-storage-demo-app.tsx`, the website `vite.config.ts`, three `package.json` — voice lands first or W1 rebases onto it; with W2: `apps/brunch-agent/package.json` (W2 already touched it) | driver branch until the stack merges | panel | -| **W2** | G0.3 (implemented; the live condition-5 purpose split is running) | FE-1505 | `binding-flue` turn observation, `harness-run.ts` `observe()`, OpenTelemetry setup in `apps/brunch-agent`; `condition-5.timings.jsonl` under evidence | with W1: `apps/brunch-agent/package.json`, `yarn.lock` | as W1 | timing | -| **W3** | P1 (cycle two landed, FE-1431 Done; next: the gherkin generality proof) | FE-1393 | `plugin-gherkin/plugin.yaml` and its tests; a gherkin interview case and readout under evidence; the schema `CHANGELOG` | W4 is complete: restack onto a line containing `ln/w4-topology` before FE-1393 edits prompt data; with W1: none | W4 after the driver reconciles it | plugins | - -Live path and branch: `git worktree list`, `gt ls`. Driver checkout is this clone. - -Re-braid (restack and resolve, then diverge again). Length follows how fine the tickets are. - -| When | Who | Onto | -| --- | --- | --- | -| Done 2026-08-26 (Lu) — the braid before Proof 0 | timing, then plugins and topology | The five effort branches now form one line above the driver: 1504 → 1506 → 1505 → 1431-plugins → w4-topology. The `timing` checkout holds all four G0 moves and is where FE-1503's run happens; FE-1393 starts above `ln/w4-topology`, so it edits prompt data at its guarded core location | -| A join point is about to be written from a second effort | the efforts that share it | the line that already landed, else driver then `main` | -| Voice lands | panel | Voice (join: voice first) | -| The pending plugin stack merges | every cut effort | `main` | - -### Gap assessment (2026-08-26) - -| Triangle edge | Today | Gap | -| --- | --- | --- | -| **Panel → Brunch** | W1 routes the real panel's `/api/chat` to the SDCPN elicitor; `yarn dev:brunch` starts both services; `brunch_ask` round-trips. | Conduct the human Proof 0 run from the re-braided `hash-timing` checkout. | -| **Persistence modelled** | W1 sends one stable ui-shell principal on every request, resolves it to one target document and namespaced sessions, and stamps an opaque owner key that refuses cross-principal reads and writes. SQLite and per-document JSON remain. | Witness reload against the re-braided live surface; no persistence design gap remains for G0. | -| **Real elicitation** | The production SDCPN elicitor is reachable from the panel on W1; captures, sweep outcomes, and completion are rendered readably, and the attach contract is recorded. | Conduct the eight-turn human run from `hash-timing`, with a screen recording and a plain-language account under proof evidence. | -| **Deployment (G2)** | — | Was Linear-gated behind gherkin via FE-1423 ← FE-1396; that blocker was removed 2026-08-26. FE-1440/FE-1441 remain the owners. | - -### Tool inventory — current truth and intent - -| Side | Current truth | Intent (Lu, 2026-08-26) | Owner of the change | -| --- | --- | --- | --- | -| Server (`apps/brunch-agent`, harness-owned via `toolName`) | `brunch_ask` (suspend-for-reply affordance, rendered by the panel's interactive tool), `brunch_sweep` (private extraction into the store; plugin `checks` such as `slot-assertion` run inside it). Prefix from `PRODUCT_NAME = "brunch"`; one edit renames. | `ba_sweep`, `ba_check` (checks as a callable tool), `ba_ask` (possibly not needed yet — questions are plain text so far) | core `naming.ts`; FE-1477 for what the panel sees | -| Client (Petrinaut, `petrinaut-core`) | ~40 fine-grained `petrinautAiTools` (`addPlace` … `updateSubnet`, `applyAutoLayout`) executed in the panel's `onToolCall`; not reachable from the Brunch elicitor. | `pn_read`, `pn_mutate` (coarse tools over the action schemas), with a `pn_infer_slots` post-update that fills TypeScript from injected comments | FE-1438 (round trip), FE-1480 (realization, ADR-0005 obligations) | - -### After G0 — the sequence - -- **G1 — the usable triangle.** R1 (sweep off the critical path) first; identity and dedup in the - fold so completion can move; resume. The earlier plan's A and B, worked inside the triangle. -- **G2 — the demo triangle.** Client-tool round trip (FE-1438 → FE-1480 → FE-1479), deployment - behind demo.petrinaut.org (FE-1440, FE-1441), then Proof 2. - -### Epicentres and lanes (context the moves and streams inherit) - -The vertical slice of [S-007](STRATEGY-LOG.md#s-007) remains the map of the code: five epicentres, -ordered by the size of the gap they close, worked from the centre outward. The triangle -subordinates them — each is reached as the end-to-end flow needs it. - -| Epicentre | Gap | Issue | -| --- | --- | --- | -| **E1 — controller read path** | *Landed on the unmerged stack (FE-1497, #9325):* fold, `evaluateCompletion`, sweep list, and cue exist and ran live in condition 5. Remaining gap: node identity in the fold (7 objective nodes for 2 questions) — worked in G1. | FE-1497 (gist: harness controller read path) | -| **E2 — the SDCPN plugin in code** | *Landed on the unmerged stack:* `plugin-sdcpn/plugin.yaml` (`sdcpn/2026-08-25.2`) is parsed by `readPluginDefinition` against the core schema and drives the fold and completion. Remaining gap: the `project` and `validate` code and the key catalogue's convergence (P1). | FE-1482 (gist: CPS plugin, redefined as the skeleton epicentre) | -| **E3 — targeted correction** | `supersedes` is unreachable from extraction; no affected-slice computation; no delta; the target-document is still identified with the conversation. | FE-1479 (targeted re-elicitation), FE-1478 (provenance read), FE-1439 (durable session / document boundary) | -| **E4 — the real entry** | Client-tool results do not return to the elicitor; retry/abandonment semantics unproven; realization gated. | FE-1438, FE-1420, FE-1480 | -| **E5 — the teaching layer** | The harness teaches eight sentences; the plugin runbook carries five-sixths harness method that gherkin would repeat; the parser reads the floor and anchor from prose by convention. Opened by E1's landing ([S-008](STRATEGY-LOG.md#s-008)); designed by [ADR-0007](../adr/0007-harness-teaching-meets-plugin-content-at-fixed-keys.md); converged by co-authoring both plugins ([S-009](STRATEGY-LOG.md#s-009)). | FE-1431 (authoring surface — Done, catalogue frozen at cycle two), FE-1406 (repertoire — built and moved into core by ADR-0008), FE-1393 (zero new keys — the open proof) | - -```text -skeleton (construct job; proves the loop, produces fixtures) -FE-1497 controller read path -> FE-1482 plugin file + parser + fold --> FE-1404 skeleton run against the baseline simulated expert - (condition 5 currently proves that the loop closes but does not reach completion) - -reviewer lane (review-and-revise job; the acceptance proof) -FE-1420 retry/abandonment safety -> FE-1438 client-tool return -> FE-1439 durable session -FE-1478 provenance read -> FE-1480 scaffold/realization -> FE-1479 targeted correction join - -authoring lane (E5; a convergence cycle alongside the skeleton run, joining it at a run over the migrated plugin) -each cycle: write the core schema + core repertoire + both plugin.yaml files together - -> review: does every key plausibly serve both? press against the CPS edge material - -> run: re-do the simulated interviews over the wired agent — baseline conditions 4 (the rendered - layer as prompt only) and 5 (the shipped harness in the loop); 1–2 are frozen, 3 retired (S-010) - -> the strains and failures found are the next cycle's input to the ontologies and definitions - -> edit; the catalogue freezes when a cycle changes no key -FE-1431 (schema, plugin.yaml, key reader) | FE-1406 (core ./prompts repertoire) | FE-1393 (gherkin, zero keys) advance together -``` - -Arrows are strategic order. The skeleton lane and the reviewer lane run in parallel; they join at -FE-1479, whose "affected slice", "re-evaluate", and "delta" moves consume E1's fold and completion. -The authoring lane's sizing is [S-008](STRATEGY-LOG.md#s-008)'s; its co-authoring method is -[S-009](STRATEGY-LOG.md#s-009)'s. - -### Proof bundle - -- **Proof 0 — the black triangle (FE-1503).** Prospective fields: claim and scenario as in the - objective; production entrypoints `apps/brunch-agent/src/petrinaut-chat.ts` over `/api/chat` and - the real Petrinaut panel; fixture: none — a human is the expert; runnable procedure: the - documented dev commands; run snapshot: per-turn timing and the store under proof evidence; - legibility snapshot: a screen recording plus a plain-language account; witness: the human who - ran it (required — this is a live-runtime claim). Result-dependent fields open. -- **Proof 1 — the loop works (skeleton run, FE-1404).** A harness with **no domain knowledge**, - loaded with the SDCPN plugin file, interviews the existing simulated coatings-plant expert - through the production capture, fold, completion, and cue path. Scored against conditions 1 and - 2 on the inherited dimensions, with the FE-1407 failure catalogue as the oracle list. Then the - truck-fleet case (Layer B's validation case; fixture from the inbox SDCPN nets if the dossier - stays missing) through the **unchanged** plugin file: zero new headings, zero new rows. - Existing [condition-5 evidence](../evidence/evaluations/process-model-elicitation/baseline/transcripts/) - narrows the claim: **the harness conducts an elicitation; it does not yet converge one.** Identity - and latency remain open. The next run adds per-purpose timing before the C1/C2 and FE-1407 - read-out; the truck-fleet half remains unrun. -- **Proof 2 — the acceptance run** as stated in the objective, on the reviewer lane. -- **Inputs:** the plugin file; the baseline situation pack, transcripts, and readout (coatings - plant, not truck fleet); the FE-1407 catalogue; the FE-1402 invariants as tests on - `evaluateCompletion`; the 44-prefix rehearsal as a golden-fixture candidate once re-expressed at - kind level. No new evaluation instrument is built for September: the simulated expert and the - C1/C2 scoring are the fixed instrument, and for condition 5 the harness's own facts (captures, - sweep results, completion report) replace any text classifier ([S-010](STRATEGY-LOG.md#s-010)). -- **Durable outputs:** production-path code in `packages/core` and `packages/plugin-sdcpn`; the - skeleton transcript and readout under evaluation evidence; amendments to the plugin file only - where the run forces them. -- **Runtime and witness boundary:** Proof 1 needs no human witness; Proof 2 requires the deployed - production entrypoint and a witness record. -- **Oracle candidates:** each FM entry as a harness test; `evaluateCompletion` invariants; - slice-locality of the projection delta (outside-scope region byte-stable). - -### Active soft edges - -- FE-1497 precedes FE-1482 only by the width of an interface: the fold and completion functions are - harness code that the plugin's tables parameterise. Build them together on one branch if that is - faster; do not design the interface before the first plugin exercises it. -- FE-1420's idempotency and abandonment semantics precede FE-1438's external-tool protocol; FE-1439 - then proves the reviewer path survives reload without crossing principals. -- FE-1478 supplies supporting-capture reads before FE-1480 realization; FE-1480's executable proof - remains gated by FE-1438. -- FE-1393 follows the SDCPN plugin; gherkin is the generality check, not the tracer that precedes. -- FE-1477 and FE-1440 share one routing implementation; one folds into the other. -- FE-1395's structured-tap transport fact inputs the capture-store evidence rule. -- FE-1385/FE-1423 share telemetry vocabulary before FE-1423's exposure gate. -- The living-prototype charter waits on the infrastructure conversation. - -The read-only Linear graph supplies mechanical availability, never priority. - -## Immediate concern — per-turn latency - -The production run is not viable at its observed ~145 seconds per interviewer turn. The -[latency assessment](../evidence/evaluations/process-model-elicitation/baseline/condition-5-turn-latency.md) -owns the diagnosis and intervention sequence. Operative force here: every next harness run records -`durationMs` per turn purpose (R0 lands inside G0), R1 opens G1, and the isolating spike runs when -a human at the panel cannot get a question within target; the C1/C2 and FE-1407 read-out follows -the spike. The first per-purpose figure comes from the Proof 0 panel run, not from another -simulated condition-5 run: W2's R0 instrumentation is committed and FE-1505 accepts a panel run. -The simulated baseline is a cross-check, and it runs only once a short-run knob makes it cheap. Provisional targets (adopted 2026-08-26) are 10 seconds to a visible question, 60 -seconds to a settled sweep, and fewer than 5,000 output tokens per steady-state turn. The triangle -changes the witness: latency is no longer a number in a transcript but a person waiting. - -## Active gates - -| Gate | Owner / source | Watch trigger | Last checked | Consequence | -| --- | --- | --- | --- | --- | -| G0's baseline lives on a partly merged stack | Lu; #9320 and #9321 merged 2026-08-26; #9322, #9325, #9327 (approved) and #9337 (draft) remain, carrying `ln/fe-1431-plugin-authoring-cycle` | The rest of the stack merges to `main`. | 2026-08-26 | #9337 (draft) is the bottleneck: the whole effort line (1504 → 1506 → 1505 → 1431-plugins → w4-topology) sits above it, and only #9345 (1504, draft) has a PR so far. Nothing reaches `main` until it merges. Cycle two and ADR-0008 have superseded its draft scope; take it out of draft and merge the four remaining PRs, then the line restacks onto `main`. `ln/w4-topology` needs an issue before it is submitted (a branch carries at least one). | -| FE-1480 executable realization unavailable | FE-1438; [ADR-0005](../adr/0005-model-assisted-sdcpn-realization.md) | Client tools return code diagnostics to the elicitor. | 2026-08-26 | Scaffold work may proceed; no runnable FE-1480 proof until the gate opens. | -| Final use case outstanding | Dora; FE-1476 / September Plan | Dora confirms or changes it. | 2026-08-26 | If creation is required, Proof 1 becomes acceptance-relevant rather than a harness proof; reconcile ADR-0004/proof. | -| Deferral licensing (completion spec rules 17–19) unbuildable | [elicitation-completion](../specs/elicitation-completion.md) rules 17–19; FE-1480 / [ADR-0005](../adr/0005-model-assisted-sdcpn-realization.md) | A durable projection delivery exists for an evaluated revision. | 2026-08-26 | E1 supplies the report and revision; rule 18 makes licensing `false` without a delivered projection, so no issue is opened. When FE-1480 delivers, it is one read-time function beside `evaluateCompletion` plus a binding hook at settlement; no new persistence. | -| Truck-fleet dossier missing from the repository | FE-1382 (truck-fleet dossier) promised a `docs/reference/research/` artifact that is absent. | Artifact path/branch is supplied or a reviewed replacement is selected. | 2026-08-26 | The generality half of Proof 1 uses a fixture derived from the inbox truck SDCPN and Layer B's worked example; claim no dossier-backed domain provenance. | -| Voice-edge provider undecided | Kostandin; H-6763 prototype plan (branch `kostandin/h-6763-…`); OpenAI Realtime is the current first choice, ElevenLabs the architectural lean. | Comparison recordings and a recorded team decision. | 2026-08-26 | The attach surface (`/api/chat` stream, `brunch_ask`, principal) is frozen regardless of provider; provider-specific needs arrive as generic host extensions on the website side, never as Brunch code. | - -## Decision-relevant beliefs and unknowns - -| Belief or unknown | Confidence / evidence | Cheapest probe | -| --- | --- | --- | -| Construct and review-and-revise share most of one runbook. | Medium-low; Lu's reading of the early plugin-schema passes; unrehearsed. | Author both job runbooks against the key schema and diff them; a cycle of the plugin loop. | -| Kind-level rows express the coatings case. | High; cycle-two [condition-5 evidence](../evidence/evaluations/process-model-elicitation/baseline/transcripts/) folds 166 captures into 51 nodes with 0 unmapped, and the 93 unsatisfied rows are declared demands, not missing vocabulary. Sufficiency for completion is still unshown. | A run with identity handling; count objective nodes. | -| Typed extraction on the verbatim floor holds up in a live run. | Medium-high; the [latency assessment](../evidence/evaluations/process-model-elicitation/baseline/condition-5-turn-latency.md) records repaired refusals and leaves cost, not correctness, as the open question. | R0 + the assessment's §6 spike: does a cheaper extraction model keep kind/node/slot agreement? | -| The shipped loop converges to completion. | Low; both condition-5 runs ([cycle one](../evidence/evaluations/process-model-elicitation/baseline/transcripts/cycle-1/), [cycle two](../evidence/evaluations/process-model-elicitation/baseline/transcripts/)) end with node identity the dominant defect and no terminal act for an expert-stopped engagement; the cycle-two readout routes both to FE-1383 as harness work, not catalogue gaps. | Give the sweep the node index (R4); rerun condition 5; count objective nodes. | -| Per-turn latency is dominated by extraction, and removable from the critical path. | Medium; the [latency assessment](../evidence/evaluations/process-model-elicitation/baseline/condition-5-turn-latency.md) infers the split from output volume because per-call timing is absent. | R0, then the assessment's §6 spike on frozen turn tails. | -| The condition-5 instrument is too expensive to iterate on. | High; a full run is 12–24 turns at ~145 s each (30–60 min), `harness-run.ts` writes every artefact only at the end, `HARD_STOP_AT = 24` is hard-coded with no short-run knob, and W2's afternoon (2026-08-26, ~3 h after the credential fix) produced attribution fixes and no completed figure. The instrument's cost is now a bound on the P1 cycle and on every harness fix. | A `BRUNCH_BASELINE_HARD_STOP` env (a 3-turn run yields the purpose split in under 10 min); the §6 frozen-tail replay; and taking the first split from the Proof 0 panel run, which FE-1505 already accepts ("harness **or** panel run"). | -| The baseline and the panel measure the same interviewer. | Low; `harness-run.ts` defaults `BRUNCH_SDCPN_MODEL` to `claude-opus-5`, `sdcpn-elicitor.ts` defaults it to `claude-haiku-4-5`. The 145 s figure is opus in the baseline; the panel's production default is unmeasured and undecided. | Lu names the Proof 0 interviewer model before the run; the run records it in the proof bundle. | -| The truck-fleet case adds zero headings and zero rows. | Medium; Layer B was validated against it, but never through this file. | Proof 1's second half. | -| The controller read path is small. | Low; the current implementation exceeds the plugin file in size. The parser question is answered by ADR-0007 decision 8; completion rules 17–19 remain behind the delivery gate. | Watch whether FE-1479's affected-slice and delta moves fit inside the existing engine, and whether FE-1431's key reader stays smaller than the parser it replaces. | -| Executable ownership survives a topology correction without rescoping the teaching. | Medium; W4 moved the repertoire byte-identically into core and strengthened the import guard, but no later content edit has tested the run-evidence discipline. | On the first post-W4 teaching edit, require run evidence and confirm the architecture gate still prevents plugin imports. | -| Field-local code obligations support localized realization and repair. | Low-medium; the corpus and Petrinaut diagnostics are field-addressed, but no Brunch run exists. | Realize one stochastic transition without rewriting an unrelated field. | -| Five turns yield a scoped correction. | Low; unrehearsed. The review-and-revise runbook in the plugin file is the first concrete trajectory. | Run two bounded rehearsals against a fixture model. | -| Ask carries durable client-tool results. | Medium-low; the current protocol refuses machine results. | Run one correlated FE-1438 round trip. | -| Structured export explains provenance/delta. | Medium; FE-1481 permits it. | Witness one rehearsal. | - -## Sequencing cuts - -- Cold-start does not gate review-and-revise ([S-001](STRATEGY-LOG.md#s-001)); the skeleton's fold, - completion, and cue serve both jobs, which is why it is built first. -- Implement the slice; design only what the slice forces ([S-007](STRATEGY-LOG.md#s-007)). No new - spec precedes the code that needs it. -- Plugins are per target formalism and domain-neutral by rule ([ADR-0006](../adr/0006-plugins-per-target-formalism.md)). - No domain content enters a plugin file; a case that seems to need it is a finding for an ADR. -- Evaluation instruments stay smaller than the thing they evaluate. The simulated expert and the - inherited scoring are the fixed instrument for September. -- Gherkin follows SDCPN as the generality check; no generic SDK freeze (FE-1387, gist: generic - plugin freeze) before September. -- Defer broad UI/ontology/gallery/affordances/voice/scenarios/telemetry until the loop closes. -- Fixtures supply domain state, never product wiring; provenance and the real entrypoint are gates. -- The teaching layer is built as executable topology — core-owned prompt data behind a guarded - subpath, fixed keys, a schema, and gates — never as spec prose alone; its content is not rescoped - without run evidence ([S-008](STRATEGY-LOG.md#s-008), - [ADR-0007](../adr/0007-harness-teaching-meets-plugin-content-at-fixed-keys.md), - [ADR-0008](../adr/0008-repertoire-and-plugin-contract-live-in-core.md)). -- The key catalogue is a working set until a cycle changes no key: fix it by writing both plugins - against it, not by decree ([S-009](STRATEGY-LOG.md#s-009), ADR-0007 decision 9). -- The triangle first, poorly; no layer is optimised for its own sake before the end-to-end flow - exists ([S-011](STRATEGY-LOG.md#s-011)). Providers own audio; Brunch owns history, questions, - captures, and provenance; provider conversation history is never authoritative. - -## Stop or replan - -- Dora requires cold-start creation. -- **Proxy completion:** an arc ends with durable outputs that are all desk, simulated, or - evaluation-side and no production-path code changed. The next arc must move production code or - the trigger fires. -- The next run over the harness reports tokens but not time per turn purpose (the latency concern - stays a hypothesis), or a latency target is still unset when a move or stream is selected. -- Proof 1 shows a `Must know` that kind-level rows cannot express, or the truck-fleet case needs a - new heading (ADR-0006's revisit condition). -- E1 exceeds the plugin file in size, or needs a persistence surface. -- A code obligation cannot localize realization without whole-net resynthesis. -- Two rehearsals fail the five-turn correction. -- FE-1438 loses correlation, durability, or evidence semantics. -- Production remains undeployable after FE-1479; seek a demo-surface decision, not test wiring. -- The teaching layer's content is rescoped again without run evidence, or guarded prompt defaults - become importable by plugins or from core's root. -- A first question at the panel takes longer than 10 s after R0 and R1 (the spike becomes - blocking); the panel needs Brunch-specific code inside `@hashintel/petrinaut`; or persistence - modelling needs a schema the harness must know. -- A G0 move, a stream, or any arc closes with only desk, hidden-run, or machine-only evidence - ([legibility](../agents/legibility.md#what-counts-as-legible)). -- A package is split or moved without an ADR. - -## Exceptional roots - -- **FE-1331** — create-new-net entry; keep exceptional until the watched use-case decision settles - whether it joins the cold-start lane or receives a parent. -- **FE-1334** — surprising-scenario validation gesture; parent or cancel when its owning outcome is - chosen. -- **FE-1472** — unrelated SDK-pin triage; assign an owning map or remove from the project. -- **FE-1476** — September delivery root; intended parent is FE-1357. -- **FE-1477–FE-1481** — PM-authored outcome roots; intended parent is FE-1476 after overlap review - and separately approved Linear mutation. diff --git a/libs/@hashintel/brunch-agent/docs/control/STRATEGY-LOG.md b/libs/@hashintel/brunch-agent/docs/control/STRATEGY-LOG.md deleted file mode 100644 index 6c1c1c7b72f..00000000000 --- a/libs/@hashintel/brunch-agent/docs/control/STRATEGY-LOG.md +++ /dev/null @@ -1,446 +0,0 @@ -# Brunch strategy log - -This append-only log records material strategic choices: objective, proof frontier, authority -boundary, material cut, gate consequence, or confidence changes. It is neither an ADR (which owns -accepted architecture) nor a diary. IDs increase monotonically. Conflicting decisions append an -entry naming the superseded governing ID; complementary decisions use `none`. Existing entries are -immutable except for typo/link repair, and only unsuperseded governing IDs appear in `STEERING`. - -## Entries - -### S-001 - -**Date:** 2026-08-24 - -**Trigger/evidence:** FE-1476 defines a bounded reviewer correction scenario; the final use-case -decision remains outstanding. - -**Decision:** Review-and-revise is the September proof. Full cold-start remains an important -quality benchmark and contingency lane, not a gate on this proof. - -**Consequences/cuts:** Build against an existing source-grounded target now; activate cold-start if -the use-case decision changes. This does not define permanent product scope. - -**Revisit when:** Dora confirms or changes the use case, or the prepared target cannot support the -optimisation handoff. - -**Supersedes:** none - -**Evidence links:** [STEERING objective](STEERING.md#objective-and-acceptance-proof), FE-1476, -[ADR-0004](../adr/0004-in-petrinaut-staging-and-the-monorepo-import.md) - -### S-002 - -**Date:** 2026-08-24 - -**Trigger/evidence:** The Gherkin floor deliberately under-stresses the provisional plugin contract; -FE-1480 remains unresolved and CPS is its first material consumer. - -**Decision:** The worked CPS slice establishes the minimum exercised plugin contract before a -generic contract freeze. - -**Consequences/cuts:** FE-1482 pressures the interface first; FE-1387 and broad generic/Gherkin -completion follow the proof rather than gate it. - -**Revisit when:** The worked CPS transformation requires a reusable harness primitive that must -precede the slice. - -**Supersedes:** none - -**Evidence links:** [plugin contract](../specs/plugin-contract.md), -[ADR-0003](../adr/0003-three-register-ir.md), FE-1480, FE-1482 - -### S-003 - -**Date:** 2026-08-24 - -**Trigger/evidence:** CPS semantics and reviewer transport/session work have independent early -risks, but neither proves value until a real correction crosses both. - -**Decision:** Run semantic and reviewer lanes in parallel and join them at targeted correction -before provider routing and deployment. - -**Consequences/cuts:** FE-1482/FE-1480/FE-1478 and FE-1438/FE-1439 may proceed concurrently; -FE-1479 is the mandatory join, followed by FE-1477/FE-1440 and FE-1441. - -**Revisit when:** Either lane fails its first production-path probe or FE-1479 exposes a missing -shared prerequisite. - -**Supersedes:** none - -**Evidence links:** [STEERING](STEERING.md) (the execution tree of that date; the section was -folded into "Epicentres and lanes" on 2026-08-26), FE-1479 - -### S-004 - -**Date:** 2026-08-24 - -**Trigger/evidence:** All seven incoming SDCPNs contain TypeScript code surfaces, and the richer -examples require substantial stochastic lambdas, transition kernels, dynamics, scenario code, and -metrics. FE-1480 therefore fired the replan trigger: an executable net cannot be projected -deterministically from the elicited model. - -**Decision:** Produce a deterministic SDCPN scaffold, typed code obligations, and loss report from -the elicited model; realize the obligations with model inference through Petrinaut client tools; -then gate the result with deterministic compilation and simulation. - -**Consequences/cuts:** Scaffold work remains independent, but FE-1438 blocks FE-1480's executable -production proof. The semantic and elicitor lanes first join at FE-1480 realization, then join the -review-and-revise path at FE-1479. This authority decision does not select FE-1480 implementation as -the next investment. - -**Revisit when:** Field-local obligations cannot support localized repair without whole-net -resynthesis, or Petrinaut diagnostics cannot provide the deterministic gate. - -**Supersedes:** S-003 - -**Evidence links:** [ADR-0005](../adr/0005-model-assisted-sdcpn-realization.md), -[incoming SDCPNs](../inbox/SDCPNs/), FE-1480, FE-1438 - -### S-005 - -**Date:** 2026-08-24 - -**Trigger/evidence:** FE-1480's authority boundary is settled, but the implementation floor remains -thin: the plugin SDK exposes identity plus one verbatim proposal, the client-tool surface exposes -only ask contracts, and FE-1482 has no build-ready contract. In contrast, FE-1407, FE-1402, -FE-1403, FE-1404, and FE-1406 each have bounded existing evidence and explicit non-HITL oracles. - -**Decision:** Run a design-convergence queue before more runtime feature work: FE-1407 failure -catalogue, FE-1402 completion/stopping contract, FE-1403 CPS guidance, FE-1404 condition-3 run, and -FE-1406 reusable strategy quiver. Use those results to narrow FE-1431 to a build-ready -plugin-authoring handoff, including the absence locator. Then build the under-developed reviewer -path before returning to semantic realization. - -**Consequences/cuts:** One agent can execute the design queue from existing inputs without waiting -for domain experts or the final use-case decision. No SDK, client-tool, projection, provider, or -deployment implementation belongs inside that frontier. After design convergence, the selected -order is FE-1420 → FE-1438 → FE-1439, then FE-1393 → FE-1482 → FE-1478 → FE-1480, joining at -FE-1479. These are strategic sequencing edges; Linear hard dependencies remain unchanged until a -separately approved tracker reconciliation. This replaces S-002's claim that Gherkin completion -does not gate CPS: FE-1393 now provides the smallest-honest, explicitly non-freezing SDK exercise; -FE-1482 still pressures that interface before FE-1387's generic freeze. - -**Revisit when:** A design issue requires an unrecorded product preference or new domain testimony, -condition 3 fails to discriminate the claimed improvements, or FE-1431 cannot separate a build-ready -contract from later three-target ratification. - -**Supersedes:** S-002 - -**Evidence links:** [STEERING](STEERING.md) (the design-convergence frontier of that date, closed by -S-007; no current section), -[plugin contract](../specs/plugin-contract.md), FE-1407, FE-1402, FE-1403, FE-1404, FE-1406, -FE-1431 - -### S-006 - -**Date:** 2026-08-24 - -**Trigger/evidence:** The design-convergence queue in S-005 was selected, but Linear did not encode -three genuine prerequisites, and FE-1431 still conflated a build-ready design handoff with later -three-target ratification. - -**Decision:** Encode FE-1407 blocking FE-1404, FE-1404 blocking FE-1406, and FE-1406 blocking -FE-1431 in Linear. Define FE-1431 as complete when its plugin-authoring contract is build-ready, -while retaining three-target ratification as a later condition for removing the contract's -provisional marker. Keep every other sequencing edge in S-005 soft. - -**Consequences/cuts:** Mechanical issue availability now protects the three actual joins without -pretending that the whole strategic order is a dependency graph. FE-1402 and FE-1403 can still run -independently, and SDK implementation or empirical ratification cannot hold FE-1431's design -closure open. - -**Revisit when:** A recorded prerequisite proves unnecessary, or implementation exposes a product -decision that the FE-1431 handoff failed to settle. - -**Supersedes:** none - -**Evidence links:** [STEERING](STEERING.md) (the design-convergence frontier of that date, closed by -S-007; no current section), -FE-1407, FE-1404, FE-1406, FE-1431 - -### S-007 - -**Date:** 2026-08-25 - -**Trigger/evidence:** The S-005 design-convergence queue ran to its end without changing a line of -production-path code. FE-1402's rehearsal needed an oracle and authored a DemandTable keyed to the -baseline coatings-plant domain (`where(kind, role=…)` scopes, `ROW-BREAKDOWN`-style objective rows), below -the level at which the IR spec's Layer B had already defined the plugin; the contract's "September -ships kind-only" was correct and the oracle was wrong. FE-1403's five `domain` cards each lift to a -kind-level pattern. FE-1404 produced a 5,400-line preregistered instrument through nine rejected -review renderings, never ran, and committed the rejected draft lock (stale hashes, missing paths; -its own `--verify-seal` refuses it); structurally it is a shadow harness — operator, projection -schema, diagnostic priority, novelty streak, and sealed segments each mirror a harness component -that the S-005 cut forbade building. The whole queue worked the cold-start lane while the -objective is review-and-revise (S-001: cold-start does not gate it; fixtures supply the prebuilt -model). Factual correction: STEERING's proof bundle named "truck-fleet baseline transcripts"; the -baseline situation pack is a coatings plant (Vestera Coatings, Production Process -Scheduling), and truck-fleet is Layer B's validation case, whose dossier is still missing (see the -FE-1382 gate). "Tracer as definition of done" recurred as "desk rehearsal / preregistered -instrument as definition of done". - -**Decision:** Invert S-005 and S-006: implement the vertical slice and design only what the slice -forces. Adopt [ADR-0006](../adr/0006-plugins-per-target-formalism.md): plugins are per target -formalism, authored as one sectioned Markdown file; `packages/plugin-sdcpn/plugin.yaml` is the exemplar. -Close the design-convergence queue: FE-1407, FE-1402, and FE-1403 are reclassified as test-bed -material; FE-1404 is redefined as the skeleton run — condition 3 as the protocol originally -defined it (kernel harness + real plugin), not the shadow-harness instrument; FE-1406 shrinks to -lifting harness-generic patterns out of plugin files; FE-1431 mostly dissolves (a file format and -a parser, not seven authoring seams); FE-1393 is demoted to a post-skeleton generality check (a -second formalism adds zero headings). Promote the reviewer lane (FE-1420 → FE-1438 → FE-1439) and -the semantic lane (FE-1478 → FE-1480 → FE-1479) to primary. The skeleton epicentre is FE-1482 plus -a harness controller read path (captures → model → next move), which has no issue yet. Rejected: -finishing the design queue as planned, because its outputs are desk artefacts that cannot be -wrong in a way the product would notice, and running condition 3 with the shadow harness, because -it would measure an instrument the product will never ship and displace the kernel a second time. - -**Consequences/cuts:** The hard-blocker chain FE-1407 → FE-1404 → FE-1406 → FE-1431 recorded by -S-006 is removed; Linear mutation remains a separately approved step. The plugin-contract, -completion, and interview-guidance drafts are archived; the specs shrink to the heading contract, -table grammar, `project`/`validate` seam, and `evaluateCompletion` invariants. The FE-1404 -instrument is archived as test-bed; its Valibot projection schema and validators are salvage. -Beliefs updated: "the design queue can run without HITL" is retired as answered-but-irrelevant — -it ran, and proved nothing the product needed; "CPS establishes the minimum plugin contract" -rises to high, evidenced by the one-file plugin. New heuristic recorded in the steering protocol: -an evaluation instrument larger than the thing it evaluates is itself the finding; a frontier whose -durable outputs are all desk, simulated, or evaluation-side, with no production-path code changed -by the end of one arc, triggers replan. - -**Revisit when:** The skeleton's parser, fold, or `evaluateCompletion` cannot be built from the -sectioned file without a typed declaration the file cannot carry, or a second formalism needs a -heading the contract does not have (ADR-0006's condition). - -**Supersedes:** S-005, S-006 - -**Evidence links:** [ADR-0006](../adr/0006-plugins-per-target-formalism.md), -[sdcpn plugin file](../../packages/plugin-sdcpn/plugin.yaml), -[IR spec Layer B](../specs/intermediate-representation.md#layer-b--the-cps-plugins-ir), -[archived drafts](../archive/specs/), -[baseline situation pack](../../evaluations/cases/process-model-elicitation/baseline/situation-pack.md), -[condition-3 instrument](../../evaluations/protocols/process-model-elicitation/baseline/), -FE-1402, FE-1403, FE-1404, FE-1406, FE-1431, FE-1482 - -### S-008 - -**Date:** 2026-08-25 - -**Trigger/evidence:** The controller read path landed (FE-1497, #9325) and the slice forced two -findings. First, the SDCPN `construct` runbook is five-sixths harness method — open with objectives, -slice, sweep, probe, keep the ledger, close honestly — that a `gherkin` plugin written to the same -contract would repeat; the plugin file carries it because the contract gives the harness no place -to put its own. Second, the plugin-file parser and the proposal-schema narrowing that hangs off it -are 378 lines against a 225-line file, reading the floor by regex over prose and the completion -anchor by naming convention. The [lineage audit](../evidence/proofs/audits/harness-teaching-lineage-audit.md) -then showed that the harness-teaching half of §11.5 — "guidance ownership follows vocabulary -ownership" — was affirmed at every design station since 2026-08-11 and rescoped down four times -(designed quiver → graduated cards → five relocated rows), each time as prose with no home and none -of the times citing run evidence. The penciled manifest of 2026-08-14 (licenses, techniques, -movements, motifs, rabbit_holes, failure_modes, smells, lenses, checks, tools, ontology, schema) -already stated the structure that fits: every key lets an author give formalism-specific direction -in concepts the harness defines and teaches. - -**Decision:** Complements S-007 (amending its sizing of FE-1406 and FE-1431; supersedes nothing). -Materialise the harness-teaching layer as topology, per -[ADR-0007](../adr/0007-harness-teaching-meets-plugin-content-at-fixed-keys.md) (proposed; governs on -ratification): a fixed set of harness-owned keys in four groups — contract data, guidance typed by -mechanism, per-job runbooks, machinery — each rendered key → harness default → plugin cell; a -`packages/repertoire` package that depends only on `core` and that bindings render; a JSON schema -in `core` that rejects unknown keys; gates that require the repertoire to fill every key and forbid -a plugin from adding one. FE-1406 is restored to its original question with the package as its -deliverable; FE-1431 becomes the plugin authoring surface (schema, `plugin.yaml`, key reader, -SDCPN migration); FE-1393 stays the zero-new-keys check. This complements S-007 rather than -reversing it: the slice forced the layer, the layer is built as code and gates rather than spec, -and each layer ships paired with the document that states its intent. Sequencing: the authoring -lane (FE-1431 → FE-1406 → FE-1393) runs alongside the skeleton run (FE-1404) and joins it at a -second run over the migrated plugin. Rejected: holding FE-1406 at five rows, because it repeats the -recorded pattern; and a spec-first design of the repertoire, because that is the failure S-007 -corrected. - -**Consequences/cuts:** STEERING gains a fifth epicentre for the teaching layer, an authoring lane in -the frontier, an ADR-0007 ratification gate, an anti-rescope trigger, and an updated belief row: the -"is the parser an argument for data?" probe is answered yes by decision 8. Linear edits to FE-1406, -FE-1431, and FE-1393 remain a separately approved step. The domain-neutrality rule, the derived -ordering of IR Layer B, and completion rule 15 are unchanged. - -**Revisit when:** ADR-0007 is rejected or amended in a way that removes a group; the migrated SDCPN -plugin or the gherkin plugin needs a key the schema lacks; or `packages/repertoire` grows larger -than the plugin it teaches (the instrument-larger-than-the-thing heuristic, applied to guidance). - -**Supersedes:** none - -**Evidence links:** [ADR-0007](../adr/0007-harness-teaching-meets-plugin-content-at-fixed-keys.md), -[lineage audit](../evidence/proofs/audits/harness-teaching-lineage-audit.md), -[penciled directions 2026-08-14](../archive/planning-inputs/penciled-directions-2026-08-14.md), -[SDCPN plugin file](../../packages/plugin-sdcpn/plugin.yaml), FE-1406, FE-1431, FE-1393, FE-1497 - -### S-009 - -**Date:** 2026-08-25 - -**Trigger/evidence:** Lu accepted ADR-0007 with one caveat: fixing the precise key catalogue now -would be counter-productive. The evidence behind the caveat is the FE-1482 arc itself — an agent -can produce a plausible plugin definition from a given structural and semantic schema in minutes, -so the design activity being left on the table is not writing the catalogue but pressing it: two -test-case plugins (`sdcpn`, `gherkin`) that must both read well under one schema, and a body of -process-modelling edge material (the CPS grilling inputs, the truck-fleet and coating cases, the -FE-1360 literature deposit) that the key set must be general enough to cover, specific enough to -direct, and flexible enough not to bind to. - -**Decision:** Converge the catalogue by co-authoring. Each cycle writes the schema, both plugin -files, and the repertoire together; reviews whether every key plausibly serves both plugins and the -edge material; runs the result where a run exists; edits. FE-1431, FE-1406, and FE-1393 advance in -the same cycle rather than in the sequence S-008 gave them. Keys may be added, merged, or dropped -inside a cycle, recorded in the package changelog; the catalogue freezes when a cycle changes no -key and a third-formalism sketch (formal verification) fills cells only. Rejected: freezing the -catalogue from the ADR (untested structure, the failure the record shows); and writing the SDCPN -plugin first with gherkin as an after-the-fact check (the S-007 order, which would let one -formalism shape the schema before the other pressed it). Complements S-008 (amending its lane -order); supersedes nothing. - -**Consequences/cuts:** STEERING's authoring lane becomes a cycle; the ADR-0007 gate closes; the -ADR gains decision 9; the three Linear issues are rewritten to advance together. The catalogue's -changelog lives in `packages/core` beside the schema. A cycle that changes no key is the freeze -signal, and the first one is a recorded event. - -**Revisit when:** three cycles pass without the set shrinking or stabilising (the pressure is not -converging it); or the two plugins need different groups rather than different cells (the -one-schema premise fails); or a run contradicts what a review call plausible. - -**Supersedes:** none - -**Evidence links:** [ADR-0007 decision 9](../adr/0007-harness-teaching-meets-plugin-content-at-fixed-keys.md), -[S-008](#s-008), [grilling inputs](../archive/planning-inputs/), FE-1482, FE-1406, FE-1431, FE-1393 - -### S-010 - -**Date:** 2026-08-25 (decision), recorded 2026-08-26 - -**Trigger/evidence:** The first S-009 cycle reached its "run" step and the baseline protocol had to -say what a run is. Condition 4 (the rendered ADR-0007 teaching layer as a prompt only, run and -scored 2026-08-25) showed the inherited delivery classifier producing a false negative — a -regex over the interviewer's text judging whether a model had been delivered — which is the -instrument weakness S-007 named, recurring in miniature. Condition 3's preregistered instrument -(operator, projection schema, lock) had never run and would have measured a hand-operated -projection of completion machinery the harness now ships. The harness itself exposes facts a -classifier can only guess at: captures applied, sweeps refused and why, completion computed -over the store after each turn. Lu's direction: "Retire 3, freeze 1 and 2, and start on -condition 5 now." - -**Decision:** The baseline protocol's arms are re-cut. Conditions 1 and 2 are **frozen** as the -2026-08-13 reference; condition 3 is **retired, never run**, its preregistration and lock kept as -the record of what was planned; conditions 4 and 5 are the **live arms, rerun once per authoring -cycle**. Condition 5 puts the shipped harness in the loop: the runner starts the Flue runtime -in-process with the production SDCPN elicitor and the same simulated expert, and its deliverable -is the capture store, not a delivered text — **harness facts replace the classifier** as the -instrument for anything the harness can report. This amends S-007's sentence "running condition 3 -with the shadow harness … would measure an instrument the product will never ship": the run -S-007 wanted is condition 5; the number 3 stays with the retired instrument. Rejected: running the -condition-3 instrument once "for the record", because it would measure the instrument; and -scoring condition 5 with the text classifier, because condition 4 had just shown it wrong. - -**Consequences/cuts:** The first condition-5 run (2026-08-25) is committed as evidence; STEERING -records its result under Proof 1 and its latency as an immediate concern with its own assessment. -FE-1404 is that run under a different number; its Linear body and its salvage-and-delete -expectation for the condition-3 instrument are unreconciled (Linear edit pending approval; the -instrument is frozen in place with an amendment). _Addendum 2026-08-26:_ the instrument was -deleted the next day on Lu's decision, salvage assessed as none; the preregistration and prompt -remain. The runner's `stalled` stop label misnames a -deliberate interviewer self-stop and is renamed when the runner is next touched. No spec, key, -or sequencing cut changes. - -**Revisit when:** a condition-5 rerun needs a judgment the harness cannot report (then a scoring -step is added to the protocol, not a classifier); or the frozen conditions 1–2 stop being a fair -reference because the expert or situation pack changes. - -**Supersedes:** none - -**Evidence links:** [baseline protocol](../../evaluations/protocols/process-model-elicitation/baseline/protocol.md), -[condition-3 preregistration (amended)](../../evaluations/protocols/process-model-elicitation/baseline/condition-3-preregistration.md), -[first condition-5 transcript](../evidence/evaluations/process-model-elicitation/baseline/transcripts/cycle-1/condition-5.md), -[condition-4 read-out](../evidence/evaluations/process-model-elicitation/baseline/readout.md), -[turn latency assessment](../evidence/evaluations/process-model-elicitation/baseline/condition-5-turn-latency.md), -FE-1404, FE-1431, FE-1361 - -### S-011 - -**Date:** 2026-08-26 - -**Trigger/evidence:** The first condition-5 run left the harness able to conduct an elicitation -but not to converge one, at ~145 s per turn, with its only witnesses a transcript and a JSON store. -Lu's direction after the arc close: the frontier must reach the full end-to-end flow — "the black -triangle" — before any stream is worked for its own sake, for team visibility, CEO and PM -confidence, and a stable surface for the voice-mode work (H-6763, which already bridges finalized -speech turns into `/api/chat` and consumes `brunch_ask`). A wiring sweep the same day found the -triangle closer on one edge than STEERING implied — the real Petrinaut panel already reaches -`apps/brunch-agent` locally over `/api/chat` — and further on the others: the handler is hard-wired -to the Gherkin elicitor, the target document is identified with the conversation, no principal -exists, and deployment was Linear-gated behind gherkin (FE-1441 ← FE-1423 ← FE-1396 ← FE-1394 ← -FE-1393). Lu also corrected the objective's framing and named two further design concerns. - -**Decision:** - -1. **Two jobs, one order.** Construct and review-and-revise are both target jobs; cold-start - construction must be possible. This amends S-001's sentence that review-and-revise is *the* - current proof: the current proof is the construct job through the panel (Proof 0), with the - review-and-revise acceptance run on top of it. The belief that each job needs its own - comprehensive runbook is demoted to an assumption under test — early passes over the plugin - schema suggest the jobs share most of one runbook. -2. **The black triangle is the selected frontier (G0, FE-1503):** from a checkout, documented - commands bring up the Brunch server and the Petrinaut panel on local dev services; the panel's - assistant is the SDCPN elicitor; a human conducts a real elicitation; captures persist to a - target document owned by a principal and survive reload; completion accounting is - human-readable; every turn records time per purpose. Cut: no deployment, client-side net tools, - realization, Postgres, gherkin, voice code, or quality claim. Then a **sequence**: G1 the usable - triangle (latency floor R1, identity in the fold, resume), G2 the demo triangle (client tools, - deployment, the acceptance run). -3. **Streams are parallel work.** Inside G0: wiring, persistence modelled, latency floor (R0), - legible surface. Beside G0, not blocking it: the plugin design loop (is the plugin API a viable, - understandable way to specify a domain plugin, and does it come together as effective - prompt- and context-engineering material — conditions 4 and 5 rerun per cycle); and package - topology remediation (below). -4. **Package topology is remediated, by ADR.** Lu's judgment: `repertoire` is a core concern, as - are the types and schemas that binding-, transport-, and plugin- packages consume; the envisioned - core layout is `loop / prompts (repertoire) / skills? / schemas`. No further package split - without an ADR; an ADR amending ADR-0007's package decision is the owner of the accepted shape. - Rejected: moving code before the ADR — the last two splits show what unrecorded topology costs. -5. **Tool inventory is pinned** in STEERING as current truth against intent: today `brunch_ask` - and `brunch_sweep` on the server (prefix from `PRODUCT_NAME`), Petrinaut's fine-grained - `petrinautAiTools` on the client; intended `ba_sweep`, `ba_check`, `ba_ask` (possibly not yet - needed) and `pn_read`, `pn_mutate` with a `pn_infer_slots` post-update to fill TypeScript from - injected comments. No tool is added, renamed, or promised in prose outside that table. -6. **Legibility is defined on the human**: observable interactions with visible state change and - data flow, plain-language accounts, recordings; desk evidence, hidden runs, and machine-only - artefacts never stand alone as proof. Recorded in `docs/agents/legibility.md`; a stream with - only such evidence is not done. -7. **The voice edge attaches at `/api/chat`.** The AI SDK UI-message stream, the `brunch_ask` - schema, and the principal identity are the stable surface; they change with notice. Provider - choice (OpenAI Realtime is Kostandin's first choice) is an external gate, not a Brunch decision. - -**Consequences/cuts:** FE-1503 created under FE-1476 as G0's projection; the stale FE-1396 → FE-1423 -blocker removed (FE-1394 ← FE-1393 remains, in the build map). The latency targets adopted -provisionally on 2026-08-26 stay; the isolating spike is no longer "first task of the next arc" — -R0 lands inside G0, R1 opens G1, and the spike runs when a human at the panel cannot get a question -within target. The condition-5 read-out stays deferred behind the spike. The epicentre lanes of -S-007 remain valid context and are subordinated to the triangle. No key, spec, or ADR text -changes here; the topology ADR and the surface statement in the Petrinaut integration spec are the -successor writes. _Addendum 2026-08-26:_ decision 3 misnames the work inside G0 — wiring, -persistence, latency floor, and legible surface share one proof and are therefore **moves joined -at Proof 0**, not streams; "stream" is reserved for separately proven parallel work (P1, P2), and -G0 → G1 → G2 is a **sequence**. Terms defined in `CONTEXT.md` under Strategic control. - -**Revisit when:** the first human run through the panel lands (G0's proof); the topology ADR is -accepted; the voice-provider decision is recorded; or use-case confirmation from Dora changes the -demo scenario. - -**Supersedes:** none - -**Evidence links:** [FE-1503](https://linear.app/hash/issue/FE-1503), [FE-1476](https://linear.app/hash/issue/FE-1476), -the H-6763 prototype plan — `docs/planning/process-model-elicitation/spikes/h-6763-realtime-audio-prototype-2026-08-24.md` -on branch `kostandin/h-6763-support-for-realtime-audio-interviewing-of-domain-experts` only, not -on this branch or `main`, so no relative link resolves until it merges — -[ADR-0004](../adr/0004-in-petrinaut-staging-and-the-monorepo-import.md), -[Petrinaut integration spec](../specs/petrinaut-integration.md), -[ledger §9](SPEC-LEDGER.md#sessions--durability-9), -[turn latency assessment](../evidence/evaluations/process-model-elicitation/baseline/condition-5-turn-latency.md), -[legibility protocol](../agents/legibility.md) diff --git a/libs/@hashintel/brunch-agent/docs/agents/flue-routing.md b/libs/@hashintel/brunch-agent/docs/reference/architecture/flue-routing.md similarity index 98% rename from libs/@hashintel/brunch-agent/docs/agents/flue-routing.md rename to libs/@hashintel/brunch-agent/docs/reference/architecture/flue-routing.md index 6184e885071..976b4f80cb9 100644 --- a/libs/@hashintel/brunch-agent/docs/agents/flue-routing.md +++ b/libs/@hashintel/brunch-agent/docs/reference/architecture/flue-routing.md @@ -4,9 +4,9 @@ Consult this at design moments — when you notice yourself about to add state, loop, a route, or a test harness — _before_ writing the new thing. Each row routes an indication to the affordance to rely on, the divergence it exists to prevent, and the point where canon stops and a human or an owning ticket decides. Every row is grounded in the -[architecture cheatsheet](../reference/architecture/flue-architecture-cheatsheet.md) (§ refs), the -[patterns audit](../evidence/proofs/audits/flue-patterns-audit-2026-08-17.md), or the -[flue-vs-tilde analysis](../reference/amp-analysis-flue-vs-tilde.md); details live there. +[architecture cheatsheet](flue-architecture-cheatsheet.md) (§ refs), the +[patterns audit](../../evidence/proofs/audits/flue-patterns-audit-2026-08-17.md), or the +[flue-vs-tilde analysis](../amp-analysis-flue-vs-tilde.md); details live there. **Which lane am I in?** Flue's surface sorts our system into three lanes (cheatsheet, boundary summary). _Shell-facing_ (UI transport, observability, evals, schedules, deploy): diff --git a/libs/@hashintel/brunch-agent/packages/core/test/architecture/control-surfaces.test.ts b/libs/@hashintel/brunch-agent/packages/core/test/architecture/control-surfaces.test.ts deleted file mode 100644 index 909bae0a0d0..00000000000 --- a/libs/@hashintel/brunch-agent/packages/core/test/architecture/control-surfaces.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { existsSync, readFileSync } from "node:fs"; -import { join } from "node:path"; - -import { describe, expect, test } from "vitest"; - -import { contextRootPresent, REPO_ROOT } from "./workspace"; - -const CONTROL_ROOT = join(REPO_ROOT, "docs/control"); -const STEERING_PATH = join(CONTROL_ROOT, "STEERING.md"); -const STRATEGY_LOG_PATH = join(CONTROL_ROOT, "STRATEGY-LOG.md"); -const REQUIRED_FIELDS = [ - "Date", - "Trigger/evidence", - "Decision", - "Consequences/cuts", - "Revisit when", - "Supersedes", - "Evidence links", -] as const; - -interface StrategyEntry { - readonly id: string; - readonly fields: ReadonlyMap; -} - -const strategyEntries = (markdown: string): StrategyEntry[] => - [ - ...markdown.matchAll( - /^### (S-\d{3})\n([\s\S]*?)(?=^### S-\d{3}\n|(?![\s\S]))/gm, - ), - ].map(([, id, body]) => ({ - id: id!, - fields: new Map( - [ - ...body!.matchAll( - /^\*\*([^*]+):\*\*\s*([\s\S]*?)(?=^\*\*[^*]+:\*\*|(?![\s\S]))/gm, - ), - ].map(([, name, value]) => [name!, value!.trim()]), - ), - })); - -/** - * A strategy entry may supersede several earlier entries; the field lists them - * comma-separated, or reads `none`. - */ -const supersededTargets = (field: string): string[] => - field === "none" ? [] : field.split(",").map((target) => target.trim()); - -describe.skipIf(!contextRootPresent)("strategic control surfaces", () => { - const steering = readFileSync(STEERING_PATH, "utf8"); - const strategyLog = readFileSync(STRATEGY_LOG_PATH, "utf8"); - const entries = strategyEntries(strategyLog); - - test("has one current mutable strategic control and no coordination control", () => { - expect(existsSync(STEERING_PATH)).toBe(true); - expect(existsSync(join(CONTROL_ROOT, "COORDINATION.md"))).toBe(false); - expect(steering).toContain("one mutable current strategic control"); - }); - - test("strategy entries all parse with monotonically increasing unique IDs", () => { - const entryArea = strategyLog.match(/^## Entries\n([\s\S]*)$/m); - expect(entryArea).not.toBeNull(); - const entryHeadingCount = [...entryArea![1]!.matchAll(/^### .+$/gm)].length; - expect(entries).toHaveLength(entryHeadingCount); - expect(entries.length).toBeGreaterThan(0); - expect(new Set(entries.map(({ id }) => id)).size).toBe(entries.length); - const numbers = entries.map(({ id }) => Number(id.slice(2))); - expect(numbers).toEqual([...numbers].sort((left, right) => left - right)); - }); - - test("strategy entries have every required field", () => { - for (const entry of entries) { - expect([...entry.fields.keys()]).toEqual(REQUIRED_FIELDS); - for (const value of entry.fields.values()) expect(value).not.toBe(""); - } - }); - - test("supersedes targets resolve backward without cycles", () => { - const seen = new Set(); - const invalidTargets: Array<{ - entry: string; - target: string; - reason: "malformed" | "not-earlier"; - }> = []; - for (const entry of entries) { - for (const target of supersededTargets(entry.fields.get("Supersedes")!)) { - if (!/^S-\d{3}$/.test(target)) { - invalidTargets.push({ - entry: entry.id, - target, - reason: "malformed", - }); - } - if (!seen.has(target)) { - invalidTargets.push({ - entry: entry.id, - target, - reason: "not-earlier", - }); - } - } - seen.add(entry.id); - } - expect(invalidTargets).toEqual([]); - }); - - test("every strategy ID in steering resolves and is unsuperseded", () => { - const governingSection = steering.match( - /^## Governing concerns\n([\s\S]*?)(?=^## |(?![\s\S]))/m, - ); - expect(governingSection).not.toBeNull(); - expect(governingSection![1]).toMatch(/S-\d{3}/); - const referencedIds = [...steering.matchAll(/S-\d{3}/g)].map(([id]) => id); - const knownIds = new Set(entries.map(({ id }) => id)); - const supersededIds = new Set( - entries.flatMap(({ fields }) => - supersededTargets(fields.get("Supersedes")!), - ), - ); - for (const id of referencedIds) { - expect(knownIds.has(id)).toBe(true); - expect(supersededIds.has(id)).toBe(false); - } - }); -}); diff --git a/libs/@hashintel/brunch-agent/packages/core/test/architecture/docs-index.test.ts b/libs/@hashintel/brunch-agent/packages/core/test/architecture/docs-index.test.ts deleted file mode 100644 index 070dcfcf8d2..00000000000 --- a/libs/@hashintel/brunch-agent/packages/core/test/architecture/docs-index.test.ts +++ /dev/null @@ -1,257 +0,0 @@ -/** - * Documentation coverage, as tests rather than as a habit. - * - * `docs/agents/documentation.md` states the placement rules as obligations — - * every document is indexed, documents occupy their role-based authority zone, - * and agent protocols are reachable from `AGENTS.md`. An - * obligation nobody can run is a wish, and this one decays in the quietest way - * available: a file lands, the INDEX pass is skipped once, and nothing ever says - * so. These are the mechanical checks — they walk the real `docs/` tree, so a - * document added later is governed without opting in. - * - * Both directions matter. A row that no longer points at anything is the same - * failure as an unindexed file, one step further along: the index has stopped - * describing the tree it governs, and reading it now misinforms. - */ - -import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; -import { dirname, join, relative, resolve } from "node:path"; - -import { describe, expect, test } from "vitest"; - -import { contextRootPresent, REPO_ROOT } from "./workspace"; - -const DOCS_ROOT = join(REPO_ROOT, "docs"); -const INDEX_RELPATH = "INDEX.md"; - -/** Gitignored ephemera — in the tree but not of it, so never indexed. */ -const SKIP_DIRECTORIES = new Set(["drafts"]); -/** Filesystem and placeholder artefacts: not documents. */ -const SKIP_FILES = new Set([".DS_Store", ".gitkeep"]); -/** - * `docs/agents/` is deliberately outside the INDEX's remit: those files are - * pointed at from `AGENTS.md`, which is the pointer an agent actually reads, and - * the third rule below governs them there. Listing them twice would let the two - * registries disagree about what the protocol set is. - */ -const INDEX_EXEMPT = new Set(["agents", INDEX_RELPATH]); -/** - * Preserved external analysis containing links into its source checkout and - * embedded Markdown examples. Those links are evidence, not context-local - * navigation. - */ -const LINK_CHECK_EXEMPT = new Set(["reference/amp-analysis-flue-vs-tilde.md"]); -/** Immutable migration snapshots whose old paths are part of the evidence. */ -const LINK_CHECK_EXEMPT_PREFIXES = [ - "archive/migrations/hash-monorepo-import-plan.md", - "archive/migrations/issue-pr-legibility-2026-08-20/", -]; - -/** Posix-shaped, because that is how a markdown link target is written. */ -const relPath = (path: string): string => - relative(DOCS_ROOT, path).replaceAll("\\", "/"); - -/** - * Every documentation file `docs/INDEX.md` is answerable for, relative to - * `docs/`. - * - * Enumerated live rather than snapshotted. A recorded list would go green on the - * day someone forgot to update it — the failure mode this file exists to catch, - * reproduced inside the check meant to catch it. - */ -function documentationFiles(): string[] { - const found: string[] = []; - const walk = (dir: string): void => { - for (const entry of readdirSync(dir).sort()) { - if (SKIP_DIRECTORIES.has(entry) || SKIP_FILES.has(entry)) continue; - const path = join(dir, entry); - const rel = relPath(path); - if (INDEX_EXEMPT.has(rel)) continue; - if (statSync(path).isDirectory()) walk(path); - else found.push(rel); - } - }; - walk(DOCS_ROOT); - return found; -} - -const FILES = contextRootPresent ? documentationFiles() : []; - -interface IndexRow { - /** 1-based line in `docs/INDEX.md`, so a failure names where to look. */ - readonly line: number; - /** Link target, decoded and relative to `docs/`. May name a file or a directory. */ - readonly target: string; -} - -const MARKDOWN_LINK = /\[[^\]]*\]\(([^)]+)\)/g; - -/** - * The document rows of `docs/INDEX.md` — the first cell of each table row. - * - * Only the first cell, because that is the column that claims to identify a - * document; a Digest cell may legitimately link out to a Notion page or a - * superseding source without claiming anything lives at that path. Cells are - * split on a bare `|`, which is exact for this file and would need revisiting - * only for an escaped `\|` or a pipe inside inline code. - */ -function indexRows(): IndexRow[] { - const rows: IndexRow[] = []; - const lines = readFileSync(join(DOCS_ROOT, INDEX_RELPATH), "utf8").split( - "\n", - ); - for (const [offset, line] of lines.entries()) { - const trimmed = line.trimStart(); - if (!trimmed.startsWith("|")) continue; - const firstCell = trimmed.split("|")[1] ?? ""; - for (const match of firstCell.matchAll(MARKDOWN_LINK)) { - const raw = match[1]!.trim(); - // `external`-status rows point at the canonical copy outside the repo, and - // a bare anchor points within this file. Neither makes a claim about disk. - if (/^https?:\/\//.test(raw) || raw.startsWith("#")) continue; - const path = raw.split("#")[0]!; - // One filename contains a space, so targets are percent-encoded in the - // markdown and must be decoded before they name anything on disk. - rows.push({ line: offset + 1, target: decodeURIComponent(path) }); - } - } - return rows; -} - -const ROWS = contextRootPresent ? indexRows() : []; - -/** - * Whether a row's target accounts for a file. A target naming a directory covers - * everything beneath it: the INDEX deliberately indexes some sets as a set — the - * thirteen resolved issue files, the baseline experiment's transcripts — because - * one digest describes them better than thirteen would. - */ -const covers = (target: string, file: string): boolean => { - const base = target.replace(/\/$/, ""); - return file === base || file.startsWith(`${base}/`); -}; - -describe.skipIf(!contextRootPresent)( - "every document is in the index, and the index is all documents", - () => { - test("the walk actually finds documents", () => { - // Without this, a `docs/` the walker cannot read makes the coverage check - // below iterate an empty list and pass vacuously — a silent exemption for - // the entire tree, which is worse than having no gate. - expect(FILES.length).toBeGreaterThan(0); - expect(ROWS.length).toBeGreaterThan(0); - }); - - test("every file under docs/ is covered by a row in docs/INDEX.md", () => { - for (const file of FILES) { - expect({ - file, - indexed: ROWS.some((row) => covers(row.target, file)), - }).toEqual({ - file, - indexed: true, - }); - } - }); - - test("every row in docs/INDEX.md points at something real", () => { - // A row standing for nothing is not tidiness: the index is what a reader - // consults instead of walking the tree, so a stale row is misinformation - // with the authority of a registry behind it. - for (const row of ROWS) { - const path = join(DOCS_ROOT, row.target.replace(/\/$/, "")); - const resolves = - existsSync(path) && - (statSync(path).isDirectory() - ? FILES.some((file) => covers(row.target, file)) - : true); - expect({ line: row.line, target: row.target, resolves }).toEqual({ - line: row.line, - target: row.target, - resolves: true, - }); - } - }); - }, -); - -test("relative links in context documentation point at existing files", () => { - for (const file of FILES) { - if ( - !file.endsWith(".md") || - LINK_CHECK_EXEMPT.has(file) || - LINK_CHECK_EXEMPT_PREFIXES.some((prefix) => file.startsWith(prefix)) - ) - continue; - - const sourcePath = join(DOCS_ROOT, file); - const lines = readFileSync(sourcePath, "utf8").split("\n"); - for (const [lineOffset, line] of lines.entries()) { - for (const match of line.matchAll(MARKDOWN_LINK)) { - const rawTarget = match[1]! - .trim() - .split(/\s+/, 1)[0]! - .replace(/^<|>$/g, ""); - if ( - rawTarget.startsWith("#") || - rawTarget.startsWith("/") || - /^(?:doc|file|https?|layer|mailto):/.test(rawTarget) - ) - continue; - - const target = decodeURIComponent(rawTarget.split("#", 1)[0]!); - if (!target) continue; - - expect({ - file, - line: lineOffset + 1, - target: rawTarget, - resolves: existsSync(resolve(dirname(sourcePath), target)), - }).toEqual({ - file, - line: lineOffset + 1, - target: rawTarget, - resolves: true, - }); - } - } - } -}); - -test("retired planning and history paths contain no documents", () => { - expect( - FILES.filter( - (file) => file.startsWith("planning/") || file.startsWith("history/"), - ), - ).toEqual([]); - expect(existsSync(join(DOCS_ROOT, "planning"))).toBe(false); - expect(existsSync(join(DOCS_ROOT, "history"))).toBe(false); -}); - -describe.skipIf(!contextRootPresent)( - "every agent protocol doc is reachable from AGENTS.md", - () => { - // `AGENTS.md` is the file an agent is given; a protocol it does not name is a - // protocol that will not be followed, however well written. The pointer form - // is established — the path in prose or backticks — so a substring check on - // the path is exactly as strict as the convention is. - const agentsText = readFileSync(join(REPO_ROOT, "AGENTS.md"), "utf8"); - const protocols = readdirSync(join(DOCS_ROOT, "agents")) - .filter((entry) => entry.endsWith(".md")) - .sort(); - - test("there are protocol docs to govern", () => { - expect(protocols.length).toBeGreaterThan(0); - }); - - test("AGENTS.md names each one by path", () => { - for (const protocol of protocols) { - const path = `docs/agents/${protocol}`; - expect({ path, namedInAgentsMd: agentsText.includes(path) }).toEqual({ - path, - namedInAgentsMd: true, - }); - } - }); - }, -); From 550eca926214e87995b4ebb535db31b435e4bf2c Mon Sep 17 00:00:00 2001 From: Lu Nelson Date: Thu, 27 Aug 2026 12:39:02 +0200 Subject: [PATCH 2/5] Define the bare Petrinaut Flue chat mission --- apps/brunch-agent/AGENTS.md | 12 ++- libs/@hashintel/brunch-agent/AGENTS.md | 4 +- libs/@hashintel/brunch-agent/MISSION.md | 124 ++++++++++++++++++++---- 3 files changed, 112 insertions(+), 28 deletions(-) diff --git a/apps/brunch-agent/AGENTS.md b/apps/brunch-agent/AGENTS.md index 90c05dde6d5..8f5c5dff4ed 100644 --- a/apps/brunch-agent/AGENTS.md +++ b/apps/brunch-agent/AGENTS.md @@ -1,9 +1,11 @@ # Brunch agent application This application belongs to the Brunch context rooted at -`../../libs/@hashintel/brunch-agent/`. Read that context's `AGENTS.md`, `CONTEXT.md`, and relevant -ADRs before changing this application. HASH root guidance takes precedence. +`../../libs/@hashintel/brunch-agent/`. Read that context's `AGENTS.md` and current `MISSION.md` +before changing this application. Consult `CONTEXT.md` or historical design documents only when a +concrete question requires them; ADRs and specs are hypotheses, not implementation obligations. +HASH root guidance takes precedence. -The application composes the Brunch packages, Flue runtime, HTTP routes, and local diagnostics. It -must remain independent of Petrinaut implementation packages; `apps/petrinaut-website` meets it -through the AI SDK/HTTP transport. +The application composes the Flue runtime, HTTP routes, and the Brunch packages required by the +current mission. It must remain independent of Petrinaut implementation packages; +`apps/petrinaut-website` meets it through the AI SDK/HTTP transport. diff --git a/libs/@hashintel/brunch-agent/AGENTS.md b/libs/@hashintel/brunch-agent/AGENTS.md index 69229bd8e01..bc8f6154669 100644 --- a/libs/@hashintel/brunch-agent/AGENTS.md +++ b/libs/@hashintel/brunch-agent/AGENTS.md @@ -20,8 +20,8 @@ from this file. ## Mission contract -When work starts on a branch, state these six things in the branch/PR description (no separate -document): +When work starts on a branch, state these six things in [`MISSION.md`](MISSION.md) and copy them +into the branch/PR description. Do not create additional planning or control documents. - **Imperative** — what must become true, and why now. - **Throughline** — the real entrypoint or boundary being changed. diff --git a/libs/@hashintel/brunch-agent/MISSION.md b/libs/@hashintel/brunch-agent/MISSION.md index 5d0fa489d28..c20e0aa040c 100644 --- a/libs/@hashintel/brunch-agent/MISSION.md +++ b/libs/@hashintel/brunch-agent/MISSION.md @@ -1,31 +1,113 @@ -# Mission +# Mission 1 — bare Petrinaut ↔ Flue chat -The current objective, its acceptance proof, and the stop conditions. This is the one mutable -"what now" record; a specific branch's mission contract lives on that branch. +## Imperative -## Objective +Prove the real Petrinaut demo can hold a durable, observable conversation with a plain Flue agent +before Brunch adds capture or elicitation semantics. This mission retires integration uncertainty; +it does not advance the intended harness design. -Construct and review-and-revise, in that order; cold-start construction must be possible. +## Throughline -## Acceptance proof +One interaction crosses this production path: -A human conducts a real construct elicitation through the production Brunch server and the -Petrinaut assistant panel; captures persist to a target document owned by a principal and survive -reload; completion accounting is human-readable; every turn records time per purpose. Then a -bounded review-and-revise pass: open an existing source-grounded model, trace one element to its -source utterance, correct it in a few turns, and see a provenance-preserving net delta. +`Petrinaut assistant panel → AI SDK /api/chat → Brunch-hosted plain Flue agent → model and server tool → AI SDK stream → Petrinaut client tool → correlated result → same Flue conversation` -## Stop or replan +Simplify the current implementation in place: -- A first question takes longer than the provisional target after the latency instrumentation - lands. -- Persistence needs a schema the harness must know. -- The panel needs Brunch-specific code inside `@hashintel/petrinaut`. -- An arc ends with only desk, simulated, or evaluation-side output and no production-path code - changed. +- mount one minimal plain-Flue chat agent in `apps/brunch-agent`; +- shrink `@hashintel/brunch-agent-transport-aisdk` to the Flue ↔ AI SDK wire seam it actually + exercises, with no dependency on Brunch core, bindings, or plugins; +- make `@apps/brunch-agent` consume no Brunch package except that adapter; +- remove the current SDCPN/Gherkin harness composition from the active chat path and delete or + replace tests that exist only to prove that superseded topology; +- keep Petrinaut's existing assistant panel and client-tool machinery unless the real throughline + exposes a missing seam; +- use Flue's canonical conversation as the only persisted session log. + +The voice dock is the narrow point where another input modality can submit into the same principal, +conversation, and response-stream contract. Mission 1 establishes and names that point; it does not +implement voice or introduce a voice-specific server route. + +## Proof + +From a clean checkout, a human can follow one documented start command or short command sequence and +observe all of the following through the real demo and service: + +1. A message from Petrinaut reaches the mounted Flue agent and streamed assistant text returns. +2. The panel visibly distinguishes pending/thinking or equivalent work-in-progress from completion. +3. One minimal server-side tool runs, its call/result are visible, and its result returns to the + model. +4. One existing, read-only Petrinaut client tool runs in the browser, its result is correlated to + the originating call, and the same Flue conversation resumes and responds. +5. Browser reload/reconnection reconstructs the conversation from Flue history rather than from a + second server-side transcript. +6. The configured Flue database preserves that conversation across the service restart behavior + claimed by the runbook. +7. A supported built-in Pi/Flue session API converts the persisted log into human-readable + transcript evidence, including user text, assistant text, and both tool interactions; no custom + shadow log or replacement event model is added. +8. KA's voice-mode work has one documented integration point and the minimum input/output contract + needed to join this conversation without owning a second history or transport. + +Prefer one production-path integration test plus a recorded human run over a broad replacement +suite. Unit tests should protect only parsing or correlation invariants that failed or proved easy +to regress. + +**Bonus, not completion-critical:** address the mounted agent with `@flue/sdk` from a script or test +using the same public conversation URL. Do not add a diagnostic protocol or second server for +generative testing. + +## Constraints + +- `@flue/runtime`, `@flue/sdk`, `@flue/react`, and `@flue/vite` are already pinned to npm's current + Flue 2.0 release (`2.0.3`). Follow its documented happy paths; do not perform an upgrade or a + broad Flue-conformance audit unless the registry changes or the throughline exposes drift. +- No dependency from the active app or adapter to Brunch core, binding-flue, plugin-gherkin, or + plugin-sdcpn. Do not copy their protocol types into a renamed abstraction. +- No capture, sweep, plugin schema, repertoire, IR, completion accounting, issue model, correction + workflow, or target-document persistence. +- No second conversation log. Flue history is authoritative; browser message persistence is a UI + cache only and must reconcile to the same conversation identity. +- Use one stable principal + conversation identity across chat, reload, client-tool follow-up, + transcript export, and the voice dock. Protect the mounted Flue route wherever it is reachable; + direct agent access must not bypass the same ownership rule. +- The client-tool proof should be read-only. Do not make editor mutation semantics part of this + mission. +- Update user-facing or runbook documentation only where the exercised behavior changes. Do not + document speculative follow-on architecture. + +## Fog-line + +Do not design past these questions before running the simplest path that can answer them: + +- Whether the adapter should project Flue's conversation stream directly or bridge Flue's + programmatic `dispatch`/`read` events into AI SDK chunks. +- The smallest supported way for an AI SDK client-tool result to settle a Flue tool call and resume + the same turn without Brunch ask/reply semantics. +- Which built-in Pi/Flue parser or serializer produces the required transcript evidence from the + persisted canonical records. +- Whether reload needs server reattachment, browser hydration, or both once one conversation id is + used consistently. +- The exact shape KA's in-progress voice mode can provide and consume at the dock. + +Resolve each at the real boundary, record the observed answer in code/tests/runbook, and then +re-evaluate. Do not turn the open questions into an adapter framework. + +## Stop or reorient + +Stop and surface the evidence before continuing if: + +- client-tool return requires importing Brunch ask/reply or capture semantics; +- the adapter begins defining a generalized harness event framework; +- persistence requires an application-owned duplicate of Flue conversation history; +- the voice dock requires Brunch to own provider-specific audio/session state; +- a passing test injects wiring absent from the real demo/service entrypoint; +- compatibility work expands beyond a concrete Flue 2.0 API used by this throughline; +- the server/client tool pair cannot be replayed into transcript evidence through supported APIs. ## Deferred -The harness-teaching layer (the plugin schema/repertoire machinery of ADR-0007/0008) is excluded -from the first post-reorientation branches; re-include it later in minimum-viable forms as a real -throughline demands. +Mission 2 may add the first Brunch-owned behavior only after this proof is complete: mechanically +sweep one explicit settled transcript range into durable, source-linked capture and prove idempotent +reapplication. Extraction quality, plugin/repertoire machinery, IR, completion, and review/revise +remain out of scope until separately earned. From c9fc0f54747c71e2483061ccf0dda319317e2a9c Mon Sep 17 00:00:00 2001 From: Lu Nelson Date: Thu, 27 Aug 2026 13:00:58 +0200 Subject: [PATCH 3/5] first pass on new guidance Signed-off-by: Lu Nelson --- libs/@hashintel/brunch-agent/AGENTS.md | 47 ++++++++++++++++++------- libs/@hashintel/brunch-agent/MISSION.md | 3 ++ 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/libs/@hashintel/brunch-agent/AGENTS.md b/libs/@hashintel/brunch-agent/AGENTS.md index bc8f6154669..d86e0757829 100644 --- a/libs/@hashintel/brunch-agent/AGENTS.md +++ b/libs/@hashintel/brunch-agent/AGENTS.md @@ -6,14 +6,18 @@ from this file. ## The three laws -1. **Dumbest real implementation first.** Cross the real production boundary end-to-end before - improving anything: use the real entrypoint and wiring, inline what can stay local, and pin - only the invariants and constraints the working path actually exposes. Then re-decide at the - new fog-line instead of running an inherited plan. +1. **Real throughline first, least mechanism.** Cross the real production boundary end-to-end + before improving anything: use the real entrypoint and wiring, prefer the platform and chosen + libraries to a custom mechanism, and inline what can stay local. Pin only the invariants and + constraints the working path actually exposes. Minimum applies to the mechanism, not the + contract: known consumers of this work must be able to rely on it without inventing missing + semantics. Then re-decide at the new fog-line instead of running an inherited plan. 2. **Deepen only under observed strain.** An intended design is a hypothesis, not a destination. - Admit the next piece of complexity when the current implementation strains under a present - requirement (duplication diverging, a boundary leaking, an invariant that will not hold - locally), and cut the design when the design itself is what is straining progress. + Anti-caricature: a pattern name retrieves relevant properties; it is not a blueprint. Restate + the local obligation without the name, then implement only what discharges it. Admit the next + piece of complexity when the current implementation strains under a present requirement + (duplication diverging, a boundary leaking, an invariant that will not hold locally), and cut + the design when the design itself is what is straining progress. 3. **A branch is a mission, not a ticket.** Every mission carries an imperative that guides and bounds its work; its evidence-gathering and decisions are judged against that imperative, not against a plan graph. @@ -25,9 +29,13 @@ into the branch/PR description. Do not create additional planning or control doc - **Imperative** — what must become true, and why now. - **Throughline** — the real entrypoint or boundary being changed. -- **Proof** — the observable evidence that would establish progress. +- **Proof** — the observable evidence that would establish progress, and the claim it does not + make. A path, a connected skeleton, and a discharged contract are different completions. - **Constraints** — the few already-earned truths that must stay true. -- **Fog-line** — what is unknown and must not be designed past. +- **Fog-line** — uncertainty that current evidence cannot yet decide between consequential + alternatives, and must not be designed past. Clarifying intent is not clearing terrain. Capture + unresolved flags here: why they matter, what they constrain, and what would re-enter them. + Running the path may lengthen this list; that is calibration, not regression. - **Stop or reorient** — evidence that invalidates or changes the route. ## Correctives @@ -38,9 +46,17 @@ into the branch/PR description. Do not create additional planning or control doc - A ticket is a projection; the mission is the authority. If the ticket stops serving the imperative, stop and surface the divergence instead of finishing the ticket. - When evidence changes the route, stop; do not finish the planned neighbourhood. -- When unsure, build the smallest real path that reveals more. - When things accumulate, subtract before you extend. - No imperative and proof means it is not a mission yet — do not start it. +- Censor noise; keep consequential doubt visible. +- Checking is proportional to consequence and reversibility. Within that budget, a commitment is + warranted when the premises it depends on are either observed at the real boundary or + explicitly accepted as risk. +- Low confidence must change the next move — build the smallest real path that reveals more, + inspect, choose the reversible option, or flag it — or go unsaid. +- At close, update the PR description: what each proof item established, the observed answer to + each fog-line question, and the flags that carry into the next mission. The PR description is + the only record that survives the squash. ## Retained facts @@ -59,8 +75,9 @@ into the branch/PR description. Do not create additional planning or control doc evaluation side, never inside interviewee or elicitor inputs. - **Posture:** prototype · stakes high — persisted capture data and merge gates must fail loudly, never corrupt silently · horizon: current milestone. -- **Flue design moments:** see - [`docs/reference/architecture/flue-routing.md`](docs/reference/architecture/flue-routing.md). +- **Flue:** when adding state, a loop, a route, or a test harness, consult + [`docs/reference/architecture/flue-routing.md`](docs/reference/architecture/flue-routing.md) + before inventing a parallel mechanism. ## Authorities vs obligations @@ -68,4 +85,8 @@ into the branch/PR description. Do not create additional planning or control doc [`docs/evidence/`](docs/evidence) are history and reference: prior design hypotheses and observed results. They are not marching orders. Re-earn any design you build to; an implemented decision is evidence, unimplemented design is a hypothesis. A branch may depart from a recorded decision by -noting the divergence in its commit. +noting the divergence in its commit. Provenance is not warrant: a statement is evidence of what +was said, not automatically of the terrain. This holds equally for specs, ADRs, the user's +statements, and the model's own recommendations. Objectives, trade-off preferences, and policy +settle by conversation with their owner; current-state claims, causal claims, and feasibility +settle only at the real boundary. diff --git a/libs/@hashintel/brunch-agent/MISSION.md b/libs/@hashintel/brunch-agent/MISSION.md index c20e0aa040c..986c59ec9cd 100644 --- a/libs/@hashintel/brunch-agent/MISSION.md +++ b/libs/@hashintel/brunch-agent/MISSION.md @@ -30,6 +30,9 @@ implement voice or introduce a voice-specific server route. ## Proof +This proof establishes that the production path exists and is durable. It does not discharge the +elicitation-harness contract. + From a clean checkout, a human can follow one documented start command or short command sequence and observe all of the following through the real demo and service: From ef74cf483990568c922d10cb9bc90e33782a6dfd Mon Sep 17 00:00:00 2001 From: Lu Nelson Date: Thu, 27 Aug 2026 14:11:06 +0200 Subject: [PATCH 4/5] Restore focused Linear and GitHub writing guidance --- libs/@hashintel/brunch-agent/AGENTS.md | 6 +- .../brunch-agent/docs/agents/issue-writing.md | 103 ++++++++++++++++++ 2 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 libs/@hashintel/brunch-agent/docs/agents/issue-writing.md diff --git a/libs/@hashintel/brunch-agent/AGENTS.md b/libs/@hashintel/brunch-agent/AGENTS.md index d86e0757829..21839842ae4 100644 --- a/libs/@hashintel/brunch-agent/AGENTS.md +++ b/libs/@hashintel/brunch-agent/AGENTS.md @@ -67,8 +67,10 @@ into the branch/PR description. Do not create additional planning or control doc `create`/`submit`/`restack`/`sync`/`checkout`. Never `gh stack`. Before switching the branch of a shared worktree, check for in-flight work; use a separate worktree rather than stashing, resetting, or cleaning anything you did not create. -- **Linear:** team `FE`, project `brunch-agent`. Reading is fine; get explicit approval before - any write (create, edit, comment, state change). +- **Linear and GitHub records:** follow + [`docs/agents/issue-writing.md`](docs/agents/issue-writing.md) whenever creating or editing an + issue, pull request, or comment. Linear uses team `FE`, project `brunch-agent`; reading is fine, + but get explicit approval before any Linear write (create, edit, comment, state change). - **Topology gates** (enforced by tests): plugins never import `@hashintel/brunch-agent/prompts`; transport packages never depend on a binding; bindings depend inward on core; plugins depend only on core. Evaluation answer keys stay on the diff --git a/libs/@hashintel/brunch-agent/docs/agents/issue-writing.md b/libs/@hashintel/brunch-agent/docs/agents/issue-writing.md new file mode 100644 index 00000000000..e7b7c5f8066 --- /dev/null +++ b/libs/@hashintel/brunch-agent/docs/agents/issue-writing.md @@ -0,0 +1,103 @@ +# Linear and GitHub writing + +Apply this when creating or editing a Linear issue, a GitHub issue or pull request, or a comment on +either tracker. It governs only how the record is written. It does not invoke issue decomposition, +Wayfinding, steering, branch creation, or any other workflow protocol. + +The tracker record communicates the mission; it does not become the mission's authority. Do not +turn a branch mission into a speculative issue graph. + +## Two layers + +Write for two readers: + +1. **Visible summary** — the outcome, why it matters now, what this record establishes, material + status, and consequential uncertainty. Use short, plain technical prose. Preserve causal and + conditional relationships rather than replacing them with labeled fragments. +2. **`🏗️ Agent notes`** — implementation detail and mutable execution state: the full mission + contract, constraints, exact checks, investigation notes, stack mechanics, and links to detailed + evidence. This layer is optional when there is nothing useful to hide. + +A title names the task, outcome, observable problem, or open decision. It should remain true if an +uncommitted implementation approach changes. Once changing a named mechanism is itself the agreed +task, naming that mechanism is accurate rather than overly technical. + +The visible summary is human-owned. Before editing an existing record, fetch its current raw body, +preserve intervening edits, and make the smallest material change. Move detail into Agent notes +without deleting it. Do not regenerate a human summary from a local draft or from the notes below +it. + +## Collapsed sections + +For Linear, copy this wrapper exactly; include the spaces after `+++` and the blank lines: + +```markdown ++++ 🏗️ Agent notes + +Working detail. + ++++ +``` + +For GitHub, use native details: + +```html +
+🏗️ Agent notes + +Working detail. + +
+``` + +The label is canonical. Copy it rather than retyping it: the emoji contains a variation selector, +so visually identical text can differ at the byte level. + +## Linear + +For a new agent-authored issue, put one or two short context paragraphs above Agent notes. A reader +should be able to recover the current state, its consequence, the intended outcome, and any +material uncertainty without expanding the section. A teammate-authored issue keeps its author's +shape unless that person delegates a rewrite. + +Agent notes may hold execution detail, but current mission authority remains `MISSION.md` and the +branch/PR description. Link to an authoritative fact rather than copying it into several issues. +Use comments only for events worth notifying people about: a decision, changed confidence, changed +scope, a new risk, or resolution. Edit current state into the body; do not post progress narration. + +The Linear approval gate, team, and project in `AGENTS.md` apply to every write. Fetch the raw body +immediately before an approved edit; rendered CLI output may contain headers or normalized Markdown +that are not part of the stored description. + +## GitHub pull requests + +Keep `.github/pull_request_template.md` and fill it rather than replacing it. + +- **Purpose** stays visible: state the mission's imperative, the production throughline, what the + proof establishes, and the claim it does not make. +- **What does this change?** starts with a short reviewer-facing description. Put the full mission + contract and implementation record in the GitHub Agent notes wrapper beneath it. +- **Known issues**, **tests**, **how to test**, and **demo** stay visible because reviewers need + them to judge the proof. Do not hide a consequential flag in Agent notes. +- Preserve and answer the template's checklists honestly; delete only the alternatives its comments + instruct the author to delete. + +At mission close, update the PR description with the observed result for every proof item, the +answer learned at each fog-line, and the flags carried forward. The PR description is the durable +record after squash; routine commit-by-commit narration is not. + +## Comments + +A comment appears in inboxes and feeds. Lead with the decision or material change in one or two +sentences. Add Agent notes only when supporting detail is necessary. State goes in the body; events +go in comments. A resolution comment may be longer, but its verdict remains visible before any +collapsed detail. + +## Before writing + +- The title states the real task or outcome, not an unearned mechanism. +- The visible prose explains enough to judge the change without expanding Agent notes. +- Technical working state is contained rather than deleted. +- Existing human-owned prose and intervening edits are preserved. +- Uncertainty is stated as uncertainty. +- The issue or PR remains a projection of the mission, not a replacement plan. From 32e423498f834094bbf7d0f5a65c6035c7f9f944 Mon Sep 17 00:00:00 2001 From: Lu Nelson Date: Thu, 27 Aug 2026 14:20:10 +0200 Subject: [PATCH 5/5] Restore focused tracker and Graphite conventions --- libs/@hashintel/brunch-agent/AGENTS.md | 17 +++-- .../brunch-agent/docs/agents/git-workflow.md | 51 +++++++++++++ .../brunch-agent/docs/agents/issue-tracker.md | 74 +++++++++++++++++++ 3 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 libs/@hashintel/brunch-agent/docs/agents/git-workflow.md create mode 100644 libs/@hashintel/brunch-agent/docs/agents/issue-tracker.md diff --git a/libs/@hashintel/brunch-agent/AGENTS.md b/libs/@hashintel/brunch-agent/AGENTS.md index 21839842ae4..a8dffb456e4 100644 --- a/libs/@hashintel/brunch-agent/AGENTS.md +++ b/libs/@hashintel/brunch-agent/AGENTS.md @@ -63,14 +63,17 @@ into the branch/PR description. Do not create additional planning or control doc - **Toolchain:** format TS/JSON with root `oxfmt`; lint via `lint:eslint` (Oxlint) and `lint:tsc` (`tsgo --noEmit`); unit tests via `vitest run`; build with Vite 8. Run tasks through the HASH root Yarn/Turbo workspace — add no `package.json` or lockfile here. -- **Git vs Graphite:** plain `git` for status/diff/add/commit; `gt` for - `create`/`submit`/`restack`/`sync`/`checkout`. Never `gh stack`. Before switching the branch of - a shared worktree, check for in-flight work; use a separate worktree rather than stashing, - resetting, or cleaning anything you did not create. -- **Linear and GitHub records:** follow +- **Issue, branch, and PR lifecycle:** one Linear issue = one Graphite branch = one GitHub PR; the + branch mission remains the execution authority. Follow + [`docs/agents/git-workflow.md`](docs/agents/git-workflow.md) when creating, restacking, or + submitting a branch or connecting it to an issue or PR. +- **Linear project posture:** Brunch issues live on team `FE`, project `brunch-agent`, whose mixed + inherited issue history is evidence and inbox rather than an authoritative plan. Follow + [`docs/agents/issue-tracker.md`](docs/agents/issue-tracker.md) before creating, reusing, relating, + or changing an issue. Reading is fine; get explicit approval before every Linear write. +- **Linear and GitHub writing:** follow [`docs/agents/issue-writing.md`](docs/agents/issue-writing.md) whenever creating or editing an - issue, pull request, or comment. Linear uses team `FE`, project `brunch-agent`; reading is fine, - but get explicit approval before any Linear write (create, edit, comment, state change). + issue, pull request, or comment. - **Topology gates** (enforced by tests): plugins never import `@hashintel/brunch-agent/prompts`; transport packages never depend on a binding; bindings depend inward on core; plugins depend only on core. Evaluation answer keys stay on the diff --git a/libs/@hashintel/brunch-agent/docs/agents/git-workflow.md b/libs/@hashintel/brunch-agent/docs/agents/git-workflow.md new file mode 100644 index 00000000000..ceff66c46b8 --- /dev/null +++ b/libs/@hashintel/brunch-agent/docs/agents/git-workflow.md @@ -0,0 +1,51 @@ +# Git workflow: one issue, one branch, one pull request + +Brunch branches are managed with Graphite. The submission unit is exactly one Linear issue, one +stacked branch, and one GitHub pull request. This is an identity and visibility rule, not a ticket +decomposition method: the branch is still governed by its mission. + +Work discovered while executing the mission stays on the branch when it serves the same imperative +and proof. Create another issue and branch only when the work has an independently meaningful +mission and should be reviewed or landed independently. Do not split work merely to preserve an +inherited issue graph. + +## Naming and linking + +For new work: + +- **Branch:** `{prefix}/{issue-id}-{keywords}`, for example + `ln/fe-1510-prove-petrinaut-flue-chat`. +- **PR title:** `{ISSUE-ID}: {Linear issue title in sentence case}`. +- **PR body:** link the Linear issue and follow [`issue-writing.md`](issue-writing.md), including + the repository PR template and the visible-summary / `🏗️ Agent notes` split. + +If an active branch predates its issue, create and link the issue before submission. Do not rename a +checked-out or stacked branch solely for cosmetic compliance when doing so would endanger in-flight +work; make the relationship explicit in the PR and follow the naming rule on subsequent branches. + +## Git and Graphite boundary + +Use plain `git` for local reads, staging, and commits: `status`, `diff`, `log`, `add`, and `commit`. +Use `gt` for stack-aware operations: `create`, `checkout`, `restack`, `continue`, `abort`, `submit`, +and `sync`. Raw branch creation or rebasing bypasses Graphite's parent metadata. Do not use +`gh stack` in `hashintel/hash`. + +The worktree is shared infrastructure. Before switching or restacking, inspect every involved +worktree for uncommitted or in-flight work. Never stash, reset, clean, or relocate another tenant's +changes to make a stack operation proceed. + +## Lifecycle + +1. State the mission in `MISSION.md`. +2. After explicit approval, create its Linear issue in the `brunch-agent` project and assign the + accountable human. +3. Create the Graphite branch from the intended parent, or explicitly link a pre-existing branch. +4. Commit the branch's work and proof without creating issues for incidental implementation steps. +5. Fill the GitHub PR template. The visible summary states what the mission establishes and does + not establish; Agent notes carry the full execution record. +6. Submit with `gt submit` and verify that the Linear issue, branch, and PR link to one another. +7. At close, update the PR with proof results, fog-line answers, and carried flags. Update Linear + status or comments only with explicit approval. + +Trunk is `main`. A stacked child does not inherit its parent's issue: every submitted child has its +own mission, Linear issue, and PR. diff --git a/libs/@hashintel/brunch-agent/docs/agents/issue-tracker.md b/libs/@hashintel/brunch-agent/docs/agents/issue-tracker.md new file mode 100644 index 00000000000..86ef41a9838 --- /dev/null +++ b/libs/@hashintel/brunch-agent/docs/agents/issue-tracker.md @@ -0,0 +1,74 @@ +# Issue tracker: Linear + +Brunch work is tracked on Linear team `FE`, project `brunch-agent`. Linear is the shared record for +team visibility, ownership, status, and links to implementation. GitHub pull requests are the review +and landing record. The branch mission remains the authority for execution. + +This file governs tracker location and posture only. [`issue-writing.md`](issue-writing.md) governs +how issue and PR prose is presented; [`git-workflow.md`](git-workflow.md) governs the one-to-one +issue, branch, and PR lifecycle. Neither invokes a planning or decomposition protocol. + +## Project posture + +The project contains records from several regimes: product-manager requests, issues written by the +driver or agents, a completed imported planning archive, and open work generated by the former +planning system. Treat that mixed history as **inbox and evidence**, not as one coherent active +plan. + +- **Product-manager issues express stakeholder intent.** Preserve their wording and authorship. + They establish what was requested, not that a proposed route is feasible or current. Relate a + mission issue to them when it advances, narrows, tests, or contradicts the request; do not rewrite, + close, reparent, or absorb them without their owner's direction. +- **Former planning issues are hypotheses.** Their state, parentage, labels, blockers, and apparent + specificity do not make them current obligations. Reuse one only when its actual outcome matches + the present mission; otherwise leave it intact and link the new issue with a plain account of the + relationship. +- **Completed issues remain history.** Do not reopen or retrofit them to make the current story look + continuous. +- **No bulk reconciliation.** Do not clean, relabel, cancel, reparent, or rewrite the inherited + project as housekeeping. Touch an existing record when current work has produced a concrete + disposition and the authorized owner wants that disposition recorded. + +Before creating an issue, search the entire `brunch-agent` project, including issues by other +creators and in non-active states. If nearby work exists, decide explicitly whether the mission +continues it, supersedes part of it, tests it, or is merely related. Avoid silent duplication, but +do not force a new mission under an obsolete issue graph for tidiness. + +Parent and blocker relations are optional facts. Add them only when they describe a current +reporting relationship or a dependency that cannot be crossed independently. They are not required +to make a root issue legitimate and must not be used to reconstruct a speculative plan. + +## Operations + +Reading Linear is allowed. Every create, edit, comment, relation, assignment, state change, or +project mutation requires explicit approval for that named operation. + +For an approved new issue: + +- use team `FE`, project `brunch-agent`, and assign the accountable human; +- use `linear issue create --team FE --project brunch-agent --assignee self`; +- pass multiline Markdown through `--description-file`; +- verify the stored title, description, project, assignee, and any approved relations after create; +- link the eventual GitHub PR, manually or through Linear's GitHub integration. + +For an approved edit, fetch the raw description immediately before writing and preserve intervening +human edits. `linear issue view` is suitable for reading but not as an edit source because its +rendered output includes fields outside the stored description. Fetch raw Markdown with: + +```bash +linear api --variable id=FE-XXXX <<'GRAPHQL' | jq -r '.data.issue.description' +query($id: String!) { issue(id: $id) { description } } +GRAPHQL +``` + +Linear normalizes some Markdown on save. Verify semantic content rather than trying to restore +byte-level formatting. Use full Linear issue URLs in bodies and comments when a clickable relation +matters. + +## Read-only audit posture + +A project audit asks what exists before deciding what to use. Inspect all project issues rather +than only `linear issue mine`: creator, assignee, state, parent, title, and description are the +minimum fields needed to distinguish stakeholder requests, historical plan artifacts, and active +missions. The audit itself changes nothing. Any resulting cleanup proposal is a separate, +approval-gated decision.