From e77c4067ece6d5177e3a23c6e2f0cb6e65ed84fa Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:50:06 +0000
Subject: [PATCH 01/15] Initial plan
From 76c13f3de0ba8ff637ad109f4f1c2b255700093b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:54:30 +0000
Subject: [PATCH 02/15] docs(topology-planner): reconcile planning docs and
D-20 boundary
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
PLANS.md | 1 +
crates/topology-planner/CHECKLIST.md | 43 ++----
.../topology-planner/COMPLETED-CHECKLIST.md | 23 +++
crates/topology-planner/COMPONENT.md | 4 +-
crates/topology-planner/DESIGN-NOTES.md | 139 ++++--------------
crates/topology-planner/DESIGN-RATIONALE.md | 26 ++++
crates/topology-planner/PLANS.md | 5 +
7 files changed, 95 insertions(+), 146 deletions(-)
create mode 100644 crates/topology-planner/COMPLETED-CHECKLIST.md
create mode 100644 crates/topology-planner/DESIGN-RATIONALE.md
create mode 100644 crates/topology-planner/PLANS.md
diff --git a/PLANS.md b/PLANS.md
index a972e82bf..2e17f06eb 100644
--- a/PLANS.md
+++ b/PLANS.md
@@ -11,6 +11,7 @@ plans tracker: [crates/windows-file-enumeration-sys/PLANS.md](crates/windows-fil
[crates/windows-platform-probes/PLANS.md](crates/windows-platform-probes/PLANS.md),
[crates/windows-thread-ambient-sys/PLANS.md](crates/windows-thread-ambient-sys/PLANS.md),
[crates/windows-threadpool-sys/PLANS.md](crates/windows-threadpool-sys/PLANS.md),
+[crates/topology-planner/PLANS.md](crates/topology-planner/PLANS.md),
[crates/windows-topology-sys/PLANS.md](crates/windows-topology-sys/PLANS.md),
[crates/windows-waitable-queues/PLANS.md](crates/windows-waitable-queues/PLANS.md), and
[crates/wtf-string/PLANS.md](crates/wtf-string/PLANS.md). Checklists whose work is finished move to
diff --git a/crates/topology-planner/CHECKLIST.md b/crates/topology-planner/CHECKLIST.md
index 3273e095f..bb96de9dd 100644
--- a/crates/topology-planner/CHECKLIST.md
+++ b/crates/topology-planner/CHECKLIST.md
@@ -32,7 +32,7 @@ prerequisites rather than on someone else's decision.
| Milestone | State | What it is waiting on |
|---|---|---|
-| M1 the input contract | 4 done, 1 open | `EP-1.5`'s coverage half, which wants a settled model |
+| M1 the input contract | 3 done, 2 open | `EP-1.4` and `EP-1.5`'s coverage half, which want a settled model |
| M1+ scenario and naming | **partly answered** | the name is settled (EP-D-4); the goal input is deferred for litigation, by direction |
| M2+ the plan as a value | parked, **and needs re-cutting** | re-cut against EP-D-4/EP-D-5, then the topology reshape landing |
| M3+ the policies | parked | M2+ |
@@ -45,23 +45,7 @@ consumers, and **this crate is the consumer**. Answering in the abstract has alr
wrong answer this session. Each item below states a query the planner makes, why it makes it, and
whether the topology can answer it today -- so the model is designed against a real caller.
-- [x] **EP-1.1** -- **The shard-set query.** Which processors may host a domain: online, with
- identity carried as `(group, number)` rather than a bare number, with efficiency class and SMT
- structure available so a policy can choose one domain per core or per thread and can decide
- whether efficiency cores are peers. **Gap already identified:** parked and allocated state is not
- available at all, and pinning a domain to a parked processor is a defect a client cannot detect.
- Tracked as `SH-16.10`.
- **Done:** stated as [EP-D-1](DESIGN-NOTES.md#ep-d-1), with each of its five inputs checked against
- the model rather than assumed. Three are answered cleanly; availability is not answered at all;
- and the fourth turned up a defect the item had not anticipated.
- **`Processor::capacity` is unsafe for reading efficiency class.** It is
- `online.then(find owning Core).flatten().unwrap_or(0)`, so `0` means offline, *or* in no core
- domain, *or* genuinely class zero -- and the third is every processor on every non-hybrid machine,
- so the sentinel collides with the common legitimate value. Worse here than elsewhere, because
- Windows orders class `0` as *least* performant: on a hybrid part an unknown processor is
- indistinguishable from an efficiency core, so a policy excluding them silently drops a possible
- performance core and a policy tiering them mis-tiers it. Neither fails a functional test. Filed
- against the owning crate as `SH-16.12`; use `DomainKind::Core { efficiency_class }` meanwhile.
+- [x] **EP-1.1** -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. -> [completed 2026-09-18](COMPLETED-CHECKLIST.md#ep-11)
- [x] **EP-1.2** -- **The proximity query, which is the crux.** For an ~~*ordered pair*~~
**unordered pair** of processors, how close are they -- because that is what chooses SPSC versus
@@ -86,10 +70,10 @@ whether the topology can answer it today -- so the model is designed against a r
- [x] **EP-1.3** -- **The residency query.** Which memory domain each processor belongs to, and --
for a pair spanning two of them -- what it costs to place a shared buffer on one side rather than
- the other. **Gap already identified:** `MachineMemoryTopology::distances` exists, is never populated, and Win32
- cannot populate it; the measurement exists in `windows-placement-probe` and reaches nothing.
- Tracked as `SH-16.11`. The probe measures this per node pair with a dedicated ring-placement
- column precisely because it was found to matter.
+ the other. **Gap already identified:** [D-20](../windows-topology-sys/DESIGN-NOTES.md#d-20)
+ removed `MachineMemoryTopology::distances` at the Win32 boundary, so this cost has to enter through
+ the abstract model via the inward adapter/synthesizer path. That contract is still missing and
+ remains tracked as `SH-16.11`.
**Done:** stated as [EP-D-3](DESIGN-NOTES.md#ep-d-3). This is where the direction EP-1.2 refused
lands -- proximity is the link and symmetric, residency is the hop and is not.
The processor-to-node half is answered, with one asymmetry worth preserving: an unknown *cache*
@@ -97,17 +81,10 @@ whether the topology can answer it today -- so the model is designed against a r
pool must be allocated somewhere and guessing means quietly allocating remote memory for the life
of the process. `windows-placement-probe` already refuses on the second while tolerating the
first, and that judgement was correct.
- **The cost half needs SH-16.11 restated, and it was.** That item read as though someone had
- forgotten to populate a field. Two sharper problems replace it: `distances` can never carry
- `Measured` provenance **by construction** -- its only inputs are a literal (`Synthetic`) and a file
- (capped at `Restored`) -- so populating it would not help; and even populated it is SLIT-shaped,
- one symmetric workload-independent scalar, while the question is directional. `D-9` in the
- topology crate already deferred the attributed edge list that would answer it, naming *asymmetry*
- among what it would absorb, with the trigger being that a scalar "demonstrably mismodels a machine
- somebody is tuning for" -- and this planner is that machine-tuner.
- **The trigger is approached, not met**, and the gap is a measurement nobody here can take: both
- development hosts are single-node, so every directional run prints "VACUOUS ON THIS MACHINE".
- Recorded so D-9 is reopened on evidence rather than on argument.
+ **The cost half is now scoped to the current boundary.** The planner still needs directed
+ residency-cost input plus measurement context, but those facts no longer live in
+ `windows-topology-sys`; they are requirements on `topology-model` and the adapter that populates it.
+ Historical trigger analysis remains in [DESIGN-RATIONALE.md](DESIGN-RATIONALE.md#ep-d-3-rationale-and-history).
- [ ] **EP-1.4** -- **What the planner does with an unanswered query**, given the model's bar is
that it answers without further measurement. A fact that was not observed cannot be acquired at
diff --git a/crates/topology-planner/COMPLETED-CHECKLIST.md b/crates/topology-planner/COMPLETED-CHECKLIST.md
new file mode 100644
index 000000000..0175e3ad9
--- /dev/null
+++ b/crates/topology-planner/COMPLETED-CHECKLIST.md
@@ -0,0 +1,23 @@
+# Completed checklist
+
+## Moved 2026-09-18 18:50:30 +00:00 -- Archive completed EP-1.1 details
+
+### EP-1.1 -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. *(completed 2026-09-18 18:50:30 +00:00)*
+
+- [x] **EP-1.1** -- **The shard-set query.** Which processors may host a domain: online, with
+ identity carried as `(group, number)` rather than a bare number, with efficiency class and SMT
+ structure available so a policy can choose one domain per core or per thread and can decide
+ whether efficiency cores are peers. **Gap already identified:** parked and allocated state is not
+ available at all, and pinning a domain to a parked processor is a defect a client cannot detect.
+ Tracked as `SH-16.10`.
+ **Done:** stated as [EP-D-1](DESIGN-NOTES.md#ep-d-1), with each of its five inputs checked against
+ the model rather than assumed. Three are answered cleanly; availability is not answered at all;
+ and the fourth turned up a defect the item had not anticipated.
+ **`Processor::capacity` is unsafe for reading efficiency class.** It is
+ `online.then(find owning Core).flatten().unwrap_or(0)`, so `0` means offline, *or* in no core
+ domain, *or* genuinely class zero -- and the third is every processor on every non-hybrid machine,
+ so the sentinel collides with the common legitimate value. Worse here than elsewhere, because
+ Windows orders class `0` as *least* performant: on a hybrid part an unknown processor is
+ indistinguishable from an efficiency core, so a policy excluding them silently drops a possible
+ performance core and a policy tiering them mis-tiers it. Neither fails a functional test. Filed
+ against the owning crate as `SH-16.12`; use `DomainKind::Core { efficiency_class }` meanwhile.
diff --git a/crates/topology-planner/COMPONENT.md b/crates/topology-planner/COMPONENT.md
index 439bac093..65541d650 100644
--- a/crates/topology-planner/COMPONENT.md
+++ b/crates/topology-planner/COMPONENT.md
@@ -37,7 +37,9 @@ is not yet known, and knowing them is what decides whether that is one trait or
| the outward adapter (the realizer) | Windows | `topology-model`, the runtime crates |
`topology-model` holds the abstract machine description, **the traits the planner queries**, and
-**the plan type**. Everything depends on it; **nothing depends on this crate**.
+**the plan type**. Everything depends on it; components that only describe or realize topology
+depend on `topology-model` and do not depend on this crate. Callers that need planning policy do
+depend on this crate.
That is the whole point of the arrangement. If the traits lived here, an adapter whose only job is
to describe a machine would have to depend on a planner, and anyone wanting to read a topology would
diff --git a/crates/topology-planner/DESIGN-NOTES.md b/crates/topology-planner/DESIGN-NOTES.md
index 430306c9e..1f67be5b7 100644
--- a/crates/topology-planner/DESIGN-NOTES.md
+++ b/crates/topology-planner/DESIGN-NOTES.md
@@ -1,7 +1,8 @@
# Design notes: the topology planner
Current canonical decisions for this component. See [COMPONENT.md](COMPONENT.md) for what the
-component is; see [CHECKLIST.md](CHECKLIST.md) for what is planned.
+component is; see [CHECKLIST.md](CHECKLIST.md) for what is planned. Historical context and
+exploratory analysis live in [DESIGN-RATIONALE.md](DESIGN-RATIONALE.md).
`EP-D-1` through `EP-D-3` are **queries** rather than choices: the planner's requirements, stated
precisely enough that the topology model could be designed against a real caller instead of against
@@ -20,9 +21,9 @@ renamed to match.
|---|---|
| EP-D-1 | **The shard-set query**: what the planner must know to choose which processors host a domain, and what today's model cannot tell it. |
| EP-D-2 | **The proximity query**: how close two processors are, which selects the channel between their domains. Takes an **unordered** pair; the model has no answer today. |
-| EP-D-3 | **The residency query**: where a domain's pool lives, and which side of a cross-domain pair should host a shared ring. **Ordered**, and the half the model cannot answer is structurally unanswerable rather than merely unpopulated. |
+| EP-D-3 | **The residency query**: where a domain's pool lives, and which side of a cross-domain pair should host a shared ring. **Ordered**, with directed cost entering through the abstract model/adapter path under [D-20](../windows-topology-sys/DESIGN-NOTES.md#d-20). |
| EP-D-4 | **The four-part architecture, and the planner's name.** The engineer's position: the planner is **`topology-planner`** (no `windows-` prefix); it takes a **goal** description (shape deferred for litigation), queries an **abstracted idealized** model covering processors, memory, storage, interconnects, distances and bottlenecks, and emits a **JSON-serializable, platform-neutral** plan. Two kinds of **adapter** bracket it: one exposing the planner's traits over the Windows topology objects, one **realizing** a plan as buffers, rings and threads with the user's code inserted at the right steps. Settles `MMT-1.5` (the facts crate keeps its `-sys` name), the "two graphs, one word" ambiguity, and where distance lives -- the attributed interconnect shape D-9 sketched goes in the abstract model, so D-9's deferral in the facts crate stands unreopened. |
-| EP-D-5 | **The component layout: `topology-model` is its own crate, and dependencies point one way.** The abstract model and the traits the planner queries live in `topology-model`, which the planner and both adapters depend on; nothing depends on `topology-planner`. Putting the traits in the planner would make a crate whose job is to *describe a machine* depend on one that applies *policy* -- the same defect as `outermost_partitioning_cache`, arriving as a dependency edge instead of an API. Two consequences derived from the same rule rather than decided separately: **the plan type also lives in `topology-model`** (otherwise the realizer depends on the planner), and the inward adapter and the realizer are **separate crates** (their dependency sets barely overlap, and fusing them would make reading a topology pull in the whole runtime). |
+| EP-D-5 | **The component layout: `topology-model` is its own crate, and dependencies point one way.** The abstract model and the traits the planner queries live in `topology-model`, which the planner and both adapters depend on; non-planner components do not depend on `topology-planner`. Putting the traits in the planner would make a crate whose job is to *describe a machine* depend on one that applies *policy* -- the same defect as `outermost_partitioning_cache`, arriving as a dependency edge instead of an API. Two consequences derived from the same rule rather than decided separately: **the plan type also lives in `topology-model`** (otherwise the realizer depends on the planner), and the inward adapter and the realizer are **separate crates** (their dependency sets barely overlap, and fusing them would make reading a topology pull in the whole runtime). |
## EP-D-1: the shard-set query
@@ -230,109 +231,35 @@ this query is the cause of that defect, not a separate problem.
*Recorded by [CHECKLIST.md](CHECKLIST.md) EP-1.3.*
-### What the planner is choosing
-
-Two things, and they are different questions that happen to share a subject:
-
-- **Where each domain's own pool lives.** A domain allocates node-locally to the processor it is
- pinned to. Per-processor, unordered, cheap.
-- **Which side of a cross-domain pair hosts their shared ring.** Ordered, because the producer
- writes and the consumer reads, so the placement decides which of them pays for the crossing.
-
-This is where the direction that [EP-D-2](#ep-d-2) deliberately refused lands. Proximity is the
-link and is symmetric; residency is the hop and is not.
-
-### The first half is answered, with one asymmetry worth keeping
-
-`MachineMemoryTopology::memory_domains()` yields the memory domains with their processor sets, so
-processor-to-domain is a lookup.
-
-Partial coverage exists here as it does for caches -- a processor may be named by no memory domain
--- but **the right response is different, and `windows-placement-probe` already got this right**.
-Its `places_from_topology` refuses on a missing NUMA node while tolerating a missing cache domain,
-and the asymmetry is principled: an unknown cache domain costs an optimisation, whereas an unknown
-memory domain has no honest fallback at all, since the pool has to be allocated *somewhere* and
-guessing means quietly allocating remote memory for the life of the process.
-
-So the planner inherits that: an unplaced processor may still host a domain, but not with a
-node-local pool, and the difference has to be visible in the plan rather than assumed away.
-
-### The second half is not merely unpopulated -- it cannot be measured, by construction
-
-`MachineMemoryTopology::distances` exists, and it is easy to read its permanent `None` as an oversight. It is
-not. The field is documented as being for a fed-in description, because "Windows exposes no
-user-mode SLIT reader", and that is accurate.
-
-The sharper problem is what follows from it. `distances` has exactly two input paths: hand
-construction, which defaults to `Provenance::Synthetic`, and deserialization, which
-`downgraded_to(Provenance::Restored)` caps. `MachineMemoryTopology::discover` hardcodes `None`. So **no path
-exists by which `distances` can ever carry `Measured` provenance** -- not because nobody wrote the
-code, but because the only sources are a literal and a file, and a file cannot establish that it
-describes the machine you are on.
-
-Under the model's bar -- usable without further measurement -- a planner on a real machine
-therefore cannot obtain trustworthy distance for that machine today, and no amount of populating
-the existing field would change that.
-
-### A scalar distance cannot express what this query asks
-
-Even a populated `Distances` would not answer it. The matrix is SLIT-shaped: one scalar per pair,
-with `matrix[i][i]` conventionally `10`. That is a *symmetric, workload-independent* abstraction,
-and the residency question is neither. It asks which of two directions is cheaper for a specific
-access pattern -- a ring one side writes and the other reads.
-
-`windows-topology-sys` D-9 already anticipated this precisely, and excluded it deliberately:
-
-> **HMAT-style attributed relations.** ACPI's Heterogeneous Memory Attribute Table supersedes SLIT,
-> giving per-initiator/per-target read and write latency and bandwidth -- four numbers where SLIT
-> gives one scalar [...] A general edge list (`{ from, to, read_latency_ns, read_bandwidth_mbps,
-> ... }`) would absorb HMAT, **asymmetry**, and multi-hop CXL fabrics; the scalar distance matrix
-> this schema keeps will [be revisited when] scalar distance demonstrably mismodels a machine
-> somebody is tuning for.
-
-**This planner is the machine-tuner that deferral names, and asymmetry is exactly the property it
-needs.** D-8 makes the revision cheap by keeping the JSON schema outside the semver contract, which
-that decision says is "precisely what makes D-9's deferrals safe rather than merely convenient".
-
-### The trigger is approached, not met, and saying which matters
+### The decision
-D-9's condition is *demonstrable* mismodelling, and honesty requires separating what is shown from
-what is expected.
+The planner needs two distinct residency facts:
-What is shown: `windows-placement-probe` measures per-hop cost as four numbers per undirected edge
--- two directions times two ring placements -- and its code states that "a hop is not symmetric even
-though the link is". The apparatus treats direction as real.
+- **Processor to memory-domain placement** for node-local pool allocation, with unplaced processors
+ represented explicitly.
+- **Directed cross-domain residency cost** for choosing which side of a pair hosts shared buffers,
+ with measurement context attached to measured values.
-What is **not** shown: any measurement demonstrating that the four numbers differ. Both development
-hosts report a single NUMA node, so every such run is vacuous -- the spike says so itself, printing
-"VACUOUS ON THIS MACHINE" and "Apparatus works; question unanswered". So the claim "scalar distance
-mismodels this machine" is currently unproven on hardware anyone here has.
+### Boundary alignment with D-20
-The requirement is real either way, because the planner must choose a side and today has nothing to
-choose with. But the *specific* claim that a scalar is insufficient needs a multi-node measurement,
-and that measurement should be taken before D-9 is reopened on those grounds rather than after.
+[D-20](../windows-topology-sys/DESIGN-NOTES.md#d-20) deleted `MachineMemoryTopology::distances` and
+fixed the Win32 boundary for `windows-topology-sys`. Residency-cost data required by the planner
+therefore enters through the abstract model path and the adapter/synthesizer that populates it, not
+through `windows-topology-sys`.
-### A measured locality fact must carry what it measured
+### Current status
-The probe's numbers are nanoseconds for one ring-handoff pattern at one message size. Promoting
-them into the topology as "the distance" would bake one workload into a model other consumers share
--- and a different consumer, streaming large buffers rather than handing off small messages, would
-read them as authoritative and be wrong.
+The processor-to-memory-domain half is available from topology memory-domain memberships and still
+keeps the established asymmetry: unknown cache placement can degrade, unknown memory placement has
+no honest default.
-So a measured relation has to name its measurement, not just its value. This is the concrete reason
-per-relation provenance has to be more than a trust label: "measured" is not a sufficient
-description of a number whose meaning depends on how it was obtained.
+The directed-cost half remains an open requirement on `topology-model` plus adapter inputs and stays
+tracked as `SH-16.11`.
-### What this asks of the model
+### Historical rationale
-- Processor-to-memory-domain, with the unplaced case distinguishable rather than defaulted, because
- here it has no honest default.
-- A **directed** cost between memory domains, which SLIT's scalar cannot express and which D-9
- already sketched as an attributed edge list.
-- Provenance rich enough to say *what* a measured number measured, so one consumer's workload does
- not become every consumer's constant.
-- And, before reopening D-9 on the asymmetry argument: a multi-node measurement showing the
- directions actually differ.
+Detailed trigger analysis and prior framing are recorded in
+[DESIGN-RATIONALE.md](DESIGN-RATIONALE.md#ep-d-3-rationale-and-history).
## EP-D-4: the four-part architecture, and the planner's name
@@ -391,21 +318,9 @@ that it "changes the crate's identity from processor topology to system topology
about *that crate* and still holds. NVMe belongs to the abstract model, which was never scoped to a
processor topology.
-### What it opens
-
-- **Component layout.** How many crates, and where the traits live. If the traits are defined in the
- planner, the inward adapter depends on the planner, which points the wrong way for a crate whose
- job is to describe a machine. An abstract-model crate that both depend on avoids that, at the cost
- of a fourth component. **Not yet decided.**
-- **Who measures.** The previous framing had this component measuring with permission. If distance is
- a property of the abstract model, measurement plausibly belongs to whatever *populates* that model
- -- an adapter -- rather than to the planner. The three-stage split (observe / synthesize / execute)
- survives; which component owns the middle stage does not obviously.
-- **`MMT-1.3` / `EP-1.4`'s consumer changed.** Both ask what a consumer does with a fact that was not
- observed. That consumer is no longer the planner reading `MachineMemoryTopology` directly -- it is
- the **inward adapter**, deciding how an absent Windows fact appears in the abstract model. The
- decision is still one decision, and it is still to be taken jointly, but it is taken at a boundary
- that did not exist when both items were written.
+Open follow-up history for this decision is recorded in
+[DESIGN-RATIONALE.md](DESIGN-RATIONALE.md#ep-d-4-open-follow-ups); current actionable work is tracked
+in [CHECKLIST.md](CHECKLIST.md).
### What survives unchanged
diff --git a/crates/topology-planner/DESIGN-RATIONALE.md b/crates/topology-planner/DESIGN-RATIONALE.md
new file mode 100644
index 000000000..31c45723a
--- /dev/null
+++ b/crates/topology-planner/DESIGN-RATIONALE.md
@@ -0,0 +1,26 @@
+# Design rationale: topology-planner
+
+Historical design context and exploratory analysis for this component. Current canonical decisions are
+in [DESIGN-NOTES.md](DESIGN-NOTES.md).
+
+## EP-D-3 rationale and history
+
+Earlier drafts of EP-D-3 were written against a now-deleted `MachineMemoryTopology::distances`
+field and analyzed whether that field could be repurposed. That framing is retained here as history:
+it explains why a scalar, symmetric distance matrix was considered insufficient for the directional
+residency question and why measured values must carry measurement context, not only provenance.
+
+After [D-20](../windows-topology-sys/DESIGN-NOTES.md#d-20), the relevant boundary is explicit:
+`windows-topology-sys` does not publish below Win32 topology APIs, so residency-cost data must be
+provided by the abstract model path and its adapter/synthesizer inputs.
+
+## EP-D-4 open follow-ups (historical)
+
+EP-D-4 intentionally left several follow-ups unresolved:
+
+- Adapter naming.
+- Measurement ownership in the new four-part architecture.
+- Consumer behavior for not-observed facts after the boundary split.
+
+These are tracked as checklist work in [CHECKLIST.md](CHECKLIST.md) rather than as canonical
+decisions.
diff --git a/crates/topology-planner/PLANS.md b/crates/topology-planner/PLANS.md
new file mode 100644
index 000000000..c7d77e04d
--- /dev/null
+++ b/crates/topology-planner/PLANS.md
@@ -0,0 +1,5 @@
+# Plans
+
+| Path to CHECKLIST.md | Status | Brief description | Design Notes |
+|---|---|---|---|
+| [CHECKLIST.md](CHECKLIST.md) | in progress | Plan and documentation work for the topology-planner component while implementation remains deferred. | [DESIGN-NOTES.md](DESIGN-NOTES.md), [DESIGN-RATIONALE.md](DESIGN-RATIONALE.md) |
From bc7a5920de94513b70e480bc2b73da078afcfcdc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:54:59 +0000
Subject: [PATCH 03/15] docs(topology-planner): normalize PLANS heading format
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/PLANS.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/topology-planner/PLANS.md b/crates/topology-planner/PLANS.md
index c7d77e04d..95f921598 100644
--- a/crates/topology-planner/PLANS.md
+++ b/crates/topology-planner/PLANS.md
@@ -1,4 +1,4 @@
-# Plans
+# PLANS
| Path to CHECKLIST.md | Status | Brief description | Design Notes |
|---|---|---|---|
From d5fb5ecc89c26d1ab0b727025fc942381b88be98 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:55:29 +0000
Subject: [PATCH 04/15] docs(topology-planner): keep residency contract
explicit in notes
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/DESIGN-NOTES.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/crates/topology-planner/DESIGN-NOTES.md b/crates/topology-planner/DESIGN-NOTES.md
index 1f67be5b7..383044999 100644
--- a/crates/topology-planner/DESIGN-NOTES.md
+++ b/crates/topology-planner/DESIGN-NOTES.md
@@ -245,7 +245,8 @@ The planner needs two distinct residency facts:
[D-20](../windows-topology-sys/DESIGN-NOTES.md#d-20) deleted `MachineMemoryTopology::distances` and
fixed the Win32 boundary for `windows-topology-sys`. Residency-cost data required by the planner
therefore enters through the abstract model path and the adapter/synthesizer that populates it, not
-through `windows-topology-sys`.
+through `windows-topology-sys`. That required input remains explicitly directional and must carry
+measurement context with any measured value.
### Current status
From 5b4b459f9b2cd224ba91247bc51100beb7049e7b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:55:58 +0000
Subject: [PATCH 05/15] docs(topology-planner): align PLANS status with
deferred state
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/PLANS.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/topology-planner/PLANS.md b/crates/topology-planner/PLANS.md
index 95f921598..a6f8176c8 100644
--- a/crates/topology-planner/PLANS.md
+++ b/crates/topology-planner/PLANS.md
@@ -2,4 +2,4 @@
| Path to CHECKLIST.md | Status | Brief description | Design Notes |
|---|---|---|---|
-| [CHECKLIST.md](CHECKLIST.md) | in progress | Plan and documentation work for the topology-planner component while implementation remains deferred. | [DESIGN-NOTES.md](DESIGN-NOTES.md), [DESIGN-RATIONALE.md](DESIGN-RATIONALE.md) |
+| [CHECKLIST.md](CHECKLIST.md) | not started | Plan and documentation work for the topology-planner component while implementation remains deferred. | [DESIGN-NOTES.md](DESIGN-NOTES.md), [DESIGN-RATIONALE.md](DESIGN-RATIONALE.md) |
From 2813e783e0cab5b1f725cf20a618061d731d3947 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:56:29 +0000
Subject: [PATCH 06/15] docs(topology-planner): clarify PLANS row as active
planning
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/PLANS.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/topology-planner/PLANS.md b/crates/topology-planner/PLANS.md
index a6f8176c8..6c8662f8c 100644
--- a/crates/topology-planner/PLANS.md
+++ b/crates/topology-planner/PLANS.md
@@ -2,4 +2,4 @@
| Path to CHECKLIST.md | Status | Brief description | Design Notes |
|---|---|---|---|
-| [CHECKLIST.md](CHECKLIST.md) | not started | Plan and documentation work for the topology-planner component while implementation remains deferred. | [DESIGN-NOTES.md](DESIGN-NOTES.md), [DESIGN-RATIONALE.md](DESIGN-RATIONALE.md) |
+| [CHECKLIST.md](CHECKLIST.md) | in progress | Planning and documentation work is active while implementation remains deferred. | [DESIGN-NOTES.md](DESIGN-NOTES.md), [DESIGN-RATIONALE.md](DESIGN-RATIONALE.md) |
From d26495a43c9015b627473df39c0cb9919c50cf05 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:57:01 +0000
Subject: [PATCH 07/15] docs(topology-planner): link archived SH follow-ups
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/COMPLETED-CHECKLIST.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/crates/topology-planner/COMPLETED-CHECKLIST.md b/crates/topology-planner/COMPLETED-CHECKLIST.md
index 0175e3ad9..c6f61c364 100644
--- a/crates/topology-planner/COMPLETED-CHECKLIST.md
+++ b/crates/topology-planner/COMPLETED-CHECKLIST.md
@@ -9,7 +9,8 @@
structure available so a policy can choose one domain per core or per thread and can decide
whether efficiency cores are peers. **Gap already identified:** parked and allocated state is not
available at all, and pinning a domain to a parked processor is a defect a client cannot detect.
- Tracked as `SH-16.10`.
+ Tracked as [CHECKLIST-ship-topology-and-queues.md](../../CHECKLIST-ship-topology-and-queues.md)
+ -> `SH-16.10`.
**Done:** stated as [EP-D-1](DESIGN-NOTES.md#ep-d-1), with each of its five inputs checked against
the model rather than assumed. Three are answered cleanly; availability is not answered at all;
and the fourth turned up a defect the item had not anticipated.
@@ -20,4 +21,5 @@
Windows orders class `0` as *least* performant: on a hybrid part an unknown processor is
indistinguishable from an efficiency core, so a policy excluding them silently drops a possible
performance core and a policy tiering them mis-tiers it. Neither fails a functional test. Filed
- against the owning crate as `SH-16.12`; use `DomainKind::Core { efficiency_class }` meanwhile.
+ against the owning crate as [CHECKLIST-ship-topology-and-queues.md](../../CHECKLIST-ship-topology-and-queues.md)
+ -> `SH-16.12`; use `DomainKind::Core { efficiency_class }` meanwhile.
From a555a694fbd7970ab5a79bb81486c608d3e72534 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:57:31 +0000
Subject: [PATCH 08/15] docs(topology-planner): add offset to archived item
stub timestamp
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/CHECKLIST.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/topology-planner/CHECKLIST.md b/crates/topology-planner/CHECKLIST.md
index bb96de9dd..13871b245 100644
--- a/crates/topology-planner/CHECKLIST.md
+++ b/crates/topology-planner/CHECKLIST.md
@@ -45,7 +45,7 @@ consumers, and **this crate is the consumer**. Answering in the abstract has alr
wrong answer this session. Each item below states a query the planner makes, why it makes it, and
whether the topology can answer it today -- so the model is designed against a real caller.
-- [x] **EP-1.1** -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. -> [completed 2026-09-18](COMPLETED-CHECKLIST.md#ep-11)
+- [x] **EP-1.1** -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. -> [completed 2026-09-18 18:50:30 +00:00](COMPLETED-CHECKLIST.md#ep-11)
- [x] **EP-1.2** -- **The proximity query, which is the crux.** For an ~~*ordered pair*~~
**unordered pair** of processors, how close are they -- because that is what chooses SPSC versus
From 1f34b47f39e2b6a1cf928e278c3b09e64e14af7b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:58:00 +0000
Subject: [PATCH 09/15] docs(topology-planner): keep stub date format and
explicit timestamp
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/CHECKLIST.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/topology-planner/CHECKLIST.md b/crates/topology-planner/CHECKLIST.md
index 13871b245..2918e1292 100644
--- a/crates/topology-planner/CHECKLIST.md
+++ b/crates/topology-planner/CHECKLIST.md
@@ -45,7 +45,7 @@ consumers, and **this crate is the consumer**. Answering in the abstract has alr
wrong answer this session. Each item below states a query the planner makes, why it makes it, and
whether the topology can answer it today -- so the model is designed against a real caller.
-- [x] **EP-1.1** -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. -> [completed 2026-09-18 18:50:30 +00:00](COMPLETED-CHECKLIST.md#ep-11)
+- [x] **EP-1.1** -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. *(completed 2026-09-18 18:50:30 +00:00)* -> [completed 2026-09-18](COMPLETED-CHECKLIST.md#ep-11)
- [x] **EP-1.2** -- **The proximity query, which is the crux.** For an ~~*ordered pair*~~
**unordered pair** of processors, how close are they -- because that is what chooses SPSC versus
From bee03f74c791dd5f4c10cbe634a7547e0249c326 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:58:37 +0000
Subject: [PATCH 10/15] docs(topology-planner): clarify in-progress planning
scope
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/PLANS.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/topology-planner/PLANS.md b/crates/topology-planner/PLANS.md
index 6c8662f8c..fdaa35e93 100644
--- a/crates/topology-planner/PLANS.md
+++ b/crates/topology-planner/PLANS.md
@@ -2,4 +2,4 @@
| Path to CHECKLIST.md | Status | Brief description | Design Notes |
|---|---|---|---|
-| [CHECKLIST.md](CHECKLIST.md) | in progress | Planning and documentation work is active while implementation remains deferred. | [DESIGN-NOTES.md](DESIGN-NOTES.md), [DESIGN-RATIONALE.md](DESIGN-RATIONALE.md) |
+| [CHECKLIST.md](CHECKLIST.md) | in progress | Active checklist maintenance for requirements/planning milestones; code implementation milestones are parked. | [DESIGN-NOTES.md](DESIGN-NOTES.md), [DESIGN-RATIONALE.md](DESIGN-RATIONALE.md) |
From 07a95edba5813c0b82566b8b512c91780dc3e87e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:59:12 +0000
Subject: [PATCH 11/15] docs(topology-planner): keep EP-1.1 stub in canonical
one-line form
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/CHECKLIST.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/topology-planner/CHECKLIST.md b/crates/topology-planner/CHECKLIST.md
index 2918e1292..bb96de9dd 100644
--- a/crates/topology-planner/CHECKLIST.md
+++ b/crates/topology-planner/CHECKLIST.md
@@ -45,7 +45,7 @@ consumers, and **this crate is the consumer**. Answering in the abstract has alr
wrong answer this session. Each item below states a query the planner makes, why it makes it, and
whether the topology can answer it today -- so the model is designed against a real caller.
-- [x] **EP-1.1** -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. *(completed 2026-09-18 18:50:30 +00:00)* -> [completed 2026-09-18](COMPLETED-CHECKLIST.md#ep-11)
+- [x] **EP-1.1** -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. -> [completed 2026-09-18](COMPLETED-CHECKLIST.md#ep-11)
- [x] **EP-1.2** -- **The proximity query, which is the crux.** For an ~~*ordered pair*~~
**unordered pair** of processors, how close are they -- because that is what chooses SPSC versus
From 326a2ac442e72a77acf8a09d2b992d706adcf7da Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:59:46 +0000
Subject: [PATCH 12/15] docs(topology-planner): include full completion stamp
in EP-1.1 stub link
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/CHECKLIST.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/topology-planner/CHECKLIST.md b/crates/topology-planner/CHECKLIST.md
index bb96de9dd..13871b245 100644
--- a/crates/topology-planner/CHECKLIST.md
+++ b/crates/topology-planner/CHECKLIST.md
@@ -45,7 +45,7 @@ consumers, and **this crate is the consumer**. Answering in the abstract has alr
wrong answer this session. Each item below states a query the planner makes, why it makes it, and
whether the topology can answer it today -- so the model is designed against a real caller.
-- [x] **EP-1.1** -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. -> [completed 2026-09-18](COMPLETED-CHECKLIST.md#ep-11)
+- [x] **EP-1.1** -- The shard-set query requirements and discovered efficiency-class sentinel defect are recorded. -> [completed 2026-09-18 18:50:30 +00:00](COMPLETED-CHECKLIST.md#ep-11)
- [x] **EP-1.2** -- **The proximity query, which is the crux.** For an ~~*ordered pair*~~
**unordered pair** of processors, how close are they -- because that is what chooses SPSC versus
From 0d574a7038f7bd0acf310f2e1ddcc2429f4e3096 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 20:05:46 +0000
Subject: [PATCH 13/15] docs(topology-planner): replace discharged SH-16.11
tracking references
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/CHECKLIST.md | 7 ++++++-
crates/topology-planner/DESIGN-NOTES.md | 2 +-
crates/topology-planner/DESIGN-RATIONALE.md | 5 +++--
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/crates/topology-planner/CHECKLIST.md b/crates/topology-planner/CHECKLIST.md
index 13871b245..d9b57dc93 100644
--- a/crates/topology-planner/CHECKLIST.md
+++ b/crates/topology-planner/CHECKLIST.md
@@ -73,7 +73,7 @@ whether the topology can answer it today -- so the model is designed against a r
the other. **Gap already identified:** [D-20](../windows-topology-sys/DESIGN-NOTES.md#d-20)
removed `MachineMemoryTopology::distances` at the Win32 boundary, so this cost has to enter through
the abstract model via the inward adapter/synthesizer path. That contract is still missing and
- remains tracked as `SH-16.11`.
+ remains tracked as `EP-1+.4`.
**Done:** stated as [EP-D-3](DESIGN-NOTES.md#ep-d-3). This is where the direction EP-1.2 refused
lands -- proximity is the link and symmetric, residency is the hop and is not.
The processor-to-node half is answered, with one asymmetry worth preserving: an unknown *cache*
@@ -160,6 +160,11 @@ model question -- they are this component's own.
renamed outright, and what the synthesized arrangement is called. Cheap now; expensive once either
name is public. This one blocks nothing but should not be settled by whoever writes the first type.
+- [ ] **EP-1+.4** -- **Assign measurement ownership for directed residency cost in the four-part
+ architecture.** [EP-D-3](DESIGN-NOTES.md#ep-d-3) requires directed cross-domain cost input with
+ measurement context. Record which layer owns collecting, validating, and supplying that measurement
+ context to `topology-model` through the inward adapter/synthesizer path.
+
## M2+: the plan as a value
Parked, not pending. Gated on the topology model landing. Shape recorded so it is not lost, per the
diff --git a/crates/topology-planner/DESIGN-NOTES.md b/crates/topology-planner/DESIGN-NOTES.md
index 383044999..448444bfc 100644
--- a/crates/topology-planner/DESIGN-NOTES.md
+++ b/crates/topology-planner/DESIGN-NOTES.md
@@ -255,7 +255,7 @@ keeps the established asymmetry: unknown cache placement can degrade, unknown me
no honest default.
The directed-cost half remains an open requirement on `topology-model` plus adapter inputs and stays
-tracked as `SH-16.11`.
+tracked as [CHECKLIST.md](CHECKLIST.md) `EP-1+.4`.
### Historical rationale
diff --git a/crates/topology-planner/DESIGN-RATIONALE.md b/crates/topology-planner/DESIGN-RATIONALE.md
index 31c45723a..937c616e3 100644
--- a/crates/topology-planner/DESIGN-RATIONALE.md
+++ b/crates/topology-planner/DESIGN-RATIONALE.md
@@ -22,5 +22,6 @@ EP-D-4 intentionally left several follow-ups unresolved:
- Measurement ownership in the new four-part architecture.
- Consumer behavior for not-observed facts after the boundary split.
-These are tracked as checklist work in [CHECKLIST.md](CHECKLIST.md) rather than as canonical
-decisions.
+These are tracked as checklist work in [CHECKLIST.md](CHECKLIST.md) as `EP-1.4` (not-observed
+behavior), `EP-1+.3` (adapter naming), and `EP-1+.4` (measurement ownership), rather than as
+canonical decisions.
From 1dcd6b6c4863b30e9595c46234a30040247676d2 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 20:11:12 +0000
Subject: [PATCH 14/15] docs(topology-planner): restore EP-D-3 historical
rationale context
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/CHECKLIST.md | 6 +++--
crates/topology-planner/DESIGN-RATIONALE.md | 26 ++++++++++++++-------
2 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/crates/topology-planner/CHECKLIST.md b/crates/topology-planner/CHECKLIST.md
index d9b57dc93..4ca82654f 100644
--- a/crates/topology-planner/CHECKLIST.md
+++ b/crates/topology-planner/CHECKLIST.md
@@ -157,8 +157,10 @@ model question -- they are this component's own.
are graphs of processors and their relations, so "topology" fits all of them and distinguishes
none -- and a reader seeing the word twice will eventually take one for the other. Decide whether
the observed machine keeps the bare name (qualified only by its crate), gains a qualifier, or is
- renamed outright, and what the synthesized arrangement is called. Cheap now; expensive once either
- name is public. This one blocks nothing but should not be settled by whoever writes the first type.
+ renamed outright; what the synthesized arrangement is called; and whether the inward/outward
+ adapters keep those role names or gain more specific crate/type names. Cheap now; expensive once
+ any of those names are public. This one blocks nothing but should not be settled by whoever writes
+ the first type.
- [ ] **EP-1+.4** -- **Assign measurement ownership for directed residency cost in the four-part
architecture.** [EP-D-3](DESIGN-NOTES.md#ep-d-3) requires directed cross-domain cost input with
diff --git a/crates/topology-planner/DESIGN-RATIONALE.md b/crates/topology-planner/DESIGN-RATIONALE.md
index 937c616e3..b81e1f0ce 100644
--- a/crates/topology-planner/DESIGN-RATIONALE.md
+++ b/crates/topology-planner/DESIGN-RATIONALE.md
@@ -6,13 +6,23 @@ in [DESIGN-NOTES.md](DESIGN-NOTES.md).
## EP-D-3 rationale and history
Earlier drafts of EP-D-3 were written against a now-deleted `MachineMemoryTopology::distances`
-field and analyzed whether that field could be repurposed. That framing is retained here as history:
-it explains why a scalar, symmetric distance matrix was considered insufficient for the directional
-residency question and why measured values must carry measurement context, not only provenance.
+field and analyzed whether that field could be repurposed. The current contract boundary is owned by
+[D-20](../windows-topology-sys/DESIGN-NOTES.md#d-20); this section keeps only the historical reasons
+that the old field-centric framing stayed open.
-After [D-20](../windows-topology-sys/DESIGN-NOTES.md#d-20), the relevant boundary is explicit:
-`windows-topology-sys` does not publish below Win32 topology APIs, so residency-cost data must be
-provided by the abstract model path and its adapter/synthesizer inputs.
+The first reason was shape: the planner's question is directional -- which side of a spanning pair
+hosts the shared buffer -- while a scalar, symmetric distance matrix can at best describe the link
+between two domains and not the hop-specific residency choice.
+
+The second reason was evidence. `windows-placement-probe` already supplied directional measurements,
+but every host available when this was written was single-node, so the measured result was vacuous:
+it confirmed that the probe carried direction and measurement context correctly, but it did not yet
+show a real cross-node asymmetry.
+
+That left the D-9 reopening trigger approached but unmet. The planner had reached the point of
+needing a directional cost, but without a machine whose measured result demonstrated that a scalar
+distance mismodels the machine somebody is tuning for, reopening the old topology-field decision
+remained deferred rather than claimed as proved.
## EP-D-4 open follow-ups (historical)
@@ -23,5 +33,5 @@ EP-D-4 intentionally left several follow-ups unresolved:
- Consumer behavior for not-observed facts after the boundary split.
These are tracked as checklist work in [CHECKLIST.md](CHECKLIST.md) as `EP-1.4` (not-observed
-behavior), `EP-1+.3` (adapter naming), and `EP-1+.4` (measurement ownership), rather than as
-canonical decisions.
+behavior), `EP-1+.3` (planner/model/adapter naming), and `EP-1+.4` (measurement ownership), rather
+than as canonical decisions.
From ad62769bded4734140eed3b444bc2aac14b42784 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 18 Sep 2026 20:15:44 +0000
Subject: [PATCH 15/15] docs(topology-planner): identify the component-local
plans tracker
Co-authored-by: MikeGrier <220633264+MikeGrier@users.noreply.github.com>
---
crates/topology-planner/PLANS.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/topology-planner/PLANS.md b/crates/topology-planner/PLANS.md
index fdaa35e93..d515fe976 100644
--- a/crates/topology-planner/PLANS.md
+++ b/crates/topology-planner/PLANS.md
@@ -1,4 +1,4 @@
-# PLANS
+# Plans: topology-planner
| Path to CHECKLIST.md | Status | Brief description | Design Notes |
|---|---|---|---|