Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
ecb0f1a
Initialize repo: agent config, wayfinder map, elicitation-kernel plan…
lunelson Aug 6, 2026
c07b959
Resolve Questioning-UX contract (issue 05); harden shell vocabulary
lunelson Aug 7, 2026
ebe946e
Resolve walking skeleton: Flue question round-trip (issue 10)
lunelson Aug 7, 2026
e377e8d
Map: add exploded-view diagnostic harness to Not yet specified
lunelson Aug 7, 2026
fa4f28d
Ticket 10: record ratified questionnaire reading (single multi-step a…
lunelson Aug 7, 2026
4f10557
Resolve capture-sweep logic-prototype (issue 11); graduate multi-sess…
lunelson Aug 7, 2026
8ea5e9e
Resolve shipping-shape (issue 06); add Binding to glossary
lunelson Aug 7, 2026
1272426
Ticket 06: note prototype branches as implementation seeds for core/f…
lunelson Aug 7, 2026
584737b
Resolve multi-session durable-target (issue 12); flip persistence hyp…
lunelson Aug 10, 2026
ea28697
Pre-assembly prep: consistency pre-pass, second-target rename (plugin…
lunelson Aug 10, 2026
b998519
Claim ticket 13 (sweep-seam walking skeleton)
lunelson Aug 10, 2026
e59a0bf
Ticket 13: walking skeleton built, provisional verdict posted β€” await…
lunelson Aug 10, 2026
8fd0faf
Ticket 13: record HITL reaction #1 and the harness-resolved anchoring…
lunelson Aug 10, 2026
8575f22
Resolve sweep-seam walking skeleton (ticket 13); capability list amen…
lunelson Aug 10, 2026
9a4d3fd
Resolve ticket 08: spec assembled (spec.md) β€” map complete
lunelson Aug 10, 2026
b7918d4
Spec review round 1 (HITL, tuicr): seven comments folded in
lunelson Aug 10, 2026
7414766
FE-1374: Assemble the spec (#1)
lunelson Aug 19, 2026
2e58d35
FE-1362: Decide the September demo architecture (#2)
TimDiekmann Aug 20, 2026
427a387
FE-1363: Choose the demo use case and modelling criteria (#3)
TimDiekmann Aug 20, 2026
1b43e46
FE-1388: Create the Bun workspace and enforce dependency boundaries (#4)
TimDiekmann Aug 20, 2026
996f0cf
FE-1364: Define the process-model elicitation representation (#5)
TimDiekmann Aug 20, 2026
a34663a
FE-1361: Measure the one-shot AI elicitation baseline (#6)
TimDiekmann Aug 20, 2026
9c3d525
FE-1399: Fix verified silent failures in CI and the dev app (#7)
TimDiekmann Aug 20, 2026
8771be4
FE-1397: Validate the generic IR against worked plugin payloads (#8)
TimDiekmann Aug 20, 2026
0ed47a8
FE-1400: Strengthen verification, dev storage, and the baseline runne…
TimDiekmann Aug 20, 2026
c81686d
FE-1389: Implement the first suspended free-text question (#10)
TimDiekmann Aug 20, 2026
bb56fab
FE-1390: Implement capture history and local persistence (#11)
TimDiekmann Aug 20, 2026
5951512
FE-1401: Resolve the stack legibility follow-ups (#12)
TimDiekmann Aug 20, 2026
72b74d3
FE-1419: Align capture-store rules and verification claims (#13)
TimDiekmann Aug 20, 2026
85e6ec9
FE-1424: Complete the documentation protocol (#14)
TimDiekmann Aug 20, 2026
7d6f0e7
FE-1405: Draft and test the CPS payload schemas (#15)
TimDiekmann Aug 20, 2026
06c8b09
FE-1422: Move the portable ask protocol into core (#16)
TimDiekmann Aug 20, 2026
9148daa
FE-1391: Resolve evidence quotes to durable conversation entries (#17)
TimDiekmann Aug 20, 2026
d4596f0
FE-1392: Capture settled conversation statements safely (#18)
TimDiekmann Aug 20, 2026
02d67c4
FE-1432: Resolve the stack's open review threads (#19)
TimDiekmann Aug 20, 2026
a99c1a3
FE-1433: Deliver the remote Petrinaut elicitor integration (#20)
TimDiekmann Aug 20, 2026
eb6e139
FE-1434: Test whether Flue resumes batched client-tool results (#21)
TimDiekmann Aug 20, 2026
25e2dee
FE-1435: Test whether the elicitor stream drives Petrinaut’s chat pan…
TimDiekmann Aug 20, 2026
5cb5410
FE-1436: Connect the elicitor to Petrinaut’s real chat panel (#24)
TimDiekmann Aug 20, 2026
c013178
FE-1451: Keep issues, comments, and PRs easy to scan (#23)
TimDiekmann Aug 20, 2026
8e2dcd6
FE-1449: Prove a structured brunch question suspends and resumes in P…
TimDiekmann Aug 20, 2026
0ce4d6e
FE-1464: Close the final stack review findings before repository hand…
TimDiekmann Aug 20, 2026
3c7a00e
FE-1437: Prepare the standalone authority cutover (#28)
lunelson Aug 20, 2026
67c3352
Format imported Brunch files for HASH
lunelson Aug 21, 2026
6dcd56c
Move Brunch implementation to its HASH context paths
lunelson Aug 21, 2026
ca3cdc7
Assimilate Brunch into native HASH workspaces
lunelson Aug 21, 2026
9fdc3a6
Complete Brunch lifecycle wiring
lunelson Aug 21, 2026
00aaaa3
Fix Brunch documentation code fences
lunelson Aug 21, 2026
4b8b3f1
Register the Brunch Actual-mode fixture with Turbo
lunelson Aug 21, 2026
9180e43
Complete the Brunch elicitation round trip in Petrinaut
lunelson Aug 21, 2026
6f04c47
Preserve interactive tool contract types
lunelson Aug 21, 2026
9e29311
Settle Brunch docs and defects after the authority cutover
lunelson Aug 21, 2026
8d2b2be
Record the FE-1440 trim decision in coordination
lunelson Aug 21, 2026
312f34d
Route PR descriptions through the repository template
lunelson Aug 21, 2026
0210943
changeset for petrinaut
lunelson Aug 21, 2026
df45941
Switch the Brunch stacking convention to Graphite
lunelson Aug 21, 2026
a8f9229
Run Brunch architecture tests in CI's pruned checkout
lunelson Aug 21, 2026
5277382
Drop the FE-1357 proposal snapshot that blocked ticket merges
lunelson Aug 21, 2026
c466a13
Pin bedrock-sdk's nested Anthropic SDK to the workspace version
lunelson Aug 21, 2026
92b1f90
Copy the Brunch context root into CI's pruned checkout
lunelson Aug 21, 2026
3fd48d1
Exclude the Brunch context docs from formatting and markdown lint
lunelson Aug 21, 2026
aa3c92b
Add license files to the Brunch workspaces
lunelson Aug 21, 2026
80c8ddf
Guard host interactive-tool input parse on render
lunelson Aug 24, 2026
51b50c4
Pin the local Brunch and Petrinaut listen addresses
lunelson Aug 24, 2026
27fa5c5
Fire Brunch prune extras only for a core test job
lunelson Aug 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/seven-poems-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashintel/petrinaut": patch
---

Add an interactive-tool extension point to the AI assistant panel: hosts can register app-level tools whose calls render as interactive widgets in the conversation, including tools that suspend the turn until the user responds.
76 changes: 74 additions & 2 deletions .github/actions/prune-repository/prune.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import argparse
import json
import shutil
import subprocess
from collections.abc import Iterable
from glob import glob
Expand All @@ -18,7 +19,8 @@
# ---------------------------------------------------------------------------

# If any of these packages appear in the dependency closure, add the
# corresponding extra packages to the scope.
# corresponding extra packages to the scope. Triggers use prefix matching
# so a family root can pull its children (e.g. darwin-kperf).
EXTRA_DEPENDENCIES: dict[str, list[str]] = {
# Cyclic: hashql crates need compiletest
"@rust/hashql-ast": ["@rust/hashql-compiletest"],
Expand All @@ -38,6 +40,27 @@
"@rust/hash-graph-types": ["@rust/hash-graph-test-data"],
}

# Extras that must not fire on a transitive or prefix match. Brunch core's
# architecture tests need the app and context root, but a job whose requested
# scope is only a sibling or a consumer of core must not pull that fixture.
REQUESTED_DEPENDENCIES: dict[str, list[str]] = {
"@hashintel/brunch-agent": ["@apps/brunch-agent"],
Comment thread
lunelson marked this conversation as resolved.
}

# Non-workspace paths required by packages in the *requested* scope.
# `turbo prune` copies workspace directories and root manifests only.
REQUESTED_PATHS: dict[str, list[str]] = {
# The Brunch context root is deliberately not a workspace, but the
# architecture tests in packages/core read its docs, scripts, and agent
# contract files
"@hashintel/brunch-agent": [
"libs/@hashintel/brunch-agent/AGENTS.md",
"libs/@hashintel/brunch-agent/CONTEXT.md",
"libs/@hashintel/brunch-agent/docs",
"libs/@hashintel/brunch-agent/scripts",
],
}

TURBO_QUERY = """
query {
packages {
Expand Down Expand Up @@ -73,6 +96,31 @@ def turbo_dependency_map() -> dict[str, frozenset[str]]:
return dep_map


def extras_for_requested(requested: Iterable[str]) -> frozenset[str]:
"""Return extras implied by the job's requested scopes only.

Exact identity: a name that is a prefix of its siblings must not match them.
"""

names = set(requested)
extras: set[str] = set()
for trigger, additions in REQUESTED_DEPENDENCIES.items():
if trigger in names:
extras.update(additions)
return frozenset(extras)


def extra_paths_for_requested(requested: Iterable[str]) -> list[str]:
"""Return non-workspace paths implied by the job's requested scopes only."""

names = set(requested)
paths: list[str] = []
for trigger, trigger_paths in REQUESTED_PATHS.items():
if trigger in names:
paths.extend(trigger_paths)
return paths


def expand_scopes(dependencies: Iterable[str]) -> frozenset[str]:
"""Return extra scopes implied by the dependency names.

Expand Down Expand Up @@ -121,6 +169,29 @@ def turbo_prune(scopes: Iterable[str], *, dry_run: bool = False) -> None:
subprocess.run(args, check=True)


def copy_extra_paths(scopes: Iterable[str], *, dry_run: bool = False) -> None:
"""Copy non-workspace paths that `turbo prune` cannot include."""

for path in extra_paths_for_requested(scopes):
source = Path(path)
if not source.exists():
msg = f"REQUESTED_PATHS names {source}, which does not exist"
raise FileNotFoundError(msg)

destination = Path("out") / source

if dry_run:
print(f"[dry-run] Would copy: {source} -> {destination}")
continue

print(f"Copying extra path: {source} -> {destination}")
if source.is_dir():
shutil.copytree(source, destination, dirs_exist_ok=True)
else:
destination.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(source, destination)


def resolve_workspace_members() -> list[Path]:
"""Read workspace members from Cargo.toml and resolve globs to Cargo.toml paths."""

Expand Down Expand Up @@ -192,8 +263,9 @@ def main(argv: list[str] | None = None) -> None:
}

dependencies = turbo_dependency_map()
scopes = fixpoint_expand(initial, dependencies)
scopes = fixpoint_expand(initial | extras_for_requested(initial), dependencies)
turbo_prune(scopes, dry_run=args.dry_run)
copy_extra_paths(initial, dry_run=args.dry_run)
stub_missing_members(dry_run=args.dry_run)


Expand Down
66 changes: 66 additions & 0 deletions .github/actions/prune-repository/prune_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
"""Hermetic oracles for prune extra-scope rules. Does not run turbo prune."""

from __future__ import annotations

import unittest

from prune import (
expand_scopes,
extra_paths_for_requested,
extras_for_requested,
fixpoint_expand,
)

CORE = "@hashintel/brunch-agent"
TRANSPORT = "@hashintel/brunch-agent-transport-aisdk"
APP = "@apps/brunch-agent"
WEBSITE = "@apps/petrinaut-website"


class BrunchRequestedExtras(unittest.TestCase):
def test_core_job_adds_the_app_and_context_paths(self) -> None:
self.assertEqual(extras_for_requested({CORE}), frozenset({APP}))
self.assertIn(
APP,
fixpoint_expand(
{CORE} | extras_for_requested({CORE}),
{CORE: frozenset(), APP: frozenset({CORE})},
),
)
self.assertEqual(
extra_paths_for_requested({CORE}),
[
"libs/@hashintel/brunch-agent/AGENTS.md",
"libs/@hashintel/brunch-agent/CONTEXT.md",
"libs/@hashintel/brunch-agent/docs",
"libs/@hashintel/brunch-agent/scripts",
],
)

def test_sibling_or_website_job_does_not_add_brunch_extras(self) -> None:
self.assertEqual(extras_for_requested({TRANSPORT}), frozenset())
self.assertEqual(extras_for_requested({WEBSITE}), frozenset())
self.assertEqual(extra_paths_for_requested({TRANSPORT}), [])
self.assertEqual(extra_paths_for_requested({WEBSITE}), [])

def test_transitive_core_in_the_closure_does_not_add_the_app(self) -> None:
dependencies = {
WEBSITE: frozenset({TRANSPORT}),
TRANSPORT: frozenset({CORE}),
CORE: frozenset(),
}
expanded = fixpoint_expand({WEBSITE}, dependencies)
self.assertNotIn(APP, expanded)
self.assertEqual(extras_for_requested({WEBSITE}), frozenset())


class DarwinPrefix(unittest.TestCase):
def test_child_crate_still_triggers_the_prefix_family(self) -> None:
extras = expand_scopes({"@rust/darwin-kperf-sys"})
self.assertIn("@rust/darwin-kperf-sys", extras)
self.assertIn("@rust/darwin-kperf-events", extras)


if __name__ == "__main__":
unittest.main()
3 changes: 2 additions & 1 deletion .markdownlint-cli2.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"**/_ai/**",
"**/.cursor/plans/**",
"libs/@hashintel/ds-components/**",
"libs/@hashintel/ds-helpers/**"
"libs/@hashintel/ds-helpers/**",
"libs/@hashintel/brunch-agent/docs/**"
]
}
2 changes: 2 additions & 0 deletions apps/brunch-agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.data-wipe-me/
.flue/
9 changes: 9 additions & 0 deletions apps/brunch-agent/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# 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.

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.
1 change: 1 addition & 0 deletions apps/brunch-agent/CLAUDE.md
Loading
Loading