1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright 2024-2026 Jonathan Shook
// SPDX-License-Identifier: Apache-2.0
//! Scope coordinates — the formal GK-side model of the
//! iteration position a kernel occupies inside an enclosing
//! comprehension chain.
//!
//! ## Definition
//!
//! A **scope coordinate set** for a single scope is the
//! ordered name→value tuple of every iteration extern that
//! scope owns — i.e. variables the scope declared via
//! `extern <var>: <type>` and that aren't mirroring an outer
//! scope (`is_inherited` returns false in this scope's program).
//! The order is the declaration order from the comprehension's
//! source (preserved by `IndexMap`'s insertion semantics).
//!
//! A **scope coordinate path** is the leaf-first list of
//! coordinate sets, walking from the kernel's own scope up
//! through every enclosing comprehension scope. Workload-root
//! params (top-level `params:` in the document) don't
//! contribute — they're configuration, not iteration
//! coordinates.
//!
//! ## Invariant
//!
//! Every kernel that has been *initialised in its scope* —
//! either via [`super::GkKernel::materialize_wiring_from_outer`] (post-bind
//! the path is `[own] ++ outer.scope_coordinates()`), or as a
//! root scope (path is `[own]` if non-empty, else empty) —
//! has [`super::GkKernel::scope_coordinates`] populated. This
//! is treated as a structural invariant of the GK model, not
//! an optional add-on: the runtime contract is that any
//! consumer (presentation layer, inspector, future scope-aware
//! diagnostics) can call `scope_coordinates()` on an
//! initialised kernel and get the full path back without
//! needing to walk the scope tree itself.
//!
//! ## Use
//!
//! Presentation-layer consumers (the inline status line, TUI
//! phase rows, the inspector socket) render the path as
//! striated parens — `(leaf coords), (parent coords), …` —
//! so the operator can read the active iteration off each
//! enclosing scope at a glance. Without striation the
//! operator can't tell which `k=10` belongs to the inner
//! comprehension vs. an outer one with the same coord name
//! in a different shape.
//!
//! See SRD 18b §"Iteration variables as scope outputs" for
//! how comprehension scopes synthesise the `extern` slots
//! that this module classifies as coordinates.
use IndexMap;
use crateValue;
/// One scope's worth of iteration coordinates — the LHS names
/// and current values of every `extern <var>: <type>` clause
/// that scope declared (excluding ones inherited from a parent).
///
/// Ordered by declaration position. The map is empty for scopes
/// that don't own any coordinates (e.g. a scenario node that's
/// just a list of phases — no comprehension at that level).
/// Helper for building a coord set from `(name, Value)` pairs.
/// Format a scope-coordinate path as striated parens, leaf-first:
/// `(k=10, limit=20), (table=…, optimize_for=…)`. Empty strata
/// are skipped, so a chain that passes through a non-comprehension
/// scope (e.g. a scenario node that's just a phase list) doesn't
/// render an empty `()`. Returns `""` for an empty path so callers
/// can wrap with `(…)` parens at their own discretion.
///
/// **Canonical structural identity.** This is the formatter every
/// consumer reasoning about a kernel's iteration position runs
/// through — runtime executor labels, pre-map walker labels,
/// inline status lines, scene-tree labels, error messages. Pre-map
/// and runtime producing the same string for the same iteration
/// position is what lets observer lifecycle calls bind to
/// pre-mapped scene nodes without a parallel matching scheme.