callstack / callstack/agent-device

chore(gates): classify root hubs, dynamic edges, and the root-to-daemon entry

Open
#2,542 1 comment 0 reactions 0 assignees View on GitHub
ready-for-agent refactor
Dominant language
TypeScript
Stars
4.6k
Forks
299
Avg merge
10h 14m
Merged PRs (30d)
537

Description

## Purpose

Three blind spots let daemon/root coupling reappear without failing a gate. Each is a measured hole, not a hypothetical.

1. **Root hubs are not classifiable.** R76 (`scripts/layering/daemon-platform-runtime-inventory.ts`) matches `src/daemon/**` importing `src/platform-runtime(?:\.ts|-[a-z0-9-]+\.ts)`. A daemon file importing a differently-named root hub that itself reaches platform mechanics is invisible: `src/provider-device-runtime.ts` accounts for 12 daemon file pairs and imports `src/platform-runtime.ts` and `src/platform-runtime-screen-recording-apple-runner-transport.ts` on its own behalf, neither of which is under any inventory. ADR 0022's "one leaked edge remains" is true only for direct edges to gated names.
2. **Dynamic imports are unwatched.** R4/R5/R6 see static edges. Today's one instance: `src/daemon/snapshot-interactor-capture.ts` → `src/core/interactors.ts` (dynamic; `src/core/interactors.ts` imports `src/provider-device-runtime.ts`). `docs/dependency-graph-findings.md` already records dynamic direction as "outside every rule".
3. **Nothing owns `root → daemon`.** 37 file pairs reach into daemon internals from outside. `src/daemon-client/**` — which wave 3's #2360 moved out of `src/daemon/` — still holds 13 pairs / 8 value edges into `daemon-request.ts`, `config.ts`, `daemon-process.ts`, `session-repair-tombstone.ts`, `request-progress-protocol.ts`. The move changed the client's location, not its imports.

Umbrella: #2545.

## Required behavior

1. Extend the R76 inventory so a daemon edge to a **root module that reaches platform mechanics** is classified even when the module name is not `platform-runtime-*`. Keep the existing three categories and the same no-drift/no-stale rules; widen the target predicate rather than adding a second table.
2. Make dynamic import direction observable in the same pass: a dynamic daemon edge into a root or lower zone must be classifiable or reported. Do not add a separate gate job.
3. Add one declared entry surface through which non-daemon code may import the daemon, and ratchet the rest. `src/daemon-client/**` and `src/cli/**` are the named importers today; a file outside the declared entry gaining a daemon import fails. Repair the residue rather than allowlisting it: the `daemon-client` edges into `session-repair-tombstone.ts`, `daemon-process.ts`, and `request-progress-protocol.ts` are the real work.
4. Ratchet, don't reset: the R75 handler-owned session-authority ratchet and the R6 type-inversion ratchet keep their current references. Current inversions are `commands -> client` (2), `commands -> daemon-server` (1), `mcp -> client` (1).

## Completion conditions

- A planted daemon import of an unclassified root hub turns the layering check red. Verify the same for a planted dynamic edge and a planted out-of-entry daemon import, before acceptance.
- Stale-entry and symbol-drift failures still fire (existing R76 behavior must not weaken).
- `src/daemon-client/**` → `src/daemon/**` value edges reach 0, and the shrink-only rule holds the set there.
- One gate run, no new CI job.

## Out of scope

- New detectors for problems not measured above. Per #2531's rules: fix-shaped, not detector-shaped. If a hole turns out to have no reachable edge, delete the candidate rule instead of shipping it.

## Dependencies

- None for the gate work. Wave A. The provider-device port child and the extraction child both want to touch the inventory; sequence the inventory edit into this branch where the branches meet.

Contributor guide

Open the contributing guide

Research direction

Start with scripts/layering/daemon-platform-runtime-inventory.ts and the existing R75/R6 gate references, then review docs/dependency-graph-findings.md and the named imports under src/daemon-client, src/cli, and src/daemon. Verify planted root-hub, dynamic, and out-of-entry imports fail while stale-entry and symbol-drift checks remain intact; completion requires zero daemon-client value edges and one gate run.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
build-system, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.