Skip to content

Add a worktree-proximity reference application #104

Closed

Description

@ScriptedAlchemy

Summary

Add an examples/ application that proves Agent Bundle can support custom
request hooks, context providers, cross-process topology state, semantic event
routes, RSC guidance, and directed notices without baking collision logic or a
daemon into framework core.

This is intentionally a demanding application example, not a request for
useWorktree, topology inference, dependency-overlap analysis, or collision
policy in framework core.

Scenario

One root task has two child agents in separate Git worktrees. Each begins
working on files whose dependency or path sets overlap. Application code—not
the framework—detects proximity and warns both actors through the delivery
routes their hosts support.

Example structure

examples/worktree-proximity/
  agent-bundle.config.ts
  src/
    providers/
      git-worktree.ts
      agent-topology.ts
    state.ts
    events/
      session/start.tsx
      agent/start.tsx
      tool/before.tsx
      tool/after.tsx
      stop.tsx
    domain/
      proximity.ts
    mcp/
      coordinator/tools/status.tsx
  tests/

The example authors custom APIs from framework primitives:

export const worktree = async (): Promise<WorktreeContext> =>
  (await agent()).providers.gitWorktree;

export const useWorktree = (): WorktreeContext =>
  useAgent().providers.gitWorktree;

The proximity evaluator remains ordinary application code:

export default async function BeforeTool() {
  const { actor, event, providers, notices } = await agent();
  const conflicts = await findProximity(
    providers.agentTopology.snapshot,
    providers.gitWorktree,
    event,
  );

  await Promise.all(conflicts.map((conflict) =>
    notices.publish({
      recipient: { actorId: conflict.actorId },
      content: <Agent.Warning>{conflict.summary}</Agent.Warning>,
    }),
  ));

  return conflicts.length === 0
    ? null
    : <Agent.Warning>{conflicts[0].summary}</Agent.Warning>;
}

Evidence boundary

The deterministic suite uses generated host adapters, two real child hook
processes, separate Git worktrees, and one durable local state driver. It is an
artifact/contract integration test, not proof that an external commercial host
actually dispatched the events.

Optional native smoke runs remain separately authorized and evidence-labelled.

Required journeys

  1. Observe a root actor and two child actors with explicit parent provenance.
  2. Associate each actor with a distinct worktree and current activity.
  3. Record non-overlapping work and emit no warning.
  4. Record overlapping path/dependency intent and warn the current actor.
  5. Publish a notice for the other actor.
  6. Deliver that pending notice on the other actor's next event when no native
    directed-message API exists.
  7. Deduplicate repeated native events.
  8. Mark parent identity unavailable for a fixture whose host does not expose it
    and refuse to fabricate a topology edge.
  9. Restart all hook processes and retain topology/notices through durable
    storage.

Acceptance criteria

  • The example contains no framework-private imports or handwritten host JSON.
  • Custom worktree() and useWorktree() APIs are implemented solely through
    the public context-provider contract.
  • Two independent processes share exact state revisions without a daemon.
  • Collision logic is isolated in the example domain module.
  • Current and remote-recipient warnings use the real Agent Document and notice
    projectors.
  • Unsupported identity/delivery states are visible and tested.
  • The scaffold documents the external-driver boundary. It claims external
    integration only if a real adapter is connected and passes the state-driver
    conformance suite; a disconnected example is not presented as integrated.

Design references

Stack position

Full meta-framework stack

Activity

  1. added
    enhancementNew feature or request
    meta-frameworkAgent Bundle compiler-coupled meta-framework
    runtimeRuntime context, state, rendering, or execution
    host-integrationAgent host capabilities, projection, discovery, and lifecycle
    testingFramework test harnesses and integration evidence
    on Aug 31, 2026
  2. ScriptedAlchemy commented on Sep 2, 2026

    @ScriptedAlchemy
    OwnerAuthor

    Scope proposal against current main (a9d5c0bf1, post #178–#245)

    Building this now as the Wave-6 composition finale per #107 rev 3. The issue's scenario, structure, nine journeys, acceptance criteria, and evidence boundary are taken as authoritative. Three parts of the issue text predate what actually landed; here is what I will build, and what the superseded text maps to.

    Superseded sketch details (issue text → landed contract)

    1. <Agent.Warning> never entered the Build a real RSC Agent Document renderer with streaming semantics #96 vocabulary (landed elements: Result/Text/Markdown/Json/Context/Progress/Image/Audio/Resource/Error). Current-actor warnings will render as Agent.Result-rooted documents carrying Agent.Context text — the real additional-context channel the Compile semantic Agent event routes into native host hooks #97 event projector lowers per family (tool/before supports context + deny on the pinned hosts). Notice content is likewise plain document vocabulary. Adding a Warning element would be a Build a real RSC Agent Document renderer with streaming semantics #96-lane vocabulary decision and is not needed for the semantics; not proposed here.
    2. useWorktree() (hook form): no useAgent()/client-hook contract exists on main — Build a real RSC Agent Document renderer with streaming semantics #96 shipped await agent() only. The example delivers worktree()/topology() as the custom context APIs; the hook variant is recorded as unavailable until a client-hook contract exists.
    3. notices.publish({ content: <JSX> }): Add recipient-aware notices and capability-gated delivery #99's landed publish takes a detached, bounded AgentDocumentSnapshot (states pending|attempted|expired|unavailable|withdrawn, next-event delivery only). The example builds snapshots through the public document contract and keeps the honest v1 taxonomy — attempted is the strongest state it will ever claim.

    Two upstream gaps this issue's acceptance collides with

    1. Provider modules are discovered but never executed. src/providers/* lands in the route graph and manifest, but no generated runtime path executes them; the generated Flight worker mounts only a hardcoded processLifetime bag. The acceptance bullet "custom worktree()/useWorktree() implemented solely through the public context-provider contract" is unbuildable without execution. I will deliver the missing Add typed Agent request context and pluggable context providers #95 remainder as a bounded pre-slice PR: per-request execution of discovered provider modules inside the generated Flight worker (deterministic name order, fail-closed render diagnostics, fresh AB4940+ build-time contract codes, zero generated code for provider-less projects), values mounted at (await agent()).providers.<camelCaseName>. Provider dependency graphs, generated typing, and cleanup semantics stay deferred on Add typed Agent request context and pluggable context providers #95.
    2. Generated request scopes mount neither state nor notices (Track remaining #98 state-kernel scope: warm-runtime process state, generated-runtime state mounting, budgets, lifetime visibility #233's active lane; same finding recorded on Add recipient-aware notices and capability-gated delivery #99). The example will not block on that lane: v1 wires the durable node:sqlite driver and the real notice ledger at application level from the public subpaths (@agent-bundle/runtime/state/sqlite, @agent-bundle/runtime/notices) with per-request open/close — exactly this issue's "application authors custom APIs from framework primitives" stance. Delivery admission goes through the ledger's real openRequest (kind event), so journeys 5–6 use the genuine pending → attempted machinery, not a reimplementation. If Track remaining #98 state-kernel scope: warm-runtime process state, generated-runtime state mounting, budgets, lifetime visibility #233's mounting merges mid-flight I rebase onto it and migrate to (await agent()).state/.notices; otherwise the migration is recorded as a follow-up on Track remaining #98 state-kernel scope: warm-runtime process state, generated-runtime state mounting, budgets, lifetime visibility #233.

    What gets built

    • examples/worktree-proximity (@agent-bundle-example/worktree-proximity), targets claude+codex, event routes on the shared warm runtime (session/start, agent/start, tool/before, tool/after, stop — all inside the landed G10 family set) plus mcp/coordinator/tools/status.tsx, so hooks and tools genuinely share one runtime process — the Wave-6 warm-runtime proof meta-framework: execution plan and sequencing #107 assigns here.
    • Cross-worktree shared state root derived from git rev-parse --git-common-dir (worktrees of one repo share it) — two independent processes share exact revisions through the sqlite driver, no daemon.
    • Proximity stays explicit path/dependency intent in src/domain/proximity.ts (pure application code); topology records carry per-edge provenance, and an envelope without agent identity refuses the edge with a recorded unavailable reason (journey 8 — no parent axis exists on canonical identity, and none is fabricated).
    • Deterministic suite per the issue's evidence boundary: route-unit tests via agent-bundle/rstest + agent-bundle/test, plus one serialized journey suite that builds once, creates a real repo with two worktrees, runs the generated MCP entry and real generated hook wrapper child processes over the artifact IPC, drives journeys 1–9 (incl. idempotency dedupe and a full restart with durable retention), and labels itself artifact/contract evidence — explicitly not commercial-host dispatch proof. README documents the external-driver boundary: v1 connects no external adapter and claims none.

    PR shape: PR-1 framework provider execution (#95 remainder, with changeset), PR-2 the example + suite (private package, no changeset). Landing bar per standing policy (scoped tests + typecheck + lint, merge on green). Objections to any of the three supersessions or the app-level state/notice wiring — say so here; otherwise building starts now.

  3. ScriptedAlchemy commented on Sep 2, 2026

    @ScriptedAlchemy
    OwnerAuthor

    Landed

    Delivered fully against the scope proposal above, in three PRs on top of #251's request-scope mounting:

    1. feat(routes): execute conventional context providers in generated request scopes (#95 remainder) #255 — feat(routes): execute conventional context providers (#95 remainder), merge 02d2e37e4. The generated Flight worker executes src/providers/*.{ts,tsx} factories once per request (deterministic sorted-key order, abort-aware, fail-closed), values at (await agent()).providers.<camelCaseKey>; parse-only build validation AB4940–AB4942; AgentProviderContext/AgentProviderFactory public types; provider-less projects byte-identical (sha-pinned). This was the acceptance-blocking Add typed Agent request context and pluggable context providers #95 remainder.
    2. feat(examples): add the worktree-proximity composition reference (#104) #256 — feat(examples): add the worktree-proximity composition reference, merge 9a79972dc. The example exactly as structured in this issue: git-worktree + agent-topology providers, default-exported workspace-durable topology state (mounted per feat(runtime): mount state kernel and notice ledger into generated request scopes (#233) #251), five shared-runtime event routes, pure domain/proximity.ts, coordinator/status tool, per-field native/derived provenance, edgeRefused for identity-less starts, honest capability rendering when handles are unmounted. Route-unit journey tests (3–8) over a real durable sqlite store shared across renders via public @agent-bundle/runtime/mount.
    3. test(examples): prove worktree-proximity journeys across real processes and worktrees (#104) #260 — test(examples): prove worktree-proximity journeys across real processes and worktrees, merge eb79df6d9. The deterministic suite per the evidence boundary: one built artifact, a real git repo with two linked worktrees, the generated MCP server + generated hook thin clients as separate OS processes over the artifact IPC. Journeys 1–9 all pass, including idempotent replay (7), fail-closed wrapper + route-level refusal for missing identity (8, two honesty layers), and SIGKILL/respawn durability with exact revision equality (9).

    Supersessions honored (from the scope proposal)

    Framework finding recorded

    Generated event request scopes mount host/session/workspace principals (workspace = native cwd) but no actor principal, so actor-directed notices can never reach attempted in generated runtimes v1. The example directs notices at the recipient worktree via the supported AgentRecipient.workspace axis. Actor-principal mounting is recorded on #233 as follow-up lineage.

    Acceptance criteria

    All met: no framework-private imports in example source; custom worktree() solely through the provider contract; two independent processes share exact state revisions (asserted by revision equality across processes and a restart) without a daemon; collision logic isolated in the domain module; real document + notice projectors; unsupported identity/delivery states visible and tested at both wrapper and route layers; README documents the external-driver boundary and claims no external integration.

    Gates on every PR: scoped tests + typecheck + rslint locally green (route-graph/entry-shell units, generated-route-server integration 9/9, example check with 4/4 domain + 8/8 route-unit, journey suite 1/1 covering all nine journeys). Closing.

  4. added a commit that references this issue on Sep 3, 2026
  5. ScriptedAlchemy commented on Sep 3, 2026

    @ScriptedAlchemy
    OwnerAuthor

    Closed-issue re-audit (G3) — VERIFIED, one hygiene gap fixed in #372 (squash ccb9cd18a).

    Re-run on origin/main: examples/worktree-proximity check (validate + build + typecheck + 4 domain + 8 route-unit ✓) and the cross-process journey suite packages/agent-bundle/tests/worktree-proximity-journeys.test.ts (integration pool, journeys 1–9 incl. idempotent replay and SIGKILL/respawn durability) ✓. Source imports only agent-bundle / @agent-bundle/runtime public entries; README §External-driver boundary claims no external adapter; the useWorktree() / providers.agentTopology.snapshot supersessions are recorded in the README as in the landing comment.

    Gap: the example builds to examples/worktree-proximity/artifact/, which was not gitignored (unlike examples/audiobook-curator/artifact/), so pnpm examples:check followed by pnpm lint failed with 9,372 rslint errors on generated hook wrappers. #372 ignores it.

    Still open elsewhere: actor-principal mounting in generated event scopes (recorded on #233, now closed) belongs to the #99 notices lane — the example correctly targets the workspace recipient axis meanwhile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthost-integrationAgent host capabilities, projection, discovery, and lifecyclemeta-frameworkAgent Bundle compiler-coupled meta-frameworkruntimeRuntime context, state, rendering, or executiontestingFramework test harnesses and integration evidence

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions