@principal-ai/subsystems-react 0.55.3 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/dist/index.d.ts +12 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +6 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/pierre/PierreFileView.js +3 -3
  6. package/dist/pierre/PierreFileView.js.map +1 -1
  7. package/dist/pierre/PierreTrailCodeView.d.ts +1 -6
  8. package/dist/pierre/PierreTrailCodeView.d.ts.map +1 -1
  9. package/dist/pierre/PierreTrailCodeView.js +21 -18
  10. package/dist/pierre/PierreTrailCodeView.js.map +1 -1
  11. package/dist/pierre/fileAvailability.d.ts +4 -7
  12. package/dist/pierre/fileAvailability.d.ts.map +1 -1
  13. package/dist/pierre/fileAvailability.js +5 -10
  14. package/dist/pierre/fileAvailability.js.map +1 -1
  15. package/dist/subsystem/C4Graph.d.ts.map +1 -1
  16. package/dist/subsystem/C4Graph.js +1 -1
  17. package/dist/subsystem/C4Graph.js.map +1 -1
  18. package/dist/subsystem/DecorationPanel.d.ts +37 -0
  19. package/dist/subsystem/DecorationPanel.d.ts.map +1 -0
  20. package/dist/subsystem/DecorationPanel.js +147 -0
  21. package/dist/subsystem/DecorationPanel.js.map +1 -0
  22. package/dist/subsystem/FileDrawer.d.ts +3 -1
  23. package/dist/subsystem/FileDrawer.d.ts.map +1 -1
  24. package/dist/subsystem/FileDrawer.js +2 -2
  25. package/dist/subsystem/FileDrawer.js.map +1 -1
  26. package/dist/subsystem/IssueList.d.ts.map +1 -1
  27. package/dist/subsystem/IssueList.js +26 -0
  28. package/dist/subsystem/IssueList.js.map +1 -1
  29. package/dist/subsystem/SubsystemComponentGraph.d.ts +9 -5
  30. package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
  31. package/dist/subsystem/SubsystemComponentGraph.js +37 -47
  32. package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
  33. package/dist/subsystem/TrailStackBreadcrumb.d.ts +21 -0
  34. package/dist/subsystem/TrailStackBreadcrumb.d.ts.map +1 -0
  35. package/dist/subsystem/TrailStackBreadcrumb.js +77 -0
  36. package/dist/subsystem/TrailStackBreadcrumb.js.map +1 -0
  37. package/dist/subsystem/TrailStepsNav.d.ts +4 -3
  38. package/dist/subsystem/TrailStepsNav.d.ts.map +1 -1
  39. package/dist/subsystem/TrailStepsNav.js +13 -16
  40. package/dist/subsystem/TrailStepsNav.js.map +1 -1
  41. package/dist/subsystem/TrailsPanel.d.ts +9 -7
  42. package/dist/subsystem/TrailsPanel.d.ts.map +1 -1
  43. package/dist/subsystem/TrailsPanel.js +126 -76
  44. package/dist/subsystem/TrailsPanel.js.map +1 -1
  45. package/dist/subsystem/decoration.d.ts +112 -0
  46. package/dist/subsystem/decoration.d.ts.map +1 -0
  47. package/dist/subsystem/decoration.js +54 -0
  48. package/dist/subsystem/decoration.js.map +1 -0
  49. package/dist/subsystem/model.d.ts +5 -18
  50. package/dist/subsystem/model.d.ts.map +1 -1
  51. package/dist/subsystem/model.js +3 -11
  52. package/dist/subsystem/model.js.map +1 -1
  53. package/dist/subsystem/nodes.d.ts.map +1 -1
  54. package/dist/subsystem/nodes.js +17 -24
  55. package/dist/subsystem/nodes.js.map +1 -1
  56. package/dist/subsystem/stepEmphasis.d.ts +78 -0
  57. package/dist/subsystem/stepEmphasis.d.ts.map +1 -0
  58. package/dist/subsystem/stepEmphasis.js +89 -0
  59. package/dist/subsystem/stepEmphasis.js.map +1 -0
  60. package/dist/subsystem/trailBrief.d.ts.map +1 -1
  61. package/dist/subsystem/trailBrief.js +20 -0
  62. package/dist/subsystem/trailBrief.js.map +1 -1
  63. package/dist/subsystem/trailStack.d.ts +53 -0
  64. package/dist/subsystem/trailStack.d.ts.map +1 -0
  65. package/dist/subsystem/trailStack.js +154 -0
  66. package/dist/subsystem/trailStack.js.map +1 -0
  67. package/dist/subsystem/trailStepDisplay.d.ts +38 -0
  68. package/dist/subsystem/trailStepDisplay.d.ts.map +1 -0
  69. package/dist/subsystem/trailStepDisplay.js +41 -0
  70. package/dist/subsystem/trailStepDisplay.js.map +1 -0
  71. package/package.json +3 -3
  72. package/src/index.ts +47 -1
  73. package/src/pierre/PierreFileView.tsx +3 -3
  74. package/src/pierre/PierreTrailCodeView.tsx +25 -28
  75. package/src/pierre/fileAvailability.test.ts +0 -6
  76. package/src/pierre/fileAvailability.ts +5 -13
  77. package/src/stories/Canvases/Subsystem/Deprecated.stories.tsx +3 -17
  78. package/src/stories/Canvases/Subsystem/NodeAnatomy.stories.tsx +3 -31
  79. package/src/stories/Canvases/Subsystem/StepEmphasis.stories.tsx +528 -0
  80. package/src/stories/Canvases/Subsystem/Trails.stories.tsx +0 -187
  81. package/src/stories/Components/DecorationPanel.stories.tsx +160 -0
  82. package/src/subsystem/C4Graph.tsx +0 -1
  83. package/src/subsystem/DecorationPanel.test.tsx +128 -0
  84. package/src/subsystem/DecorationPanel.tsx +334 -0
  85. package/src/subsystem/FileDrawer.tsx +6 -0
  86. package/src/subsystem/IssueList.tsx +26 -0
  87. package/src/subsystem/SubsystemComponentGraph.tsx +68 -65
  88. package/src/subsystem/TrailStackBreadcrumb.test.tsx +109 -0
  89. package/src/subsystem/TrailStackBreadcrumb.tsx +172 -0
  90. package/src/subsystem/TrailStepsNav.test.tsx +35 -0
  91. package/src/subsystem/TrailStepsNav.tsx +18 -19
  92. package/src/subsystem/TrailsPanel.test.tsx +149 -0
  93. package/src/subsystem/TrailsPanel.tsx +165 -39
  94. package/src/subsystem/decoration.test.ts +72 -0
  95. package/src/subsystem/decoration.ts +151 -0
  96. package/src/subsystem/model.test.ts +7 -22
  97. package/src/subsystem/model.ts +6 -20
  98. package/src/subsystem/nodes.tsx +19 -28
  99. package/src/subsystem/stepEmphasis.test.ts +110 -0
  100. package/src/subsystem/stepEmphasis.ts +151 -0
  101. package/src/subsystem/trailBrief.test.ts +29 -0
  102. package/src/subsystem/trailBrief.ts +20 -0
  103. package/src/subsystem/trailStack.test.ts +133 -0
  104. package/src/subsystem/trailStack.ts +229 -0
  105. package/src/subsystem/trailStepDisplay.ts +68 -0
  106. package/src/stories/Canvases/Subsystem/Proposed.stories.tsx +0 -256
  107. package/src/stories/Canvases/Subsystem/ProposedTrails.stories.tsx +0 -184
@@ -0,0 +1,38 @@
1
+ /**
2
+ * How a trail step reads in the Trails panel.
3
+ *
4
+ * A step is one seam, but the panel shows the logical hop and the site in a
5
+ * single wrapping line:
6
+ *
7
+ * - `calls` — the caller frame (the site construct).
8
+ * - `uses` — `from uses to`, where `to` is the precise target when resolved.
9
+ * - Everything else — `from mechanism to`.
10
+ *
11
+ * The evidence site lives in the code view and the stack breadcrumb; the
12
+ * sidebar row stays one line so it can wrap instead of truncating.
13
+ */
14
+ import type { SubsystemTrailStep, SubsystemTrailMechanism } from './model';
15
+ /** The slice of a component the labels need — keeps fixtures light. */
16
+ export interface TrailComponentLabelSource {
17
+ alias: string;
18
+ name?: string;
19
+ symbol?: string;
20
+ }
21
+ /** Alias → component, for turning model-local aliases into display names. */
22
+ export type TrailComponentLabels = ReadonlyMap<string, TrailComponentLabelSource>;
23
+ /** One row's primary text. */
24
+ export interface TrailStepDisplay {
25
+ mechanism: SubsystemTrailMechanism;
26
+ /** The line that names the step: caller frame for `calls`, hop otherwise. */
27
+ primary: string;
28
+ }
29
+ /** Display label for a component alias; falls back to the alias. */
30
+ export declare function trailComponentLabel(alias: string, byAlias?: TrailComponentLabels): string;
31
+ /**
32
+ * Build the single display line for one step.
33
+ *
34
+ * The resolved target (`step.target.symbol`) is the precise callee, while `to`
35
+ * is only a component alias and can be a whole class/store. Prefer the target.
36
+ */
37
+ export declare function trailStepDisplay(step: SubsystemTrailStep, byAlias?: TrailComponentLabels): TrailStepDisplay;
38
+ //# sourceMappingURL=trailStepDisplay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trailStepDisplay.d.ts","sourceRoot":"","sources":["../../src/subsystem/trailStepDisplay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAE3E,uEAAuE;AACvE,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,6EAA6E;AAC7E,MAAM,MAAM,oBAAoB,GAAG,WAAW,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;AAElF,8BAA8B;AAC9B,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,uBAAuB,CAAC;IACnC,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,oBAAoB,GAC7B,MAAM,CAIR;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,kBAAkB,EACxB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,gBAAgB,CAelB"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * How a trail step reads in the Trails panel.
3
+ *
4
+ * A step is one seam, but the panel shows the logical hop and the site in a
5
+ * single wrapping line:
6
+ *
7
+ * - `calls` — the caller frame (the site construct).
8
+ * - `uses` — `from uses to`, where `to` is the precise target when resolved.
9
+ * - Everything else — `from mechanism to`.
10
+ *
11
+ * The evidence site lives in the code view and the stack breadcrumb; the
12
+ * sidebar row stays one line so it can wrap instead of truncating.
13
+ */
14
+ /** Display label for a component alias; falls back to the alias. */
15
+ export function trailComponentLabel(alias, byAlias) {
16
+ const component = byAlias?.get(alias);
17
+ const label = component?.name?.trim() || component?.symbol?.trim();
18
+ return label || alias;
19
+ }
20
+ /**
21
+ * Build the single display line for one step.
22
+ *
23
+ * The resolved target (`step.target.symbol`) is the precise callee, while `to`
24
+ * is only a component alias and can be a whole class/store. Prefer the target.
25
+ */
26
+ export function trailStepDisplay(step, byAlias) {
27
+ const from = trailComponentLabel(step.from, byAlias);
28
+ const to = step.target?.symbol?.trim() || trailComponentLabel(step.to, byAlias);
29
+ const siteSymbol = step.site?.symbol?.trim() || step.symbol?.trim() || from;
30
+ if (step.mechanism === 'calls') {
31
+ return { mechanism: step.mechanism, primary: siteSymbol };
32
+ }
33
+ if (step.mechanism === 'uses') {
34
+ return { mechanism: step.mechanism, primary: `${from} uses ${to}` };
35
+ }
36
+ return {
37
+ mechanism: step.mechanism,
38
+ primary: `${from} ${step.mechanism} ${to}`,
39
+ };
40
+ }
41
+ //# sourceMappingURL=trailStepDisplay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trailStepDisplay.js","sourceRoot":"","sources":["../../src/subsystem/trailStepDisplay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAqBH,oEAAoE;AACpE,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,OAA8B;IAE9B,MAAM,SAAS,GAAG,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACnE,OAAO,KAAK,IAAI,KAAK,CAAC;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAwB,EACxB,OAA8B;IAE9B,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAChF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;IAE5E,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO,EAAE;QAC9B,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;KAC3D;IACD,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,EAAE;QAC7B,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,SAAS,EAAE,EAAE,EAAE,CAAC;KACrE;IACD,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,OAAO,EAAE,GAAG,IAAI,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE,EAAE;KAC3C,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@principal-ai/subsystems-react",
3
- "version": "0.55.3",
3
+ "version": "0.56.0",
4
4
  "description": "React UI for Subsystem Models — graph, Pierre code views, and session-event feeds",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -38,7 +38,7 @@
38
38
  "peerDependencies": {
39
39
  "@pierre/diffs": ">=1.1.20",
40
40
  "@principal-ade/industry-theme": "^0.1.7",
41
- "@principal-ai/subsystems-core": "^0.49.0",
41
+ "@principal-ai/subsystems-core": "^0.50.0",
42
42
  "react": "^18.0.0 || ^19.0.0",
43
43
  "react-dom": "^18.0.0 || ^19.0.0"
44
44
  },
@@ -46,7 +46,7 @@
46
46
  "@pierre/diffs": "1.3.6",
47
47
  "@principal-ade/industry-theme": "0.1.7",
48
48
  "@principal-ai/agent-monitoring": "^0.3.38",
49
- "@principal-ai/subsystems-core": "^0.49.1",
49
+ "@principal-ai/subsystems-core": "^0.50.0",
50
50
  "@storybook/addon-docs": "10.1.2",
51
51
  "@storybook/addon-links": "10.1.2",
52
52
  "@storybook/addon-onboarding": "10.1.2",
package/src/index.ts CHANGED
@@ -218,7 +218,52 @@ export {
218
218
  export type { TrailsPanelProps } from './subsystem/TrailsPanel';
219
219
  export { TrailStepsNav } from './subsystem/TrailStepsNav';
220
220
  export type { TrailStepsNavProps } from './subsystem/TrailStepsNav';
221
+ export { TrailStackBreadcrumb } from './subsystem/TrailStackBreadcrumb';
222
+ export type { TrailStackBreadcrumbProps } from './subsystem/TrailStackBreadcrumb';
223
+ export { buildTrailStack } from './subsystem/trailStack';
224
+ export type {
225
+ TrailStackAnnotation,
226
+ TrailStackFrame,
227
+ TrailStackView,
228
+ } from './subsystem/trailStack';
221
229
  export { buildStepBrief } from './subsystem/trailBrief';
230
+ export {
231
+ buildStepEmphasisMap,
232
+ emphasisForTrail,
233
+ emphasisKey,
234
+ findStepEmphasis,
235
+ orphanedEmphasis,
236
+ stepClaimKey,
237
+ } from './subsystem/stepEmphasis';
238
+ export type {
239
+ StepEmphasisDocument,
240
+ StepEmphasisMap,
241
+ StepEmphasisProvenance,
242
+ StepEmphasisRecord,
243
+ } from './subsystem/stepEmphasis';
244
+ export {
245
+ decorationModelIds,
246
+ decorationTrailId,
247
+ decorationTrailKey,
248
+ findDecorationTrail,
249
+ groupDecorationTrailsByModel,
250
+ } from './subsystem/decoration';
251
+ export type {
252
+ DecorationBaseTrailRef,
253
+ DecorationDraft,
254
+ DecorationDraftComponent,
255
+ DecorationDraftEdge,
256
+ DecorationDraftTrailRef,
257
+ DecorationProvenance,
258
+ DecorationStepAnchor,
259
+ DecorationTrailRef,
260
+ SubsystemDecoration,
261
+ } from './subsystem/decoration';
262
+ export { DecorationPanel } from './subsystem/DecorationPanel';
263
+ export type {
264
+ DecorationPanelProps,
265
+ DecorationPanelTrailMeta,
266
+ } from './subsystem/DecorationPanel';
222
267
  export { GraphLayoutCover } from './subsystem/GraphLayoutCover';
223
268
  export type { GraphLayoutCoverProps } from './subsystem/GraphLayoutCover';
224
269
  export {
@@ -232,6 +277,8 @@ export type {
232
277
  SubsystemComponentEdge,
233
278
  SubsystemTrail,
234
279
  SubsystemTrailStep,
280
+ SubsystemSiteConstruct,
281
+ SubsystemTargetConstruct,
235
282
  SubsystemTrailMechanism,
236
283
  SubsystemModelDocument,
237
284
  SubsystemComponentConstruct,
@@ -315,7 +362,6 @@ export {
315
362
  ROLE_COLOR,
316
363
  ROLE_LABEL,
317
364
  FRAMEWORK_BADGE_COLOR,
318
- PROPOSED_COLOR,
319
365
  } from './subsystem/model';
320
366
  export type {
321
367
  SubsystemSourceSpan,
@@ -105,14 +105,14 @@ export function PierreFileView({
105
105
  );
106
106
 
107
107
  if (error) {
108
- // A file with no local checkout is usually a proposed seam that isn't
109
- // implemented yet — explain that instead of echoing the host error.
108
+ // A file with no local checkout is usually a seam that isn't implemented
109
+ // yet — explain that instead of echoing the host error.
110
110
  if (isFileUnavailableError(error)) {
111
111
  return (
112
112
  <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 4 }}>
113
113
  <span style={{ color: theme.colors.text }}>
114
114
  This file isn't in the local checkout for this repo — it may be
115
- proposed or not yet implemented.
115
+ missing or not yet implemented.
116
116
  </span>
117
117
  <span
118
118
  style={{
@@ -100,11 +100,6 @@ export interface PierreTrailCodeViewProps {
100
100
  * rather than the selected step. Only fires on change, not per scroll event.
101
101
  */
102
102
  onVisibleStepChange?: (index: number) => void;
103
- /**
104
- * Aliases of components marked `proposed`. A step whose file can't be read
105
- * but whose endpoint is proposed reads as "planned" rather than "missing".
106
- */
107
- proposedAliases?: ReadonlySet<string>;
108
103
  /**
109
104
  * Resolve a token to a model construct key (e.g. a component alias) for the
110
105
  * step its snippet belongs to. Return `null` when the token doesn't name a
@@ -138,10 +133,9 @@ function siteKey(step: Pick<SubsystemTrailStep, 'purl' | 'file'>): string {
138
133
  function unavailableNotice(
139
134
  step: SubsystemTrailStep,
140
135
  error: string,
141
- proposed: boolean,
142
136
  ): string {
143
137
  return isFileUnavailableError(error)
144
- ? fileUnavailableNotice(step.file, proposed)
138
+ ? fileUnavailableNotice(step.file)
145
139
  : `Couldn't load ${step.file}: ${error}`;
146
140
  }
147
141
 
@@ -206,7 +200,6 @@ export function PierreTrailCodeView({
206
200
  background: backgroundProp,
207
201
  onOpenFile,
208
202
  onVisibleStepChange,
209
- proposedAliases,
210
203
  resolveSymbol,
211
204
  onSymbolClick,
212
205
  }: PierreTrailCodeViewProps) {
@@ -292,24 +285,15 @@ export function PierreTrailCodeView({
292
285
  scheduleVisibleStepReport();
293
286
  }, [scheduleVisibleStepReport]);
294
287
 
295
- // A step onto a proposed component is planned work; label its missing file
296
- // accordingly instead of showing a bare "not found".
297
- const isProposedStep = useCallback(
298
- (step: SubsystemTrailStep): boolean =>
299
- proposedAliases != null &&
300
- (proposedAliases.has(step.from) || proposedAliases.has(step.to)),
301
- [proposedAliases],
302
- );
303
-
304
288
  const pathsKey = useMemo(() => {
305
289
  const keys = [...new Set(trail.steps.map((s) => siteKey(s)))];
306
290
  keys.sort();
307
291
  return keys.join('\0');
308
292
  }, [trail.steps]);
309
293
 
310
- // Load each site independently: one unreadable step (a proposed seam whose
311
- // file isn't implemented yet) must not blank the whole trail. Failures
312
- // are kept per-path and rendered as inline placeholders below.
294
+ // Load each site independently: one unreadable step must not blank the
295
+ // whole trail. Failures are kept per-path and rendered as inline
296
+ // placeholders below.
313
297
  useEffect(() => {
314
298
  let cancelled = false;
315
299
  setLoad({ status: 'loading' });
@@ -350,15 +334,26 @@ export function PierreTrailCodeView({
350
334
  const failure = load.unavailable.get(key);
351
335
  if (failure != null) {
352
336
  return unavailableSlice(
353
- unavailableNotice(step, failure, isProposedStep(step)),
337
+ unavailableNotice(step, failure),
354
338
  );
355
339
  }
356
340
  const contents = load.byPath.get(key) ?? '';
357
- const start = step.span?.startLine ?? 1;
358
- const end = step.span?.endLine ?? start;
359
- return sliceSnippetWindow(contents, start, end, contextLines, start);
341
+ // A resolved site construct is the frame the reader wants: show its
342
+ // whole declaration and focus the seam line inside it. Older models
343
+ // fall back to a context window around the seam.
344
+ const site = step.site?.span;
345
+ const start = site?.startLine ?? step.span?.startLine ?? 1;
346
+ const end = site?.endLine ?? step.span?.endLine ?? start;
347
+ const focus = step.span?.startLine ?? start;
348
+ return sliceSnippetWindow(
349
+ contents,
350
+ start,
351
+ end,
352
+ site ? 0 : contextLines,
353
+ focus,
354
+ );
360
355
  });
361
- }, [load, trail.steps, contextLines, isProposedStep]);
356
+ }, [load, trail.steps, contextLines]);
362
357
 
363
358
  const items = useMemo((): CodeViewItem<TrailStepAnnotation>[] => {
364
359
  if (load.status !== 'ready' || slices.length === 0) return [];
@@ -392,11 +387,11 @@ export function PierreTrailCodeView({
392
387
  name: step.file,
393
388
  contents: slice.contents,
394
389
  lang: pierreLangForPath(step.file),
395
- cacheKey: `${trail.id}:${index}:${step.file}:${step.span?.startLine ?? ''}:${slice.sliceStart}-${slice.sliceEnd}${failure != null ? ':unavailable' : ''}`,
390
+ cacheKey: `${trail.id}:${index}:${step.file}:${step.span?.startLine ?? ''}:${step.site?.span?.startLine ?? ''}-${step.site?.span?.endLine ?? ''}:${slice.sliceStart}-${slice.sliceEnd}${failure != null ? ':unavailable' : ''}`,
396
391
  },
397
392
  };
398
393
  });
399
- }, [load, slices, trail.id, trail.steps, isProposedStep]);
394
+ }, [load, slices, trail.id, trail.steps]);
400
395
 
401
396
  const selectedLines = useMemo((): CodeViewLineSelection | null => {
402
397
  if (stepIndex == null || stepIndex < 0 || stepIndex >= slices.length) {
@@ -468,7 +463,9 @@ export function PierreTrailCodeView({
468
463
  </span>
469
464
  ) : (
470
465
  <>
471
- L{step.span?.startLine ?? '?'}
466
+ {step.site?.span
467
+ ? `L${step.site.span.startLine}-${step.site.span.endLine}`
468
+ : `L${step.span?.startLine ?? '?'}`}
472
469
  {onOpenFile && (
473
470
  <OpenFileHeaderButton
474
471
  file={step.file}
@@ -23,12 +23,6 @@ describe('isFileUnavailableError', () => {
23
23
  });
24
24
 
25
25
  describe('fileUnavailableNotice', () => {
26
- test('names proposed work as planned, not missing', () => {
27
- expect(
28
- fileUnavailableNotice('src/a.ts', true),
29
- ).toBe("Proposed — src/a.ts isn't in the local checkout yet.");
30
- });
31
-
32
26
  test('falls back to a plain not-in-checkout notice', () => {
33
27
  expect(fileUnavailableNotice('src/a.ts')).toBe(
34
28
  'Not in the local checkout: src/a.ts',
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Host file reads fail with a small, stable set of messages when a path can't
3
- * be served from any local checkout — most often a *proposed* seam whose file
4
- * isn't implemented yet. These helpers detect that class of failure so the
5
- * Pierre views can show a proposed / not-yet-available notice instead of a raw
3
+ * be served from any local checkout. These helpers detect that class of failure
4
+ * so the Pierre views can show a not-yet-available notice instead of a raw
6
5
  * host error.
7
6
  */
8
7
 
@@ -23,15 +22,8 @@ export function isFileUnavailableError(
23
22
  }
24
23
 
25
24
  /**
26
- * One-line notice shown in place of a snippet whose file can't be read. When
27
- * the step touches a proposed component the wording names that, so a proposed
28
- * seam reads as "planned" rather than "missing".
25
+ * One-line notice shown in place of a snippet whose file can't be read.
29
26
  */
30
- export function fileUnavailableNotice(
31
- path: string,
32
- proposed?: boolean,
33
- ): string {
34
- return proposed
35
- ? `Proposed — ${path} isn't in the local checkout yet.`
36
- : `Not in the local checkout: ${path}`;
27
+ export function fileUnavailableNotice(path: string): string {
28
+ return `Not in the local checkout: ${path}`;
37
29
  }
@@ -12,9 +12,8 @@ import type {
12
12
  import { trailFromSteps } from './fixtures';
13
13
 
14
14
  /**
15
- * `deprecated` is the inverse of `proposed`: the claim was real, its source is
16
- * gone upstream. Mirrors Proposed.stories.tsx so the two temporary states read
17
- * as siblings — proposed = not built yet, deprecated = built once, removed since.
15
+ * `deprecated` marks a claim whose source is gone upstream. The node keeps a
16
+ * transitional marker until a cleanup pass removes it.
18
17
  */
19
18
  const meta = {
20
19
  title: 'Canvases/Subsystem/Deprecated',
@@ -154,22 +153,9 @@ const spotlightRows: Array<{ label: string; component: SubsystemComponent }> = [
154
153
  role: 'entry',
155
154
  },
156
155
  },
157
- {
158
- label: 'proposed (the sibling temporary state)',
159
- component: {
160
- alias: 'prop-fn',
161
- name: 'OpenCodeV2Lifecycle',
162
- construct: 'function',
163
- file: '',
164
- purl: PURL,
165
- symbol: 'OpenCodeV2Lifecycle',
166
- purpose: 'Proposed Studio host lifecycle',
167
- proposed: true,
168
- },
169
- },
170
156
  ];
171
157
 
172
- /** Spotlights: slate deprecated badge + border vs live, proposed, and entry. */
158
+ /** Spotlights: slate deprecated badge + border vs live and entry. */
173
159
  export const Spotlights: Story = {
174
160
  render: () => (
175
161
  <div
@@ -142,33 +142,6 @@ const CHANNELS: Channel[] = [
142
142
  declaration: storeDetail,
143
143
  },
144
144
  },
145
- {
146
- label: 'proposed',
147
- note: 'dashed goldenrod border + right badge; fileless.',
148
- component: {
149
- alias: 'prop',
150
- name: 'OpenCodeV2Lifecycle',
151
- construct: 'function',
152
- file: '',
153
- purl: PURL,
154
- symbol: 'OpenCodeV2Lifecycle',
155
- proposed: true,
156
- },
157
- },
158
- {
159
- label: 'proposed + role',
160
- note: 'proposed wins the right badge; role stays on the model.',
161
- component: {
162
- alias: 'prop-role',
163
- name: 'startMaintainFlow',
164
- construct: 'function',
165
- file: '',
166
- purl: PURL,
167
- symbol: 'startMaintainFlow',
168
- proposed: true,
169
- role: 'service',
170
- },
171
- },
172
145
  {
173
146
  label: 'framework stereotype',
174
147
  note: 'left badge prefers "framework · stereotype"; border stays construct.',
@@ -230,11 +203,11 @@ function ChannelCell({ channel }: { channel: Channel }) {
230
203
 
231
204
  const LEGEND: Array<[string, string]> = [
232
205
  ['border color', 'construct kind (Pierre palette) — or primary when a file is open (spotlight)'],
233
- ['border style', 'solid normally; dashed goldenrod when `proposed`; dotted when the node has findings'],
206
+ ['border style', 'solid normally; dotted when the node has findings'],
234
207
  ['border width', '2px; 4px when selected or file-matched'],
235
208
  ['corners', '8px rounded; square for `external`'],
236
209
  ['left badge (top edge)', 'construct / framework stereotype / entityKind'],
237
- ['right badge (top edge)', 'role, or `proposed` (wins); storage sits beside it'],
210
+ ['right badge (top edge)', 'role; storage sits beside it'],
238
211
  ['bottom strip (bottom edge)', 'filename — hover only, or while that file is open'],
239
212
  ['fill', 'backgroundSecondary; opacity 0.18 when dimmed'],
240
213
  ['OCCUPIED', 'top-left · top-right · bottom-center · border · fill'],
@@ -439,8 +412,7 @@ export const IssueOverlayProposal: Story = {
439
412
  </div>
440
413
  <ul style={{ margin: 0, paddingLeft: 18, fontSize: 12, lineHeight: 1.7, color: '#b0b0b0' }}>
441
414
  <li>
442
- <b>Dotted border</b> (keeps the construct color) = the node has findings — a sibling of
443
- <b> proposed</b>&apos;s dashed, kept distinct so the two don&apos;t read alike.
415
+ <b>Dotted border</b> (keeps the construct color) = the node has findings.
444
416
  </li>
445
417
  <li>
446
418
  <b>Corner chip</b> carries severity (<b>red</b> = error / contradicts source,{' '}