@formicoidea/labre-framework-cynefin 0.31.0 → 0.33.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.
@@ -0,0 +1,41 @@
1
+ import type { QualityNudge } from '@formicoidea/labre-core/blocks/surface';
2
+ /**
3
+ * Estuarine **map quality** — the checklist, and this framework's ENTIRE
4
+ * contribution to validation (WS4).
5
+ *
6
+ * ## No rules, and therefore no profiles (PO arbitration, 26/08/2026)
7
+ *
8
+ * The 26/08 study looked for deterministic rules on an Estuarine map and found
9
+ * none worth shipping. Everything an Estuarine session decides — where the
10
+ * counter-factual line falls, which constraints are volatile, whether a
11
+ * constraint is a constructor or an actor — is a judgement the group makes out
12
+ * loud; an algorithm that claimed to check any of it would be lying about the
13
+ * one thing the method exists to produce.
14
+ *
15
+ * A severity profile is a dial over rules. With no rule to dial, a profile
16
+ * picker is a control that decides nothing: three entries, no observable
17
+ * effect, and a user reasonably concluding that the tool checks something it
18
+ * does not. So this framework ships **no `profiles.ts`** — deliberately, not
19
+ * by omission. The profiles will be born WITH the first rule, if one is ever
20
+ * born; until then the file's absence is the honest statement.
21
+ *
22
+ * What does reach the user is this checklist, offered on the map because
23
+ * `ValidationFrameworkExtension` declares `estuarine:map` a root instance
24
+ * (WS0.3) — the gate no longer needs a rule to exist.
25
+ *
26
+ * Registered from the flag-gated `CynefinEstuarineViewExtension`, beside the
27
+ * framework declaration: a checklist is tooling. Switching the flag off takes
28
+ * it away and leaves the ticks written on the map, unread, until it comes back.
29
+ */
30
+ /**
31
+ * **Q1–Q4** — the four things an Estuarine map needs in order to do its job,
32
+ * and that no algorithm can check.
33
+ *
34
+ * Q1 and Q2 are about the two lines that make the map a map: a counter-factual
35
+ * line nobody argued over is a curve, not a boundary, and an undelimited
36
+ * volatile zone leaves every constraint equally urgent. Q3 is the method's own
37
+ * discipline — above the counter-factual line you do not act, you Monitor,
38
+ * Research or Request. Q4 is the typing the hexagons carry in the group's head
39
+ * and nowhere in the document.
40
+ */
41
+ export declare const ESTUARINE_NUDGES: readonly QualityNudge[];
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Estuarine **map quality** — the checklist, and this framework's ENTIRE
3
+ * contribution to validation (WS4).
4
+ *
5
+ * ## No rules, and therefore no profiles (PO arbitration, 26/08/2026)
6
+ *
7
+ * The 26/08 study looked for deterministic rules on an Estuarine map and found
8
+ * none worth shipping. Everything an Estuarine session decides — where the
9
+ * counter-factual line falls, which constraints are volatile, whether a
10
+ * constraint is a constructor or an actor — is a judgement the group makes out
11
+ * loud; an algorithm that claimed to check any of it would be lying about the
12
+ * one thing the method exists to produce.
13
+ *
14
+ * A severity profile is a dial over rules. With no rule to dial, a profile
15
+ * picker is a control that decides nothing: three entries, no observable
16
+ * effect, and a user reasonably concluding that the tool checks something it
17
+ * does not. So this framework ships **no `profiles.ts`** — deliberately, not
18
+ * by omission. The profiles will be born WITH the first rule, if one is ever
19
+ * born; until then the file's absence is the honest statement.
20
+ *
21
+ * What does reach the user is this checklist, offered on the map because
22
+ * `ValidationFrameworkExtension` declares `estuarine:map` a root instance
23
+ * (WS0.3) — the gate no longer needs a rule to exist.
24
+ *
25
+ * Registered from the flag-gated `CynefinEstuarineViewExtension`, beside the
26
+ * framework declaration: a checklist is tooling. Switching the flag off takes
27
+ * it away and leaves the ticks written on the map, unread, until it comes back.
28
+ */
29
+ /**
30
+ * **Q1–Q4** — the four things an Estuarine map needs in order to do its job,
31
+ * and that no algorithm can check.
32
+ *
33
+ * Q1 and Q2 are about the two lines that make the map a map: a counter-factual
34
+ * line nobody argued over is a curve, not a boundary, and an undelimited
35
+ * volatile zone leaves every constraint equally urgent. Q3 is the method's own
36
+ * discipline — above the counter-factual line you do not act, you Monitor,
37
+ * Research or Request. Q4 is the typing the hexagons carry in the group's head
38
+ * and nowhere in the document.
39
+ */
40
+ export const ESTUARINE_NUDGES = [
41
+ {
42
+ id: 'estuarine.q1-counterfactual',
43
+ framework: 'estuarine',
44
+ labelKey: 'com.labre.estuarine.quality.counterfactual',
45
+ fallback: 'The counter-factual line has been negotiated and drawn by the group',
46
+ order: 1,
47
+ },
48
+ {
49
+ id: 'estuarine.q2-volatile-zone',
50
+ framework: 'estuarine',
51
+ labelKey: 'com.labre.estuarine.quality.volatile-zone',
52
+ fallback: 'The volatile zone has been delimited',
53
+ order: 2,
54
+ },
55
+ {
56
+ id: 'estuarine.q3-strategies',
57
+ framework: 'estuarine',
58
+ labelKey: 'com.labre.estuarine.quality.strategies',
59
+ fallback: 'Every element above the counter-factual line has a Monitor, Research or Request strategy',
60
+ order: 3,
61
+ },
62
+ {
63
+ id: 'estuarine.q4-hexagon-types',
64
+ framework: 'estuarine',
65
+ labelKey: 'com.labre.estuarine.quality.hexagon-types',
66
+ fallback: 'Every hexagon is typed: constraint, constructor or actor',
67
+ order: 4,
68
+ },
69
+ ];
@@ -0,0 +1,48 @@
1
+ import type { RoleDefs } from '@formicoidea/labre-core/std/gfx';
2
+ /**
3
+ * Estuarine role vocabulary (WS4).
4
+ *
5
+ * Two roles, and deliberately only two: the MAP — the axes and the three
6
+ * reference curves an Estuarine session is read against — and the CONSTRAINT
7
+ * hexagon the group drops onto it. Everything else on such a board (the
8
+ * captions, the stickies, a free arrow drawn to link two hexagons) is a plain
9
+ * drawing and stays neutral, because nothing in this framework has anything to
10
+ * say about it.
11
+ *
12
+ * ## Cynefin declares NO role, and never will
13
+ *
14
+ * The two frameworks share this package and share nothing else here. The PO's
15
+ * arbitration of 26/08/2026 is that Cynefin is out of the validation perimeter
16
+ * for good: its four domains are a sense-making device, not a notation with
17
+ * rules, so giving its background a role would advertise tooling — a profile
18
+ * picker, a quality checklist — over a framework that has nothing to check.
19
+ * A role with no consumer is a promise the product does not keep.
20
+ *
21
+ * ## What a role buys Estuarine, which ships no rule either
22
+ *
23
+ * The map role is what makes the map a ROOT INSTANCE: it is handed to
24
+ * `ValidationFrameworkExtension` so the engine can answer "is this element
25
+ * somebody's frame?" and offer the Map quality checklist on it. That gate used
26
+ * to be derived from the registered rules alone, which is exactly why WS0.3
27
+ * gave it a second, explicit source — see `ValidationFrameworkDef`.
28
+ *
29
+ * The constraint role earns its keep on its own: a hexagon is a plain polygon
30
+ * shape on the canvas, so nothing about its geometry says what it means, and
31
+ * the first rule this framework ever writes will be written against this role
32
+ * rather than against `shapeType === 'polygon'`.
33
+ *
34
+ * ## Compatibility
35
+ *
36
+ * No backfill (promise #71): maps and hexagons drawn before today carry no
37
+ * role, are nobody's frame, and go on painting exactly as they did. They simply
38
+ * offer no checklist until they are redrawn.
39
+ */
40
+ /** Every role this framework declares. */
41
+ export type EstuarineRole = 'map' | 'constraint';
42
+ export type EstuarineRoleId = `estuarine:${EstuarineRole}`;
43
+ /** Role ids, keyed by the name used at the creation sites. */
44
+ export declare const ESTUARINE_ROLE: {
45
+ readonly map: "estuarine:map";
46
+ readonly constraint: "estuarine:constraint";
47
+ };
48
+ export declare const ESTUARINE_ROLES: RoleDefs;
@@ -0,0 +1,28 @@
1
+ /** Role ids, keyed by the name used at the creation sites. */
2
+ export const ESTUARINE_ROLE = {
3
+ map: 'estuarine:map',
4
+ constraint: 'estuarine:constraint',
5
+ };
6
+ const DEFS = [
7
+ // The map itself: the e / t axes and the three curves everything else is
8
+ // positioned against. A frame, so it specialises nothing — a rule written on
9
+ // `estuarine:constraint` must never match the map it is measured against.
10
+ {
11
+ id: ESTUARINE_ROLE.map,
12
+ kind: 'node',
13
+ labelKey: 'com.labre.estuarine.role.map',
14
+ labelFallback: 'Estuarine map',
15
+ },
16
+ // The hexi constraint. A `node`: it is measured by its bounds, which is
17
+ // exactly what an Estuarine reading is about — where on the energy/time
18
+ // plane the group placed this constraint.
19
+ {
20
+ id: ESTUARINE_ROLE.constraint,
21
+ kind: 'node',
22
+ labelKey: 'com.labre.estuarine.role.constraint',
23
+ labelFallback: 'Constraint',
24
+ },
25
+ ];
26
+ // Null prototype: a lookup table keyed by ids that may one day come from
27
+ // host-supplied packs, so `defs['toString']` must not resolve.
28
+ export const ESTUARINE_ROLES = Object.assign(Object.create(null), Object.fromEntries(DEFS.map(def => [def.id, def])));
@@ -3,13 +3,67 @@ import { EstuarineElementModel } from '@formicoidea/labre-core/model';
3
3
  import { ToolbarModuleExtension, } from '@formicoidea/labre-core/shared/services';
4
4
  import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
5
5
  import { html } from 'lit';
6
- const ResizeIcon = html `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5H5v4M15 19h4v-4" /><path d="M5 5l6 6M19 19l-6-6" /></svg>`;
6
+ const ResizeIcon = html `<svg
7
+ width="24"
8
+ height="24"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ stroke-width="1.6"
13
+ stroke-linecap="round"
14
+ stroke-linejoin="round"
15
+ >
16
+ <path d="M9 5H5v4M15 19h4v-4" />
17
+ <path d="M5 5l6 6M19 19l-6-6" />
18
+ </svg>`;
7
19
  // All curve icons use currentColor so the toolbar can grey them when inactive;
8
20
  // they are distinguished by shape (wave / arc / hooked curve).
9
- const LiminalIcon = html `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M3 13c3-6 6 4 9 0s6-6 9 0" /></svg>`;
10
- const VolatileIcon = html `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M7 4a9 9 0 0 1 0 18" /></svg>`;
11
- const CounterfactualIcon = html `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 7c7 0 11 4 12 14" /></svg>`;
12
- const AxisIcon = html `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3v18M6 12h15" /><path d="M3 6l3-3 3 3M18 9l3 3-3 3" /></svg>`;
21
+ const LiminalIcon = html `<svg
22
+ width="24"
23
+ height="24"
24
+ viewBox="0 0 24 24"
25
+ fill="none"
26
+ stroke="currentColor"
27
+ stroke-width="2"
28
+ stroke-linecap="round"
29
+ >
30
+ <path d="M3 13c3-6 6 4 9 0s6-6 9 0" />
31
+ </svg>`;
32
+ const VolatileIcon = html `<svg
33
+ width="24"
34
+ height="24"
35
+ viewBox="0 0 24 24"
36
+ fill="none"
37
+ stroke="currentColor"
38
+ stroke-width="2"
39
+ stroke-linecap="round"
40
+ >
41
+ <path d="M7 4a9 9 0 0 1 0 18" />
42
+ </svg>`;
43
+ const CounterfactualIcon = html `<svg
44
+ width="24"
45
+ height="24"
46
+ viewBox="0 0 24 24"
47
+ fill="none"
48
+ stroke="currentColor"
49
+ stroke-width="2"
50
+ stroke-linecap="round"
51
+ >
52
+ <path d="M4 7c7 0 11 4 12 14" />
53
+ </svg>`;
54
+ const AxisIcon = html `<svg
55
+ width="24"
56
+ height="24"
57
+ viewBox="0 0 24 24"
58
+ fill="none"
59
+ stroke="currentColor"
60
+ stroke-width="1.6"
61
+ stroke-linecap="round"
62
+ stroke-linejoin="round"
63
+ >
64
+ <path d="M6 3v18M6 12h15" />
65
+ <path d="M3 6l3-3 3 3M18 9l3 3-3 3" />
66
+ </svg>`;
13
67
  function booleanToggle(id, tooltip, icon, prop) {
14
68
  return {
15
69
  id,
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
- export {};
1
+ export { cynefinEstuarineCommandIcons, cynefinEstuarineCommands, } from './commands.js';
2
+ export { cynefinEstuarineTranslationEntries } from './translations.js';
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
- export {};
1
+ export { cynefinEstuarineCommandIcons, cynefinEstuarineCommands, } from './commands.js';
2
+ export { cynefinEstuarineTranslationEntries } from './translations.js';
@@ -2,6 +2,7 @@ import { makeTemplateSnapshot, surfaceText, } from '@formicoidea/labre-core/gfx/
2
2
  import { FontFamily, ShapeStyle, TextAlign } from '@formicoidea/labre-core/model';
3
3
  import { REF_H as CYN_H, REF_W as CYN_W } from '../cynefin/consts.js';
4
4
  import { HEX_FILL, HEX_SIZE, HEX_STROKE, HEX_VERTICES, REF_H as EST_H, REF_W as EST_W, } from '../estuarine/consts.js';
5
+ import { ESTUARINE_ROLE } from '../estuarine/roles.js';
5
6
  function sticky(x, y, text) {
6
7
  return {
7
8
  type: 'shape',
@@ -24,6 +25,9 @@ function sticky(x, y, text) {
24
25
  function hexagon(x, y) {
25
26
  return {
26
27
  type: 'shape',
28
+ // Same role the toolbox stamps (`actions.ts`): a template must produce the
29
+ // map a user would have drawn by hand, roles included.
30
+ role: ESTUARINE_ROLE.constraint,
27
31
  shapeType: 'polygon',
28
32
  vertices: HEX_VERTICES,
29
33
  filled: true,
@@ -47,11 +51,23 @@ function caption(x, y, str) {
47
51
  };
48
52
  }
49
53
  function tpl(name, preview, elements) {
50
- return { name, type: 'template', preview, content: makeTemplateSnapshot(elements, name) };
54
+ return {
55
+ name,
56
+ type: 'template',
57
+ preview,
58
+ content: makeTemplateSnapshot(elements, name),
59
+ };
51
60
  }
52
61
  const ATTRS = 'width="100%" height="100%" viewBox="0 0 135 80" xmlns="http://www.w3.org/2000/svg"';
62
+ // Cynefin's background carries NO role, deliberately and for good: the
63
+ // framework is out of the validation perimeter (PO, 26/08/2026). See
64
+ // `estuarine/roles.ts`.
53
65
  const cynefinBg = (xywh) => ({ type: 'cynefin', xywh });
54
- const estuarineBg = (xywh) => ({ type: 'estuarine', xywh });
66
+ const estuarineBg = (xywh) => ({
67
+ type: 'estuarine',
68
+ role: ESTUARINE_ROLE.map,
69
+ xywh,
70
+ });
55
71
  export const cynefinTemplateCategory = {
56
72
  name: 'Cynefin',
57
73
  templates: [
@@ -1,17 +1,11 @@
1
1
  import { EmptyTool } from '@formicoidea/labre-core/gfx/pointer';
2
- import { LitElement } from 'lit';
3
- declare const EdgelessCynefinEstuarineMenu_base: typeof LitElement & import("@formicoidea/labre-core/_pkgs/global/utils").Constructor<import("@formicoidea/labre-core/_pkgs/affine-widget-edgeless-toolbar").EdgelessToolbarToolClass>;
2
+ import { EdgelessCommandMenu } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
4
3
  /**
5
- * The popover above the toolbar hosting both frameworks: create the Cynefin
6
- * diagram, the Estuarine map, or a hexagon constraint node.
4
+ * The popover above the toolbar hosting both frameworks. Since PF3 it declares
5
+ * nothing: {@link EdgelessCommandMenu} renders `cynefinEstuarineCommands` for
6
+ * the `senior-menu` surface (`docs/adr/0008`).
7
7
  */
8
- export declare class EdgelessCynefinEstuarineMenu extends EdgelessCynefinEstuarineMenu_base {
9
- static styles: import("lit").CSSResult;
8
+ export declare class EdgelessCynefinEstuarineMenu extends EdgelessCommandMenu {
9
+ protected owner: "cynefin-estuarine";
10
10
  type: typeof EmptyTool;
11
- private _finish;
12
- private _createCynefin;
13
- private _createMap;
14
- private _createHexagon;
15
- render(): import("lit-html").TemplateResult<1>;
16
11
  }
17
- export {};
@@ -1,122 +1,14 @@
1
- import { DefaultTool } from '@formicoidea/labre-core/blocks/surface';
2
1
  import { EmptyTool } from '@formicoidea/labre-core/gfx/pointer';
3
- import { ShapeStyle, TextFitMode } from '@formicoidea/labre-core/model';
4
- import { EdgelessToolbarToolMixin } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
5
- import { Bound } from '@formicoidea/labre-core/global/gfx';
6
- import { css, html, LitElement } from 'lit';
7
- import { REF_H as CYN_H, REF_W as CYN_W } from '../cynefin/consts.js';
8
- import { HEX_FILL, HEX_SIZE, HEX_STROKE, HEX_VERTICES, REF_H as EST_H, REF_W as EST_W, } from '../estuarine/consts.js';
9
- import { cynefinMenuIcon, estuarineMenuIcon, hexagonMenuIcon, } from './icons.js';
10
- /** Estuarine map default size (REF aspect, scaled up so it reads on canvas). */
11
- const MAP_SCALE = 1.2;
2
+ import { EdgelessCommandMenu } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
12
3
  /**
13
- * The popover above the toolbar hosting both frameworks: create the Cynefin
14
- * diagram, the Estuarine map, or a hexagon constraint node.
4
+ * The popover above the toolbar hosting both frameworks. Since PF3 it declares
5
+ * nothing: {@link EdgelessCommandMenu} renders `cynefinEstuarineCommands` for
6
+ * the `senior-menu` surface (`docs/adr/0008`).
15
7
  */
16
- export class EdgelessCynefinEstuarineMenu extends EdgelessToolbarToolMixin(LitElement) {
8
+ export class EdgelessCynefinEstuarineMenu extends EdgelessCommandMenu {
17
9
  constructor() {
18
10
  super(...arguments);
11
+ this.owner = 'cynefin-estuarine';
19
12
  this.type = EmptyTool;
20
13
  }
21
- static { this.styles = css `
22
- :host {
23
- display: flex;
24
- z-index: -1;
25
- justify-content: center;
26
- }
27
- .menu-content {
28
- display: flex;
29
- align-items: center;
30
- justify-content: center;
31
- }
32
- .button-group-container {
33
- display: flex;
34
- align-items: center;
35
- gap: 14px;
36
- fill: var(--affine-icon-color);
37
- }
38
- .button-group-container svg {
39
- width: 24px;
40
- height: 24px;
41
- }
42
- `; }
43
- _finish(id) {
44
- const { gfx } = this;
45
- gfx.doc.captureSync();
46
- gfx.tool.setTool(DefaultTool);
47
- gfx.selection.set({ elements: [id], editing: false });
48
- }
49
- _createCynefin() {
50
- const { gfx } = this;
51
- if (!gfx.surface)
52
- return;
53
- const { centerX, centerY } = gfx.viewport;
54
- const id = gfx.surface.addElement({
55
- type: 'cynefin',
56
- xywh: new Bound(centerX - CYN_W / 2, centerY - CYN_H / 2, CYN_W, CYN_H).serialize(),
57
- });
58
- this._finish(id);
59
- }
60
- _createMap() {
61
- const { gfx } = this;
62
- if (!gfx.surface)
63
- return;
64
- const width = EST_W * MAP_SCALE;
65
- const height = EST_H * MAP_SCALE;
66
- const { centerX, centerY } = gfx.viewport;
67
- const id = gfx.surface.addElement({
68
- type: 'estuarine',
69
- xywh: new Bound(centerX - width / 2, centerY - height / 2, width, height).serialize(),
70
- });
71
- this._finish(id);
72
- }
73
- _createHexagon() {
74
- const { gfx } = this;
75
- if (!gfx.surface)
76
- return;
77
- const { centerX: cx, centerY: cy } = gfx.viewport;
78
- const id = gfx.surface.addElement({
79
- type: 'shape',
80
- shapeType: 'polygon',
81
- vertices: HEX_VERTICES,
82
- filled: true,
83
- fillColor: HEX_FILL,
84
- strokeColor: HEX_STROKE,
85
- strokeWidth: 2,
86
- shapeStyle: ShapeStyle.General,
87
- roughness: 0,
88
- // hexi constraints behave like post-its: fixed hex, text shrinks
89
- textFitMode: TextFitMode.Contained,
90
- xywh: new Bound(cx - HEX_SIZE / 2, cy - HEX_SIZE / 2, HEX_SIZE, HEX_SIZE).serialize(),
91
- });
92
- this._finish(id);
93
- }
94
- render() {
95
- return html `
96
- <edgeless-slide-menu>
97
- <div class="menu-content">
98
- <div class="button-group-container">
99
- <edgeless-tool-icon-button
100
- .tooltip=${'Cynefin framework'}
101
- @click=${this._createCynefin}
102
- >
103
- ${cynefinMenuIcon}
104
- </edgeless-tool-icon-button>
105
- <edgeless-tool-icon-button
106
- .tooltip=${'Estuarine map'}
107
- @click=${this._createMap}
108
- >
109
- ${estuarineMenuIcon}
110
- </edgeless-tool-icon-button>
111
- <edgeless-tool-icon-button
112
- .tooltip=${'Hexagon node'}
113
- @click=${this._createHexagon}
114
- >
115
- ${hexagonMenuIcon}
116
- </edgeless-tool-icon-button>
117
- </div>
118
- </div>
119
- </edgeless-slide-menu>
120
- `;
121
- }
122
14
  }
@@ -1,5 +1,6 @@
1
1
  import { DefaultTool } from '@formicoidea/labre-core/blocks/surface';
2
2
  import { EmptyTool } from '@formicoidea/labre-core/gfx/pointer';
3
+ import { translateKey } from '@formicoidea/labre-core/shared/services';
3
4
  import { EdgelessToolbarToolMixin } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
4
5
  import { SignalWatcher } from '@formicoidea/labre-core/global/lit';
5
6
  import { css, html, LitElement } from 'lit';
@@ -64,7 +65,9 @@ export class EdgelessCynefinEstuarineSeniorButton extends EdgelessToolbarToolMix
64
65
  render() {
65
66
  return html `<edgeless-toolbar-button
66
67
  class="ce-button"
67
- .tooltip=${this.popper ? '' : 'Cynefin / Estuarine'}
68
+ .tooltip=${this.popper
69
+ ? ''
70
+ : translateKey(this.edgeless.std, 'com.labre.framework.cynefin-estuarine', 'Cynefin / Estuarine')}
68
71
  .tooltipOffset=${4}
69
72
  .active=${!!this.popper}
70
73
  @click=${this._toggleMenu}
@@ -4,6 +4,7 @@ import { html } from 'lit';
4
4
  export const cynefinEstuarineSeniorTool = SeniorToolExtension('cynefin-estuarine', ({ block }) => {
5
5
  return {
6
6
  name: 'Cynefin / Estuarine',
7
+ labelKey: 'com.labre.framework.cynefin-estuarine',
7
8
  content: html `<edgeless-cynefin-estuarine-senior-button
8
9
  .edgeless=${block}
9
10
  ></edgeless-cynefin-estuarine-senior-button>`,
@@ -0,0 +1,19 @@
1
+ import { type TranslationKeyManifestEntry } from '@formicoidea/labre-core/std';
2
+ /**
3
+ * THIS framework's contribution to the translation-key manifest.
4
+ *
5
+ * Since WS4 it also carries the Estuarine ROLE labels and the four Map quality
6
+ * NUDGES — the framework's entire validation vocabulary, since it declares no
7
+ * rule and no profile (`estuarine/nudges.ts`). Cynefin contributes neither,
8
+ * having no role of its own.
9
+ *
10
+ * Its command labels and descriptions are built from a TEMPLATE, so the
11
+ * concrete keys exist nowhere but in the declarations themselves and the
12
+ * core manifest could not restate them even if it wanted to. The
13
+ * contribution therefore ships WITH the framework: in the bundled
14
+ * distribution `@formicoidea/labre-framework-cynefin` carries it, and a host
15
+ * composes it into its catalogue exactly as it already composes
16
+ * `cynefinEstuarineCommands` into the command registry. See
17
+ * `packages/affine/all/src/translations.ts`.
18
+ */
19
+ export declare const cynefinEstuarineTranslationEntries: TranslationKeyManifestEntry[];
@@ -0,0 +1,22 @@
1
+ import { collectTranslationKeys, commandTranslationEntries, mergeTranslationEntries, } from '@formicoidea/labre-core/std';
2
+ import { cynefinEstuarineCommands } from './commands.js';
3
+ import { ESTUARINE_NUDGES } from './estuarine/nudges.js';
4
+ import { ESTUARINE_ROLES } from './estuarine/roles.js';
5
+ /**
6
+ * THIS framework's contribution to the translation-key manifest.
7
+ *
8
+ * Since WS4 it also carries the Estuarine ROLE labels and the four Map quality
9
+ * NUDGES — the framework's entire validation vocabulary, since it declares no
10
+ * rule and no profile (`estuarine/nudges.ts`). Cynefin contributes neither,
11
+ * having no role of its own.
12
+ *
13
+ * Its command labels and descriptions are built from a TEMPLATE, so the
14
+ * concrete keys exist nowhere but in the declarations themselves and the
15
+ * core manifest could not restate them even if it wanted to. The
16
+ * contribution therefore ships WITH the framework: in the bundled
17
+ * distribution `@formicoidea/labre-framework-cynefin` carries it, and a host
18
+ * composes it into its catalogue exactly as it already composes
19
+ * `cynefinEstuarineCommands` into the command registry. See
20
+ * `packages/affine/all/src/translations.ts`.
21
+ */
22
+ export const cynefinEstuarineTranslationEntries = mergeTranslationEntries(commandTranslationEntries(cynefinEstuarineCommands), collectTranslationKeys('role', ESTUARINE_ROLES), collectTranslationKeys('nudge', ESTUARINE_NUDGES));
package/dist/view.d.ts CHANGED
@@ -1,4 +1,19 @@
1
1
  import { type ViewExtensionContext, ViewExtensionProvider } from '@formicoidea/labre-core/ext-loader';
2
+ /**
3
+ * Cynefin / Estuarine rendering — ALWAYS registered, independent of any flag.
4
+ * Disabling `cynefin-estuarine` hides only the creation tooling (see
5
+ * {@link CynefinEstuarineViewExtension}); frames already drawn must still
6
+ * paint, stay selectable, stay editable and keep their contextual toolbar. See
7
+ * `docs/adr/0009`.
8
+ */
9
+ export declare class CynefinEstuarineRenderViewExtension extends ViewExtensionProvider {
10
+ name: string;
11
+ setup(context: ViewExtensionContext): void;
12
+ }
13
+ /**
14
+ * Cynefin / Estuarine creation tooling — flag-gated (`cynefin-estuarine`): the
15
+ * senior toolbar button and both templates categories.
16
+ */
2
17
  export declare class CynefinEstuarineViewExtension extends ViewExtensionProvider {
3
18
  name: string;
4
19
  effect(): void;