@opetope/runtime 0.1.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.
- package/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +345 -0
- package/README.ru.md +344 -0
- package/dist/application-compiler-edges.d.ts +3 -0
- package/dist/application-compiler-edges.js +2 -0
- package/dist/application-compiler-edges.js.map +1 -0
- package/dist/application-compiler-graph.d.ts +8 -0
- package/dist/application-compiler-graph.js +2 -0
- package/dist/application-compiler-graph.js.map +1 -0
- package/dist/application-compiler.d.ts +116 -0
- package/dist/application-compiler.js +2 -0
- package/dist/application-compiler.js.map +1 -0
- package/dist/application-conditions.d.ts +18 -0
- package/dist/application-conditions.js +2 -0
- package/dist/application-conditions.js.map +1 -0
- package/dist/application-definition.d.ts +30 -0
- package/dist/application-definition.js +2 -0
- package/dist/application-definition.js.map +1 -0
- package/dist/application-error.d.ts +10 -0
- package/dist/application-error.js +2 -0
- package/dist/application-error.js.map +1 -0
- package/dist/application-execution.d.ts +43 -0
- package/dist/application-execution.js +2 -0
- package/dist/application-execution.js.map +1 -0
- package/dist/application-feature-bindings.d.ts +11 -0
- package/dist/application-feature-bindings.js +2 -0
- package/dist/application-feature-bindings.js.map +1 -0
- package/dist/application-feature-instance.d.ts +5 -0
- package/dist/application-feature-instance.js +2 -0
- package/dist/application-feature-instance.js.map +1 -0
- package/dist/application-group-order.d.ts +29 -0
- package/dist/application-group-order.js +2 -0
- package/dist/application-group-order.js.map +1 -0
- package/dist/application-instance-retirement.d.ts +36 -0
- package/dist/application-instance-retirement.js +2 -0
- package/dist/application-instance-retirement.js.map +1 -0
- package/dist/application-open-options.d.ts +29 -0
- package/dist/application-open-options.js +2 -0
- package/dist/application-open-options.js.map +1 -0
- package/dist/application-port-compiler.d.ts +28 -0
- package/dist/application-port-compiler.js +2 -0
- package/dist/application-port-compiler.js.map +1 -0
- package/dist/attachment-call-declaration.d.ts +43 -0
- package/dist/attachment-call-declaration.js +2 -0
- package/dist/attachment-call-declaration.js.map +1 -0
- package/dist/attachment-declaration.d.ts +68 -0
- package/dist/attachment-declaration.js +2 -0
- package/dist/attachment-declaration.js.map +1 -0
- package/dist/attachment-execution.d.ts +9 -0
- package/dist/attachment-execution.js +2 -0
- package/dist/attachment-execution.js.map +1 -0
- package/dist/attachment-retirement-scheduler.d.ts +14 -0
- package/dist/attachment-retirement-scheduler.js +2 -0
- package/dist/attachment-retirement-scheduler.js.map +1 -0
- package/dist/call-option-snapshot.d.ts +20 -0
- package/dist/call-option-snapshot.js +2 -0
- package/dist/call-option-snapshot.js.map +1 -0
- package/dist/compile-call-target-bindings.d.ts +14 -0
- package/dist/compile-call-target-bindings.js +2 -0
- package/dist/compile-call-target-bindings.js.map +1 -0
- package/dist/compile-module-template.d.ts +38 -0
- package/dist/compile-module-template.js +2 -0
- package/dist/compile-module-template.js.map +1 -0
- package/dist/condition-group-execution.d.ts +44 -0
- package/dist/condition-group-execution.js +2 -0
- package/dist/condition-group-execution.js.map +1 -0
- package/dist/condition-override.d.ts +28 -0
- package/dist/condition-override.js +2 -0
- package/dist/condition-override.js.map +1 -0
- package/dist/condition-source.d.ts +10 -0
- package/dist/condition-source.js +2 -0
- package/dist/condition-source.js.map +1 -0
- package/dist/condition-types.d.ts +14 -0
- package/dist/condition.d.ts +28 -0
- package/dist/condition.js +2 -0
- package/dist/condition.js.map +1 -0
- package/dist/control-registry.d.ts +56 -0
- package/dist/control-registry.js +2 -0
- package/dist/control-registry.js.map +1 -0
- package/dist/dynamic-scope-child.d.ts +23 -0
- package/dist/dynamic-scope-child.js +2 -0
- package/dist/dynamic-scope-child.js.map +1 -0
- package/dist/dynamic-scope-controller.d.ts +16 -0
- package/dist/dynamic-scope-controller.js +2 -0
- package/dist/dynamic-scope-controller.js.map +1 -0
- package/dist/feature-attachment-authoring-types.d.ts +51 -0
- package/dist/feature-attachment-lowering.d.ts +18 -0
- package/dist/feature-attachment-lowering.js +2 -0
- package/dist/feature-attachment-lowering.js.map +1 -0
- package/dist/feature-attachment.d.ts +45 -0
- package/dist/feature-attachment.js +2 -0
- package/dist/feature-attachment.js.map +1 -0
- package/dist/feature-authoring-types.d.ts +196 -0
- package/dist/feature-authoring.d.ts +15 -0
- package/dist/feature-authoring.js +2 -0
- package/dist/feature-authoring.js.map +1 -0
- package/dist/feature-body.d.ts +53 -0
- package/dist/feature-body.js +2 -0
- package/dist/feature-body.js.map +1 -0
- package/dist/feature-call-authority.d.ts +8 -0
- package/dist/feature-call-authority.js +2 -0
- package/dist/feature-call-authority.js.map +1 -0
- package/dist/feature-call-types.d.ts +39 -0
- package/dist/feature-call.d.ts +18 -0
- package/dist/feature-call.js +2 -0
- package/dist/feature-call.js.map +1 -0
- package/dist/feature-calls.d.ts +6 -0
- package/dist/feature-calls.js +2 -0
- package/dist/feature-calls.js.map +1 -0
- package/dist/feature-contract.d.ts +70 -0
- package/dist/feature-contract.js +2 -0
- package/dist/feature-contract.js.map +1 -0
- package/dist/feature-contribution-model.d.ts +38 -0
- package/dist/feature-contribution-model.js +2 -0
- package/dist/feature-contribution-model.js.map +1 -0
- package/dist/feature-contribution.d.ts +126 -0
- package/dist/feature-contribution.js +2 -0
- package/dist/feature-contribution.js.map +1 -0
- package/dist/feature-definition-api.d.ts +53 -0
- package/dist/feature-definition-support.d.ts +21 -0
- package/dist/feature-definition-support.js +2 -0
- package/dist/feature-definition-support.js.map +1 -0
- package/dist/feature-effect.d.ts +26 -0
- package/dist/feature-effect.js +2 -0
- package/dist/feature-effect.js.map +1 -0
- package/dist/feature-event.d.ts +32 -0
- package/dist/feature-event.js +2 -0
- package/dist/feature-event.js.map +1 -0
- package/dist/feature-generation.d.ts +34 -0
- package/dist/feature-generation.js +2 -0
- package/dist/feature-generation.js.map +1 -0
- package/dist/feature-lazy-generation.d.ts +6 -0
- package/dist/feature-lazy-generation.js +2 -0
- package/dist/feature-lazy-generation.js.map +1 -0
- package/dist/feature-lazy.d.ts +44 -0
- package/dist/feature-lazy.js +2 -0
- package/dist/feature-lazy.js.map +1 -0
- package/dist/feature-materialization-binding.d.ts +31 -0
- package/dist/feature-materialization-binding.js +2 -0
- package/dist/feature-materialization-binding.js.map +1 -0
- package/dist/feature-materialization-types.d.ts +45 -0
- package/dist/feature-model-dependencies.d.ts +23 -0
- package/dist/feature-model-dependencies.js +2 -0
- package/dist/feature-model-dependencies.js.map +1 -0
- package/dist/feature-model.d.ts +60 -0
- package/dist/feature-model.js +2 -0
- package/dist/feature-model.js.map +1 -0
- package/dist/feature-optional.d.ts +15 -0
- package/dist/feature-optional.js +2 -0
- package/dist/feature-optional.js.map +1 -0
- package/dist/feature-own-lowering.d.ts +22 -0
- package/dist/feature-own-lowering.js +2 -0
- package/dist/feature-own-lowering.js.map +1 -0
- package/dist/feature-port-binding.d.ts +6 -0
- package/dist/feature-port-binding.js +2 -0
- package/dist/feature-port-binding.js.map +1 -0
- package/dist/feature-port.d.ts +66 -0
- package/dist/feature-port.js +2 -0
- package/dist/feature-port.js.map +1 -0
- package/dist/feature-record.d.ts +6 -0
- package/dist/feature-record.js +2 -0
- package/dist/feature-record.js.map +1 -0
- package/dist/feature-resource.d.ts +29 -0
- package/dist/feature-resource.js +2 -0
- package/dist/feature-resource.js.map +1 -0
- package/dist/feature-scope-types.d.ts +35 -0
- package/dist/feature-scope.d.ts +29 -0
- package/dist/feature-scope.js +2 -0
- package/dist/feature-scope.js.map +1 -0
- package/dist/feature-stream.d.ts +37 -0
- package/dist/feature-stream.js +2 -0
- package/dist/feature-stream.js.map +1 -0
- package/dist/feature-timers.d.ts +14 -0
- package/dist/feature-timers.js +2 -0
- package/dist/feature-timers.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/inspection-activity-protocol.d.ts +63 -0
- package/dist/inspection-activity.d.ts +54 -0
- package/dist/inspection-activity.js +2 -0
- package/dist/inspection-activity.js.map +1 -0
- package/dist/inspection-diff.d.ts +10 -0
- package/dist/inspection-diff.js +2 -0
- package/dist/inspection-diff.js.map +1 -0
- package/dist/inspection-module-activity.d.ts +4 -0
- package/dist/inspection-module-activity.js +2 -0
- package/dist/inspection-module-activity.js.map +1 -0
- package/dist/inspection-observer.d.ts +38 -0
- package/dist/inspection-observer.js +2 -0
- package/dist/inspection-observer.js.map +1 -0
- package/dist/inspection-plan.d.ts +33 -0
- package/dist/inspection-plan.js +2 -0
- package/dist/inspection-plan.js.map +1 -0
- package/dist/inspection-protocol.d.ts +333 -0
- package/dist/inspection-protocol.js +2 -0
- package/dist/inspection-protocol.js.map +1 -0
- package/dist/inspection-registry.d.ts +41 -0
- package/dist/inspection-registry.js +2 -0
- package/dist/inspection-registry.js.map +1 -0
- package/dist/inspection-session.d.ts +92 -0
- package/dist/inspection-session.js +2 -0
- package/dist/inspection-session.js.map +1 -0
- package/dist/inspection-snapshot.d.ts +4 -0
- package/dist/inspection-snapshot.js +2 -0
- package/dist/inspection-snapshot.js.map +1 -0
- package/dist/inspection-state.d.ts +91 -0
- package/dist/inspection-state.js +2 -0
- package/dist/inspection-state.js.map +1 -0
- package/dist/instance-demand.d.ts +31 -0
- package/dist/instance-demand.js +2 -0
- package/dist/instance-demand.js.map +1 -0
- package/dist/internal.d.ts +41 -0
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -0
- package/dist/keyed-scope-controller.d.ts +11 -0
- package/dist/keyed-scope-controller.js +2 -0
- package/dist/keyed-scope-controller.js.map +1 -0
- package/dist/model-kernel.d.ts +18 -0
- package/dist/model-kernel.js +2 -0
- package/dist/model-kernel.js.map +1 -0
- package/dist/module-call-context.d.ts +7 -0
- package/dist/module-call-context.js +2 -0
- package/dist/module-call-context.js.map +1 -0
- package/dist/module-call-runtime.d.ts +21 -0
- package/dist/module-call-runtime.js +2 -0
- package/dist/module-call-runtime.js.map +1 -0
- package/dist/module-generation.d.ts +57 -0
- package/dist/module-generation.js +2 -0
- package/dist/module-generation.js.map +1 -0
- package/dist/module-instance-types.d.ts +156 -0
- package/dist/module-instance.d.ts +19 -0
- package/dist/module-instance.js +2 -0
- package/dist/module-instance.js.map +1 -0
- package/dist/module-runtime-identity.d.ts +4 -0
- package/dist/module-runtime-identity.js +2 -0
- package/dist/module-runtime-identity.js.map +1 -0
- package/dist/module-scope-open.d.ts +4 -0
- package/dist/module-scope-open.js +2 -0
- package/dist/module-scope-open.js.map +1 -0
- package/dist/module-scope-retirement.d.ts +3 -0
- package/dist/module-scope-retirement.js +2 -0
- package/dist/module-scope-retirement.js.map +1 -0
- package/dist/module-template-ir.d.ts +59 -0
- package/dist/owner-generation-retirement.d.ts +6 -0
- package/dist/owner-generation-retirement.js +2 -0
- package/dist/owner-generation-retirement.js.map +1 -0
- package/dist/owner-generation-state.d.ts +123 -0
- package/dist/owner-generation-state.js +2 -0
- package/dist/owner-generation-state.js.map +1 -0
- package/dist/owner-generation.d.ts +16 -0
- package/dist/owner-generation.js +2 -0
- package/dist/owner-generation.js.map +1 -0
- package/dist/public-module-definition.d.ts +9 -0
- package/dist/public-module-definition.js +2 -0
- package/dist/public-module-definition.js.map +1 -0
- package/dist/public-module-instance.d.ts +6 -0
- package/dist/public-module-instance.js +2 -0
- package/dist/public-module-instance.js.map +1 -0
- package/dist/public-module-retirement-diagnostics.d.ts +5 -0
- package/dist/public-module-retirement-diagnostics.js +2 -0
- package/dist/public-module-retirement-diagnostics.js.map +1 -0
- package/dist/public-module-retirement.d.ts +3 -0
- package/dist/public-module-retirement.js +2 -0
- package/dist/public-module-retirement.js.map +1 -0
- package/dist/public-module-scope.d.ts +5 -0
- package/dist/public-module-scope.js +2 -0
- package/dist/public-module-scope.js.map +1 -0
- package/dist/public-module-state.d.ts +28 -0
- package/dist/public-module-state.js +2 -0
- package/dist/public-module-state.js.map +1 -0
- package/dist/public-module-types.d.ts +295 -0
- package/dist/public-module.d.ts +4 -0
- package/dist/resource-cache.d.ts +12 -0
- package/dist/resource-cache.js +2 -0
- package/dist/resource-cache.js.map +1 -0
- package/dist/resource-controller.d.ts +29 -0
- package/dist/resource-controller.js +2 -0
- package/dist/resource-controller.js.map +1 -0
- package/dist/resource-policy.d.ts +16 -0
- package/dist/resource-policy.js +2 -0
- package/dist/resource-policy.js.map +1 -0
- package/dist/resource-snapshot.d.ts +12 -0
- package/dist/resource-snapshot.js +2 -0
- package/dist/resource-snapshot.js.map +1 -0
- package/dist/resource-types.d.ts +3 -0
- package/dist/runtime-error-reporting.d.ts +4 -0
- package/dist/runtime-error-reporting.js +2 -0
- package/dist/runtime-error-reporting.js.map +1 -0
- package/dist/stream-backpressure.d.ts +18 -0
- package/dist/stream-backpressure.js +2 -0
- package/dist/stream-backpressure.js.map +1 -0
- package/dist/stream-cleanup.d.ts +17 -0
- package/dist/stream-cleanup.js +2 -0
- package/dist/stream-cleanup.js.map +1 -0
- package/dist/stream-controller-types.d.ts +51 -0
- package/dist/stream-controller.d.ts +5 -0
- package/dist/stream-controller.js +2 -0
- package/dist/stream-controller.js.map +1 -0
- package/docs/agent-guide.md +214 -0
- package/docs/agent-guide.ru.md +208 -0
- package/docs/cookbook.md +734 -0
- package/docs/cookbook.ru.md +729 -0
- package/docs/decisions.md +1437 -0
- package/docs/devtools.md +423 -0
- package/docs/devtools.ru.md +419 -0
- package/docs/how-it-works.md +521 -0
- package/docs/how-it-works.ru.md +495 -0
- package/docs/releases.md +78 -0
- package/docs/releases.ru.md +78 -0
- package/docs/spec.md +874 -0
- package/docs/spec.ru.md +884 -0
- package/package.json +72 -0
|
@@ -0,0 +1,1437 @@
|
|
|
1
|
+
# Opetope — решения и основания
|
|
2
|
+
|
|
3
|
+
Нормативный API и законы описаны в [spec.md](spec.md), устройство — в [how-it-works.md](how-it-works.md). Здесь собраны краткие причины и связи решений. Номера Dnnn стабильны; ссылки на уточняющее решение задают действующую форму. Изменение публичного контракта добавляет новый номер и обновляет спецификацию.
|
|
4
|
+
|
|
5
|
+
<a id="d1"></a>
|
|
6
|
+
|
|
7
|
+
## D1 — три слова: `call`, `command`, `action`
|
|
8
|
+
|
|
9
|
+
Команды объявляются через call/calls, исполняются через invoke; useCommand/useCommands связывают Call с UI. См. [D174](#d174), [D243](#d243).
|
|
10
|
+
|
|
11
|
+
<a id="d2"></a>
|
|
12
|
+
|
|
13
|
+
## D2 — отказ новой работы после retirement
|
|
14
|
+
|
|
15
|
+
Неактивный экземпляр отклоняет новую работу ошибкой авторского subject/code. Действующая система ошибок — [D69](#d69), [D81](#d81).
|
|
16
|
+
|
|
17
|
+
<a id="d3"></a>
|
|
18
|
+
|
|
19
|
+
## D3 — `attach` и dynamic lifetime без слова `lifetime`
|
|
20
|
+
|
|
21
|
+
`attach` подключает источник с open/close, `scope.while/switch/keyed` это dynamic lifetime; слова `lifetime` в API нет. время жизни выражается формой, а не термином. Сужено [D141](#d141).
|
|
22
|
+
|
|
23
|
+
<a id="d4"></a>
|
|
24
|
+
|
|
25
|
+
## D4 — `defineModel<Shape>(id)`, View сливается в Model
|
|
26
|
+
|
|
27
|
+
модель это запись `Readable` и `Call`; слово Token уходит. UI-контракт и контракт данных — одно понятие.
|
|
28
|
+
|
|
29
|
+
<a id="d5"></a>
|
|
30
|
+
|
|
31
|
+
## D5 — принадлежащие фиче значения объявляются в own
|
|
32
|
+
|
|
33
|
+
Секция own объявляет принадлежащие фиче модели, команды, реактивные источники и вложения. Действующая форма — [D80](#d80).
|
|
34
|
+
|
|
35
|
+
<a id="d6"></a>
|
|
36
|
+
|
|
37
|
+
## D6 — `ModelContext` без generic
|
|
38
|
+
|
|
39
|
+
зависимости модель объявляет своим интерфейсом, фича подставляет. модель не должна знать, кто её собирает.
|
|
40
|
+
|
|
41
|
+
<a id="d7"></a>
|
|
42
|
+
|
|
43
|
+
## D7 — `imports` принимает определение фичи
|
|
44
|
+
|
|
45
|
+
imports принимает определение фичи как контракт её exports. Внешний контракт хоста объявляется defineHostContract. См. [D80](#d80), [D98](#d98).
|
|
46
|
+
|
|
47
|
+
<a id="d8"></a>
|
|
48
|
+
|
|
49
|
+
## D8 — `requires.x` это `Call`, доменные порты удалены
|
|
50
|
+
|
|
51
|
+
`requires.x` это `Call`; `domainPorts`, `defineDomainPort`, `adaptPort` удалены. требование к чужому провайдеру — обычный вызов.
|
|
52
|
+
|
|
53
|
+
<a id="d9"></a>
|
|
54
|
+
|
|
55
|
+
## D9 — `provides` объединяет `port`, `slot`, `pipe`, `register`
|
|
56
|
+
|
|
57
|
+
одна секция на capability и вклады; `contributions` и слово `contribute` удалены. вид цели различает форму вклада, поэтому вторая секция ничего не добавляла.
|
|
58
|
+
|
|
59
|
+
<a id="d10"></a>
|
|
60
|
+
|
|
61
|
+
## D10 — `defineRoot` опционален
|
|
62
|
+
|
|
63
|
+
Отдельные публичные root-декларации не требуются: права UI задаёт frame вклада Slot. См. [D85](#d85).
|
|
64
|
+
|
|
65
|
+
<a id="d11"></a>
|
|
66
|
+
|
|
67
|
+
## D11 — секция `ui` это builder
|
|
68
|
+
|
|
69
|
+
Монтаж UI реализуется через Slot и integration entry; отдельной authoring-секции ui нет. См. [D85](#d85).
|
|
70
|
+
|
|
71
|
+
<a id="d12"></a>
|
|
72
|
+
|
|
73
|
+
## D12 — публичный authoring root один: `defineFeature`
|
|
74
|
+
|
|
75
|
+
`defineModule`, `Module*` и `Task*` живут в `internal`. kernel-словарь наружу не выходит.
|
|
76
|
+
|
|
77
|
+
<a id="d13"></a>
|
|
78
|
+
|
|
79
|
+
## D13 — ошибки `<Subject><State>Error`
|
|
80
|
+
|
|
81
|
+
Ошибки имеют авторский subject и стабильный code; действующая система — [D69](#d69), [D81](#d81).
|
|
82
|
+
|
|
83
|
+
<a id="d14"></a>
|
|
84
|
+
|
|
85
|
+
## D14 — один словарь `phase`
|
|
86
|
+
|
|
87
|
+
фазы это `open`, `close`, `rollback`, `fence`, `drain`, `retry`. одно время жизни — один набор слов, включая devtools.
|
|
88
|
+
|
|
89
|
+
<a id="d15"></a>
|
|
90
|
+
|
|
91
|
+
## D15 — переименования под авторский словарь
|
|
92
|
+
|
|
93
|
+
Authoring names следуют общему словарю. Текущие имена: useCommand, calls, onDemand, openFeature, event.subscribe, key и Collection. См. spec §3.
|
|
94
|
+
|
|
95
|
+
<a id="d16"></a>
|
|
96
|
+
|
|
97
|
+
## D16 — обязателен только `id`
|
|
98
|
+
|
|
99
|
+
суффикса `.feature` нет, разделитель только точка. id это адрес в плане приложения, а не вид сущности.
|
|
100
|
+
|
|
101
|
+
<a id="d17"></a>
|
|
102
|
+
|
|
103
|
+
## D17 — изоляция временной совместимости
|
|
104
|
+
|
|
105
|
+
Временные адаптеры отделяются от постоянного API библиотеки. Дополнительная совместимость должна иметь явную границу и владельца.
|
|
106
|
+
|
|
107
|
+
<a id="d18"></a>
|
|
108
|
+
|
|
109
|
+
## D18 — `gateway` остаётся для owned I/O
|
|
110
|
+
|
|
111
|
+
Owned I/O описывается attachment/resource/stream с lifetime владельца; отдельного gateway primitive нет. См. [D96](#d96).
|
|
112
|
+
|
|
113
|
+
<a id="d19"></a>
|
|
114
|
+
|
|
115
|
+
## D19 — тестовая поверхность `renderRoot`
|
|
116
|
+
|
|
117
|
+
Публичный UI test harness использует renderSlot и createScenario. См. [D85](#d85), [D215](#d215).
|
|
118
|
+
|
|
119
|
+
<a id="d20"></a>
|
|
120
|
+
|
|
121
|
+
## D20 — trusted subpaths
|
|
122
|
+
|
|
123
|
+
доверенные подпути это `@opetope/core/internal`, `@opetope/runtime/internal`, `@opetope/react/integration`. граница автора и хоста проверяется линтом, а не соглашением.
|
|
124
|
+
|
|
125
|
+
<a id="d21"></a>
|
|
126
|
+
|
|
127
|
+
## D21 — см. D26
|
|
128
|
+
|
|
129
|
+
`resource(from, target, {…})`, `stream(from, target, {…})`, `event(from, subscribe, {…})`; lint-правило порядка ключей снято. См. [D26](#d26).
|
|
130
|
+
|
|
131
|
+
<a id="d22"></a>
|
|
132
|
+
|
|
133
|
+
## D22 — формы `once` и `singleFlight`
|
|
134
|
+
|
|
135
|
+
`once: true` — один результат на поколение, `once: input => key` — по ключу, `singleFlight: input => key` без объекта-обёртки. политика вызова описывается значением, а не конфигурацией.
|
|
136
|
+
|
|
137
|
+
<a id="d23"></a>
|
|
138
|
+
|
|
139
|
+
## D23 — типы переименованы вместе со значениями
|
|
140
|
+
|
|
141
|
+
Типы используют тот же словарь, что значения. Текущие subject names и ошибки — [D81](#d81); формы Call/Readable/Model — spec §3.
|
|
142
|
+
|
|
143
|
+
<a id="d24"></a>
|
|
144
|
+
|
|
145
|
+
## D24 — монтаж UI находится в integration
|
|
146
|
+
|
|
147
|
+
Монтаж модели относится к host integration. Действующие entry points — @opetope/react/integration и @opetope/react/testing; отдельный ViewRootProvider не нужен. См. [D85](#d85).
|
|
148
|
+
|
|
149
|
+
<a id="d25"></a>
|
|
150
|
+
|
|
151
|
+
## D25 — поле снапшота ресурса называется `key`
|
|
152
|
+
|
|
153
|
+
в `ResourceSnapshot` поле `key`, как и опция; `requestKey` удалён. опция и снапшот говорят об одном ключе.
|
|
154
|
+
|
|
155
|
+
<a id="d26"></a>
|
|
156
|
+
|
|
157
|
+
## D26 — позиционные источник и носитель типа
|
|
158
|
+
|
|
159
|
+
`resource(from, target, {…})`, `stream(from, target, {…})`, `event(from, subscribe, {…})`; lint-правило порядка ключей снято. TypeScript выводит второй аргумент до контекстной типизации третьего, поэтому порядок ключей опций больше не влияет на вывод `Target` и `Payload`; закреплять порядок линтом значило бы поставить форму в зависимость от конфига. Уточняет: [D21](#d21).
|
|
160
|
+
|
|
161
|
+
<a id="d27"></a>
|
|
162
|
+
|
|
163
|
+
## D27 — id позиционной строкой, слово Token убрано
|
|
164
|
+
|
|
165
|
+
`ModelToken`→`Model`, `isModelToken`→`isModel`, id передаётся позиционно. слово Token не принадлежит авторскому словарю.
|
|
166
|
+
|
|
167
|
+
<a id="d28"></a>
|
|
168
|
+
|
|
169
|
+
## D28 — View слит в Model
|
|
170
|
+
|
|
171
|
+
`defineViewContract`, `viewReadable`, `viewCommand`, `useView` и типы `View*` удалены; UI-контракт это `defineModel<Shape>`, `requires` корня содержит только `models`. два контракта на один UI-вход давали два места правки.
|
|
172
|
+
|
|
173
|
+
<a id="d29"></a>
|
|
174
|
+
|
|
175
|
+
## D29 — см. D59
|
|
176
|
+
|
|
177
|
+
`bindModel` отвергает значение, которое не `Readable` и не связанная команда, лишнее имя поля остаётся ошибкой типа. runtime-список дублировал бы `Shape` — два источника правды. См. [D59](#d59).
|
|
178
|
+
|
|
179
|
+
<a id="d30"></a>
|
|
180
|
+
|
|
181
|
+
## D30 — см. D71
|
|
182
|
+
|
|
183
|
+
`Command<Input, Output>` без режима, `CommandHook` это `{ run, inFlight, lastError }`, `useCommand` не держит listener на invoker; наблюдаемое состояние вызова модель отдаёт полем `Readable`. режим был вторым способом смотреть на вызов, а харнесс строится через `externalReadable`. См. [D71](#d71).
|
|
184
|
+
|
|
185
|
+
<a id="d31"></a>
|
|
186
|
+
|
|
187
|
+
## D31 — см. D60
|
|
188
|
+
|
|
189
|
+
две декларации с одинаковым `Shape` взаимозаменяемы для компилятора, различает их runtime-идентичность. id в типе сделал бы объявления номинальными и потянул брендирование в подписи. См. [D60](#d60).
|
|
190
|
+
|
|
191
|
+
<a id="d32"></a>
|
|
192
|
+
|
|
193
|
+
## D32 — см. D76
|
|
194
|
+
|
|
195
|
+
`useCommand` держит ноль listener-ов на invoker, `useReadable` ровно один на `Readable`, после unmount ноль и там, и там. проверка требовала listener на хук, а [D71](#d71) убрал подписку у `useCommand`. См. [D76](#d76).
|
|
196
|
+
|
|
197
|
+
<a id="d33"></a>
|
|
198
|
+
|
|
199
|
+
## D33 — см. D77
|
|
200
|
+
|
|
201
|
+
`measure` берёт `before` после открытия харнесса, `sampleHeap` собирает мусор перед `liveBytes()`. См. [D77](#d77).
|
|
202
|
+
|
|
203
|
+
<a id="d34"></a>
|
|
204
|
+
|
|
205
|
+
## D34 — семейство `ViewCommand*` переименовано
|
|
206
|
+
|
|
207
|
+
`ViewCommandHook`→`CommandHook`, `bindViewCommand`→`bindCommand`, `ViewBindingInvalidError`→`ModelBindingInvalidError`. слово `View` ушло с концептом ([D28](#d28)), имена не могут его переживать.
|
|
208
|
+
|
|
209
|
+
<a id="d35"></a>
|
|
210
|
+
|
|
211
|
+
## D35 — никаких deprecated-алиасов до первой публикации
|
|
212
|
+
|
|
213
|
+
Публичное переименование выполняется согласованно во всех пакетах, типах, документации и примерах. Пока API экспериментальный, устаревшие aliases не сохраняются как параллельный словарь.
|
|
214
|
+
|
|
215
|
+
<a id="d36"></a>
|
|
216
|
+
|
|
217
|
+
## D36 — `model()` и `state()` возвращают ref
|
|
218
|
+
|
|
219
|
+
значение живёт от открытия экземпляра до retire, источник позиционный — `model(Declaration, from, create)`; refs данных не входят в module IR. фабрика модели получает живой `ModelContext`, поэтому deps модели это значения, а не refs.
|
|
220
|
+
|
|
221
|
+
<a id="d37"></a>
|
|
222
|
+
|
|
223
|
+
## D37 — см. D73
|
|
224
|
+
|
|
225
|
+
`ModelContext` в полном составе — `call`, `lane`, `effect`, `event`, `resource`, `stream`, `scope`, `own` рядом с `state`, `update`, `signal`; узлы живут от открытия экземпляра до retire, а `from` это готовое значение: у модели нет импортов. без своего kernel-а роль узлов модели играли deps. См. [D73](#d73).
|
|
226
|
+
|
|
227
|
+
<a id="d38"></a>
|
|
228
|
+
|
|
229
|
+
## D38 — см. D72
|
|
230
|
+
|
|
231
|
+
`ctx.state` возвращает `OwnedState`, `ctx.update` принимает только его, поэтому чужой `Readable` отвергается компилятором. иначе владение проверяется только в рантайме. См. [D72](#d72).
|
|
232
|
+
|
|
233
|
+
<a id="d39"></a>
|
|
234
|
+
|
|
235
|
+
## D39 — `exports` это фабрика call-ref
|
|
236
|
+
|
|
237
|
+
контракт создаётся автоматически под id `<feature>.exports`, пять перегрузок `defineFeature` сведены в одну форму. отдельный контракт дублировал то, что фича уже описала.
|
|
238
|
+
|
|
239
|
+
<a id="d40"></a>
|
|
240
|
+
|
|
241
|
+
## D40 — `defineHostImport` и перенос типов в internal
|
|
242
|
+
|
|
243
|
+
`defineImportContract`→`defineHostImport`, `ImportContract`→`HostImport`; `OnDemandImportContract`, `FeatureReady*`, `RequiredPort` уходят в `internal`. публичный вход содержит только словарь автора.
|
|
244
|
+
|
|
245
|
+
<a id="d41"></a>
|
|
246
|
+
|
|
247
|
+
## D41 — см. D61
|
|
248
|
+
|
|
249
|
+
`ApplicationExecution` публичен; `RequiredPort`, `OnDemandHostImport`, `CollectionLookup` и `SignalSource` остаются выводимыми результатами в allowlist гейта. См. [D61](#d61).
|
|
250
|
+
|
|
251
|
+
<a id="d42"></a>
|
|
252
|
+
|
|
253
|
+
## D42 — `requires.x` это call-ref фичи
|
|
254
|
+
|
|
255
|
+
требование lower-ится в один call скрытого вложения требований, доменные порты удалены. требование это тот же вызов, второго механизма не нужно.
|
|
256
|
+
|
|
257
|
+
<a id="d43"></a>
|
|
258
|
+
|
|
259
|
+
## D43 — `calls(imports.x, keys)` принимает импорт напрямую
|
|
260
|
+
|
|
261
|
+
источник без open/close получает одно неявное вложение; `attach` остаётся для источников с lifecycle. `attach` ради значения без жизненного цикла — лишний шаг.
|
|
262
|
+
|
|
263
|
+
<a id="d44"></a>
|
|
264
|
+
|
|
265
|
+
## D44 — см. D62
|
|
266
|
+
|
|
267
|
+
`slot(target, contribution|factory, { priority })`, так же `pipe` и `register`; у `pipe` второй аргумент всегда фабрика. обработчик `pipe` сам функция, поэтому короткая форма неотличима от фабрики. См. [D62](#d62).
|
|
268
|
+
|
|
269
|
+
<a id="d45"></a>
|
|
270
|
+
|
|
271
|
+
## D45 — `contributions` слита в `provides`
|
|
272
|
+
|
|
273
|
+
`contribute` заменён на `slot`, `pipe`, `register` по виду цели, `provide` переименован в `port`. одна секция объявляет и capability, и вклады.
|
|
274
|
+
|
|
275
|
+
<a id="d46"></a>
|
|
276
|
+
|
|
277
|
+
## D46 — имена корня и action по авторскому словарю
|
|
278
|
+
|
|
279
|
+
`defineViewRoot`→`defineRoot`, `defineRootInput`→`input`, `defineInputAction`→`action`, `ViewRootDefinition`→`Root`; `RootInstance`, `ActionHandler` ушли с входа. на входе остаётся то, что автор пишет руками.
|
|
280
|
+
|
|
281
|
+
<a id="d47"></a>
|
|
282
|
+
|
|
283
|
+
## D47 — см. D63
|
|
284
|
+
|
|
285
|
+
добавлен рядом с `root`, `model`, `mapCommand`. есть фичи, чей UI-продукт это сам ресурс. См. [D63](#d63).
|
|
286
|
+
|
|
287
|
+
<a id="d48"></a>
|
|
288
|
+
|
|
289
|
+
## D48 — `@opetope/react/testing` с `renderRoot`
|
|
290
|
+
|
|
291
|
+
отдельный подпуть, разрешённый только тестам: харнесс монтирует фикстуру моделей и отдаёт `close`, `instance`, `Root`, `updateInput`. тестовый вход не должен расширять продуктовый. `renderRoot`→`renderSlot` в [D85](#d85).
|
|
292
|
+
|
|
293
|
+
<a id="d49"></a>
|
|
294
|
+
|
|
295
|
+
## D49 — см. D64
|
|
296
|
+
|
|
297
|
+
`command(run)` живёт в `@opetope/react/testing`, `defineCallTarget` публичным не становится. фикстуре нужна идентичность вызова, но конструктор целей ради тестов не открывают. См. [D64](#d64).
|
|
298
|
+
|
|
299
|
+
<a id="d50"></a>
|
|
300
|
+
|
|
301
|
+
## D50 — см. D65
|
|
302
|
+
|
|
303
|
+
UI использует contribution frame Slot; отдельные публичные root declarations не требуются. См. [D65](#d65).
|
|
304
|
+
|
|
305
|
+
<a id="d51"></a>
|
|
306
|
+
|
|
307
|
+
## D51 — `FeatureRoot` принимает результат секции `ui`
|
|
308
|
+
|
|
309
|
+
проп `ui` это результат `root(...)` или фабрика корня; `ui.roots.x` больше нет. реестр корней добавлял адресацию там, где хост и так держит ссылку. Удалено [D85](#d85).
|
|
310
|
+
|
|
311
|
+
<a id="d52"></a>
|
|
312
|
+
|
|
313
|
+
## D52 — см. D66
|
|
314
|
+
|
|
315
|
+
Модель принадлежит lifetime своего владельца; contribution frame определяет доступ UI. См. [D66](#d66).
|
|
316
|
+
|
|
317
|
+
<a id="d53"></a>
|
|
318
|
+
|
|
319
|
+
## D53 — см. D69
|
|
320
|
+
|
|
321
|
+
`GenerationError` (`inactive`, `not-ready`, `quarantined`, `cleanup-failed`), `CallError` (`cancelled`, `closed`, `publication-rejected`), `ReadableError`, `RootError`, `ModelError`, `ActionError`, `ApplicationError`, `DeclarationError`; `isCancellation` это маркер отменяющих кодов. класс на состояние раздувал вход — 44 значения при цели 40. См. [D69](#d69).
|
|
322
|
+
|
|
323
|
+
<a id="d54"></a>
|
|
324
|
+
|
|
325
|
+
## D54 — внутренние имена react без слова `View`
|
|
326
|
+
|
|
327
|
+
`createViewRootController`→`createRootController`, `requireViewRootFrameBinding`→`requireRootFrameBinding`, тексты ошибок тоже. снятое слово не выживает во внутренних именах.
|
|
328
|
+
|
|
329
|
+
<a id="d55"></a>
|
|
330
|
+
|
|
331
|
+
## D55 — авторитет корня проверяется типом
|
|
332
|
+
|
|
333
|
+
`root(Root, { models, strict })` требует все объявленные корнем модели, strict-корень не принимает лишних. грант моделей это часть контракта; лишнюю модель ловит только структурное различие, потому что `Model<Shape>` не несёт id ([D60](#d60)). Удалено [D85](#d85).
|
|
334
|
+
|
|
335
|
+
<a id="d56"></a>
|
|
336
|
+
|
|
337
|
+
## D56 — см. D66
|
|
338
|
+
|
|
339
|
+
Модель принадлежит lifetime своего владельца; contribution frame определяет доступ UI. См. [D66](#d66).
|
|
340
|
+
|
|
341
|
+
<a id="d57"></a>
|
|
342
|
+
|
|
343
|
+
## D57 — см. D78
|
|
344
|
+
|
|
345
|
+
Изменение области видимости API должно сопровождаться обновлением типов и исполняемых consumer examples. См. [D78](#d78).
|
|
346
|
+
|
|
347
|
+
<a id="d58"></a>
|
|
348
|
+
|
|
349
|
+
## D58 — см. D67
|
|
350
|
+
|
|
351
|
+
`defineSlot`, `defineSwitchSlot` и `Slot` остаются в `react`; типы это `SlotTarget`, `SwitchSlotTarget`, `SlotContribution`. слот рендерит разметку и без React смысла не имеет. См. [D67](#d67).
|
|
352
|
+
|
|
353
|
+
<a id="d59"></a>
|
|
354
|
+
|
|
355
|
+
## D59 — у `defineModel` нет runtime-списка полей
|
|
356
|
+
|
|
357
|
+
`bindModel` отвергает значение, которое не `Readable` и не связанная команда, лишнее имя поля остаётся ошибкой типа. runtime-список дублировал бы `Shape` — два источника правды. Уточняет: [D29](#d29).
|
|
358
|
+
|
|
359
|
+
<a id="d60"></a>
|
|
360
|
+
|
|
361
|
+
## D60 — `Model<Shape>` структурный, id в типе не несёт
|
|
362
|
+
|
|
363
|
+
две декларации с одинаковым `Shape` взаимозаменяемы для компилятора, различает их runtime-идентичность. id в типе сделал бы объявления номинальными и потянул брендирование в подписи. Уточняет: [D31](#d31).
|
|
364
|
+
|
|
365
|
+
<a id="d61"></a>
|
|
366
|
+
|
|
367
|
+
## D61 — публично только `ApplicationExecution`
|
|
368
|
+
|
|
369
|
+
`ApplicationExecution` публичен; `RequiredPort`, `OnDemandHostImport`, `CollectionLookup` и `SignalSource` остаются выводимыми результатами в allowlist гейта. Правило: тип из результата публичного значения в `internal` не переносить. имя нужно там, где автор пишет его руками. Уточняет: [D41](#d41).
|
|
370
|
+
|
|
371
|
+
<a id="d62"></a>
|
|
372
|
+
|
|
373
|
+
## D62 — форма вкладов: цель первым аргументом
|
|
374
|
+
|
|
375
|
+
`slot(target, contribution|factory, { priority })`, так же `pipe` и `register`; у `pipe` второй аргумент всегда фабрика. обработчик `pipe` сам функция, поэтому короткая форма неотличима от фабрики. Уточняет: [D44](#d44).
|
|
376
|
+
|
|
377
|
+
<a id="d63"></a>
|
|
378
|
+
|
|
379
|
+
## D63 — `resource` это четвёртый метод секции `ui`
|
|
380
|
+
|
|
381
|
+
добавлен рядом с `root`, `model`, `mapCommand`. есть фичи, чей UI-продукт это сам ресурс. Уточняет: [D47](#d47).
|
|
382
|
+
|
|
383
|
+
<a id="d64"></a>
|
|
384
|
+
|
|
385
|
+
## D64 — `command(run)` остаётся на тестовом входе
|
|
386
|
+
|
|
387
|
+
`command(run)` живёт в `@opetope/react/testing`, `defineCallTarget` публичным не становится. фикстуре нужна идентичность вызова, но конструктор целей ради тестов не открывают. Уточняет: [D49](#d49).
|
|
388
|
+
|
|
389
|
+
<a id="d65"></a>
|
|
390
|
+
|
|
391
|
+
## D65 — `defineRoot` остаётся обязательным
|
|
392
|
+
|
|
393
|
+
UI использует contribution frame Slot; отдельные публичные root declarations не требуются. См. [D85](#d85), [D188](#d188).
|
|
394
|
+
|
|
395
|
+
<a id="d66"></a>
|
|
396
|
+
|
|
397
|
+
## D66 — authority-слой удалён, `uiGrants` нет
|
|
398
|
+
|
|
399
|
+
Модель принадлежит lifetime своего владельца; contribution frame определяет доступ UI. Действующая модель монтажа — [D85](#d85), [D188](#d188), [D209](#d209).
|
|
400
|
+
|
|
401
|
+
<a id="d67"></a>
|
|
402
|
+
|
|
403
|
+
## D67 — слоты принадлежат `@opetope/react`
|
|
404
|
+
|
|
405
|
+
`defineSlot`, `defineSwitchSlot` и `Slot` остаются в `react`; типы это `SlotTarget`, `SwitchSlotTarget`, `SlotContribution`. слот рендерит разметку и без React смысла не имеет. Уточняет: [D58](#d58).
|
|
406
|
+
|
|
407
|
+
<a id="d68"></a>
|
|
408
|
+
|
|
409
|
+
## D68 — композиция приложения упрощена
|
|
410
|
+
|
|
411
|
+
мир выводится как roots, члены доменов и транзитивное замыкание импортов; приложение получает обязательный `id`, `defineDomain` переходит на `when`, а `openApplication` принимает `signals` и `bind(contract, value)`. перечислять мир руками — работа компилятора.
|
|
412
|
+
|
|
413
|
+
<a id="d69"></a>
|
|
414
|
+
|
|
415
|
+
## D69 — один класс ошибки на субъект, состояние в `code`
|
|
416
|
+
|
|
417
|
+
`GenerationError` (`inactive`, `not-ready`, `quarantined`, `cleanup-failed`), `CallError` (`cancelled`, `closed`, `publication-rejected`), `ReadableError`, `RootError`, `ModelError`, `ActionError`, `ApplicationError`, `DeclarationError`; `isCancellation` это маркер отменяющих кодов. класс на состояние раздувал вход — 44 значения при цели 40. Уточняет: [D13](#d13), [D53](#d53).
|
|
418
|
+
|
|
419
|
+
<a id="d70"></a>
|
|
420
|
+
|
|
421
|
+
## D70 — вклад получает авторитет на моделях своего экземпляра
|
|
422
|
+
|
|
423
|
+
`Slot` рендерит вклад внутри неявного module-frame фичи-контрибьютора, поэтому в `Component` работают `useModel` на любую модель этого экземпляра и хуки поверх её полей; strict-набор остаётся у явных корней. иначе вклад читает состояние через пропсы и хост становится передатчиком данных фичи.
|
|
424
|
+
|
|
425
|
+
<a id="d71"></a>
|
|
426
|
+
|
|
427
|
+
## D71 — режим `observe` удалён
|
|
428
|
+
|
|
429
|
+
`Command<Input, Output>` без режима, `CommandHook` это `{ run, inFlight, lastError }`, `useCommand` не держит listener на invoker; наблюдаемое состояние вызова модель отдаёт полем `Readable`. режим был вторым способом смотреть на вызов, а харнесс строится через `externalReadable`. Уточняет: [D30](#d30).
|
|
430
|
+
|
|
431
|
+
<a id="d72"></a>
|
|
432
|
+
|
|
433
|
+
## D72 — `OwnedState<Value>` в публичном словаре
|
|
434
|
+
|
|
435
|
+
`ctx.state` возвращает `OwnedState`, `ctx.update` принимает только его, поэтому чужой `Readable` отвергается компилятором. иначе владение проверяется только в рантайме. Уточняет: [D38](#d38).
|
|
436
|
+
|
|
437
|
+
<a id="d73"></a>
|
|
438
|
+
|
|
439
|
+
## D73 — у модели свой kernel
|
|
440
|
+
|
|
441
|
+
`ModelContext` в полном составе — `call`, `lane`, `effect`, `event`, `resource`, `stream`, `scope`, `own` рядом с `state`, `update`, `signal`; узлы живут от открытия экземпляра до retire, а `from` это готовое значение: у модели нет импортов. без своего kernel-а роль узлов модели играли deps. Уточняет: [D37](#d37).
|
|
442
|
+
|
|
443
|
+
<a id="d74"></a>
|
|
444
|
+
|
|
445
|
+
## D74 — транспорт не расширяет словарь модели
|
|
446
|
+
|
|
447
|
+
Модель объявляет зависимости интерфейсом и получает готовые значения при создании; отдельного ленивого источника моделей не требуется. См. [D169](#d169).
|
|
448
|
+
|
|
449
|
+
<a id="d75"></a>
|
|
450
|
+
|
|
451
|
+
## D75 — типы политик публичны
|
|
452
|
+
|
|
453
|
+
`scoped` и `latest` возвращают `ScopedRetention` и `LatestBackpressure`, оба имени публичны. правило [D61](#d61) — тип результата публичного значения не уходит в `internal`.
|
|
454
|
+
|
|
455
|
+
<a id="d76"></a>
|
|
456
|
+
|
|
457
|
+
## D76 — `listenerMultiplicity.root` под контракт после D71
|
|
458
|
+
|
|
459
|
+
`useCommand` держит ноль listener-ов на invoker, `useReadable` ровно один на `Readable`, после unmount ноль и там, и там. проверка требовала listener на хук, а [D71](#d71) убрал подписку у `useCommand`. Уточняет: [D32](#d32).
|
|
460
|
+
|
|
461
|
+
<a id="d77"></a>
|
|
462
|
+
|
|
463
|
+
## D77 — метрика на операцию без разовой материализации
|
|
464
|
+
|
|
465
|
+
`measure` берёт `before` после открытия харнесса, `sampleHeap` собирает мусор перед `liveBytes()`. Уточняет: [D33](#d33).
|
|
466
|
+
|
|
467
|
+
<a id="d78"></a>
|
|
468
|
+
|
|
469
|
+
## D78 — состав чанка вместо подъёма cap
|
|
470
|
+
|
|
471
|
+
Изменение области видимости API должно сопровождаться обновлением типов и исполняемых consumer examples. Внутренний ABI не становится словарём UI.
|
|
472
|
+
|
|
473
|
+
<a id="d79"></a>
|
|
474
|
+
|
|
475
|
+
## D79 — вклад получает опцию `when`
|
|
476
|
+
|
|
477
|
+
Отключённый diagnostic consumer не должен создавать runtime subscriptions и работу в горячем пути. Наблюдение включается явно.
|
|
478
|
+
|
|
479
|
+
<a id="d80"></a>
|
|
480
|
+
|
|
481
|
+
## D80 — секция владения называется `own`
|
|
482
|
+
|
|
483
|
+
`defineFeature({ own })`, контексты `exports`, `provides`, `ui` отдают `own`. секция называет владение, а не настройку. Уточняет: [D5](#d5).
|
|
484
|
+
|
|
485
|
+
<a id="d81"></a>
|
|
486
|
+
|
|
487
|
+
## D81 — авторские имена без слова generation
|
|
488
|
+
|
|
489
|
+
`GenerationBoundary`→`FeatureBoundary`, `useGenerationDemand`→`useFeature`, `Generation`→`FeatureInstance`, `GenerationError`→`FeatureError`, код `inactive`→`retired`; `FeatureBoundaryError` отдельным классом, потому что субъект тут не поколение, а отсутствующий boundary. поколение это слово рантайма, автор видит экземпляр фичи.
|
|
490
|
+
|
|
491
|
+
<a id="d82"></a>
|
|
492
|
+
|
|
493
|
+
## D82 — `fold` у `pipe` трекуемый
|
|
494
|
+
|
|
495
|
+
обработчик получает `{ get }` третьим аргументом, `fold(value, meta, get?)` — третьим параметром, поэтому в `computed` результат подписан и на `entries`, и на прочитанное обработчиками. без трекинга fold пересчитывался только при смене состава вкладов.
|
|
496
|
+
|
|
497
|
+
<a id="d83"></a>
|
|
498
|
+
|
|
499
|
+
## D83 — `defineHostContract` вместо `defineHostImport`
|
|
500
|
+
|
|
501
|
+
`HostImport<Value>`→`HostContract<Value>`, `OnDemandHostImport`→`OnDemandHostContract`; `bind` не менялся. слово «контракт» уже стоит в `bind(contract, value)`, а `Host` отвечает, кто его исполняет.
|
|
502
|
+
|
|
503
|
+
<a id="d84"></a>
|
|
504
|
+
|
|
505
|
+
## D84 — см. D89
|
|
506
|
+
|
|
507
|
+
`own`→`timers` во всех пяти контекстах (`ModelContext`, `ModelEffectContext`, `ModelEventSubscribeContext`, `ModelScopeOpen`, `open`/`close` вложений). слово `own` закреплено за секцией владения ([D80](#d80)) и `OwnedState`, а `cleanup.delay(…)` читалось бы неверно. См. [D89](#d89).
|
|
508
|
+
|
|
509
|
+
<a id="d85"></a>
|
|
510
|
+
|
|
511
|
+
## D85 — секция `ui` и корни уходят, UI входит вкладами
|
|
512
|
+
|
|
513
|
+
уходят секция `ui` и её builder, `defineRoot`, `input`, `action`, `FeatureRoot`, `renderRoot`, `mapCommand`, типы `Root`, `RootInput`, `Action` и strict-frame; остаются `FeatureBoundary`, `useFeature`, `useFeatureRetry`, `useFeatureError` с обычным `ReactNode` в children. Форма вклада `slot(target, value|factory, { priority, when })` со `value` вида `{ Component, props?, models? }`: `props` это адаптер `(slotProps) => componentProps`, `models` — UI-модели вклада, а `requiresModels([...])(Component)` проверяется типом на его границе. корень был вторым способом входа UI в приложение, а вклады уже несут авторитет моделей ([D70](#d70)). Уточняет: [D10](#d10), [D11](#d11), [D19](#d19), [D46](#d46), [D48](#d48), [D51](#d51), [D55](#d55), [D63](#d63), [D65](#d65) (не редактируются).
|
|
514
|
+
|
|
515
|
+
<a id="d86"></a>
|
|
516
|
+
|
|
517
|
+
## D86 — доменные исходы это возвращаемые значения
|
|
518
|
+
|
|
519
|
+
`useCommand` отдаёт `result` последнего исхода `ok`, `throw` остаётся для исключительного, а форма `{ type: 'ok'; data } | { type: 'error'; error }` это конвенция, не тип фреймворка. доменная ошибка это ответ продукта, и на исключениях UI её не различал.
|
|
520
|
+
|
|
521
|
+
<a id="d87"></a>
|
|
522
|
+
|
|
523
|
+
## D87 — см. D118
|
|
524
|
+
|
|
525
|
+
фабрика вклада остаётся фабрикой экземпляра, а per-mount часть это `models`: `model(Decl, create)`, где `create` получает `(ctx, props)` — `Readable` пропсов этого монтирования. фабрика поколения не видит пропсов монтирования; отклонены фабрика на каждое монтирование и отдельный per-mount член. См. [D118](#d118).
|
|
526
|
+
|
|
527
|
+
<a id="d88"></a>
|
|
528
|
+
|
|
529
|
+
## D88 — см. D98
|
|
530
|
+
|
|
531
|
+
запись принимает `Call`, `Readable` и `Resource`; владеемое состояние выходит суженным до `Readable` (писатель остаётся у владельца), а модель целиком не экспортируется. экспорт ref-ов заставлял импортера самого материализовать значение. См. [D98](#d98).
|
|
532
|
+
|
|
533
|
+
<a id="d89"></a>
|
|
534
|
+
|
|
535
|
+
## D89 — namespace владеемых таймеров это `timers`
|
|
536
|
+
|
|
537
|
+
`own`→`timers` во всех пяти контекстах (`ModelContext`, `ModelEffectContext`, `ModelEventSubscribeContext`, `ModelScopeOpen`, `open`/`close` вложений). слово `own` закреплено за секцией владения ([D80](#d80)) и `OwnedState`, а `cleanup.delay(…)` читалось бы неверно. Уточняет: [D84](#d84).
|
|
538
|
+
|
|
539
|
+
<a id="d90"></a>
|
|
540
|
+
|
|
541
|
+
## D90 — type-only реэкспорт внутри границы фреймворка
|
|
542
|
+
|
|
543
|
+
линт допускает в `opetope/*/src` type-only реэкспорт там, где маршрут уже разрешён на импорт; value-реэкспорт запрещён, для потребителей запрет не меняется. политика линта, а не форма API.
|
|
544
|
+
|
|
545
|
+
<a id="d91"></a>
|
|
546
|
+
|
|
547
|
+
## D91 — см. D99, D101, D105
|
|
548
|
+
|
|
549
|
+
optional оформляет слабое ребро без принудительного открытия провайдера; текущий результат — Lookup со found/missing. См. [D99](#d99), [D101](#d101), [D105](#d105). отменены [D105](#d105).
|
|
550
|
+
|
|
551
|
+
<a id="d92"></a>
|
|
552
|
+
|
|
553
|
+
## D92 — см. D105
|
|
554
|
+
|
|
555
|
+
`optional` в `imports` и `requires` это слабое ребро: потребитель может жить дольше провайдера, экспорты приходят как `Readable<Lookup<Exports>>`, вызов слабого порта оседает `CallError` кодом `unavailable`, а провайдер вне приложения это постоянно отсутствующий провайдер. См. [D105](#d105).
|
|
556
|
+
|
|
557
|
+
<a id="d93"></a>
|
|
558
|
+
|
|
559
|
+
## D93 — см. D102
|
|
560
|
+
|
|
561
|
+
`defineCondition({ id })` привязывает хост, `defineCondition({ from, id, select })` вычисляет факт из экспортов одной фичи и хосту не принадлежит; `defineFeature({ when: [Condition] })` задаёт время жизни и строк не принимает; в `defineApplication({ id, features, reporter })` `roots` и `domains` удалены, а группа фич с одинаковым набором условий это выведенный домен для порядка активации и плана devtools; `openApplication` принимает `conditions`, а `defineSignal`, `Signal` и `Domain` ушли с публичного входа. домен был вторым местом объявления времени жизни, и хост мог его переопределить. См. [D102](#d102).
|
|
562
|
+
|
|
563
|
+
<a id="d94"></a>
|
|
564
|
+
|
|
565
|
+
## D94 — см. D109, D110, D112, D113, D114
|
|
566
|
+
|
|
567
|
+
`TaskExecutor`→`CallExecutor`, `TaskLane`→`CallLane`, `TaskCall`→`CallInvocation`, поле `task` рецепта стало `policy`, метрика `listenerMultiplicity.task`→`.call`; `Attachment`, `Scope`, `Lane`, `Hub` остались. у автора вызов называется `call`, kernel не имеет права звать тот же концепт иначе. См. [D109](#d109), [D110](#d110), [D112](#d112), [D113](#d113), [D114](#d114).
|
|
568
|
+
|
|
569
|
+
<a id="d95"></a>
|
|
570
|
+
|
|
571
|
+
## D95 — см. D107, D108
|
|
572
|
+
|
|
573
|
+
диспозер выполняется в том же drain, что диспозеры узлов модели, в обратном порядке; после фенса регистрация это `TypeError`, как у `timers`. уборку без узла некуда было положить; вложениям член не добавлен — у них есть колбэк `close`. См. [D107](#d107), [D108](#d108).
|
|
574
|
+
|
|
575
|
+
<a id="d96"></a>
|
|
576
|
+
|
|
577
|
+
## D96 — `gateway` и секция `gateways` удаляются
|
|
578
|
+
|
|
579
|
+
уходят builder `gateway`, ключ `gateways` и скрытые вложения `gatewayN`; owned I/O это `attach` плюс `call({ within })`, `ctx.stream` или `ctx.event`, методы хоста — `calls`. Уточняет: [D18](#d18), [D97](#d97).
|
|
580
|
+
|
|
581
|
+
<a id="d97"></a>
|
|
582
|
+
|
|
583
|
+
## D97 — см. D96
|
|
584
|
+
|
|
585
|
+
уходят builder `gateway`, ключ `gateways` и скрытые вложения `gatewayN`; owned I/O это `attach` плюс `call({ within })`, `ctx.stream` или `ctx.event`, методы хоста — `calls`. См. [D96](#d96).
|
|
586
|
+
|
|
587
|
+
<a id="d98"></a>
|
|
588
|
+
|
|
589
|
+
## D98 — `exports` вычисляется на открытии с живым `own`
|
|
590
|
+
|
|
591
|
+
запись принимает `Call`, `Readable` и `Resource`; владеемое состояние выходит суженным до `Readable` (писатель остаётся у владельца), а модель целиком не экспортируется. экспорт ref-ов заставлял импортера самого материализовать значение. Уточняет: [D39](#d39) (не редактируется), [D88](#d88).
|
|
592
|
+
|
|
593
|
+
<a id="d99"></a>
|
|
594
|
+
|
|
595
|
+
## D99 — `optional(x)` в `imports`
|
|
596
|
+
|
|
597
|
+
optional оформляет слабое ребро без принудительного открытия провайдера; текущий результат — Lookup со found/missing. См. [D105](#d105).
|
|
598
|
+
|
|
599
|
+
<a id="d100"></a>
|
|
600
|
+
|
|
601
|
+
## D100 — см. D101
|
|
602
|
+
|
|
603
|
+
ref остаётся на define, `undefined` появляется только там, где ref материализуется — живой `own`, `exports`, источник `attach`, фабрика модели. присутствие порта известно только на компиляции приложения, а builder обязан вернуть ref; отклонён `CallError unavailable` у живого ref. См. [D101](#d101).
|
|
604
|
+
|
|
605
|
+
<a id="d101"></a>
|
|
606
|
+
|
|
607
|
+
## D101 — `optional(port)` в `requires`, вариант (а)
|
|
608
|
+
|
|
609
|
+
ref остаётся на define, `undefined` появляется только там, где ref материализуется — живой `own`, `exports`, источник `attach`, фабрика модели. присутствие порта известно только на компиляции приложения, а builder обязан вернуть ref; отклонён `CallError unavailable` у живого ref. Отменено [D105](#d105).
|
|
610
|
+
|
|
611
|
+
<a id="d102"></a>
|
|
612
|
+
|
|
613
|
+
## D102 — время жизни объявляет фича
|
|
614
|
+
|
|
615
|
+
`defineCondition({ id })` привязывает хост, `defineCondition({ from, id, select })` вычисляет факт из экспортов одной фичи и хосту не принадлежит; `defineFeature({ when: [Condition] })` задаёт время жизни и строк не принимает; в `defineApplication({ id, features, reporter })` `roots` и `domains` удалены, а группа фич с одинаковым набором условий это выведенный домен для порядка активации и плана devtools; `openApplication` принимает `conditions`, а `defineSignal`, `Signal` и `Domain` ушли с публичного входа. домен был вторым местом объявления времени жизни, и хост мог его переопределить. Уточняет: [D68](#d68) (не редактируется), [D93](#d93), [D103](#d103).
|
|
616
|
+
|
|
617
|
+
<a id="d103"></a>
|
|
618
|
+
|
|
619
|
+
## D103 — см. D102
|
|
620
|
+
|
|
621
|
+
`defineCondition({ id })` привязывает хост, `defineCondition({ from, id, select })` вычисляет факт из экспортов одной фичи и хосту не принадлежит; `defineFeature({ when: [Condition] })` задаёт время жизни и строк не принимает; в `defineApplication({ id, features, reporter })` `roots` и `domains` удалены, а группа фич с одинаковым набором условий это выведенный домен для порядка активации и плана devtools; `openApplication` принимает `conditions`, а `defineSignal`, `Signal` и `Domain` ушли с публичного входа. домен был вторым местом объявления времени жизни, и хост мог его переопределить. См. [D102](#d102).
|
|
622
|
+
|
|
623
|
+
<a id="d104"></a>
|
|
624
|
+
|
|
625
|
+
## D104 — см. D105, D106
|
|
626
|
+
|
|
627
|
+
`optional` в `imports` и `requires` это слабое ребро: потребитель может жить дольше провайдера, экспорты приходят как `Readable<Lookup<Exports>>`, вызов слабого порта оседает `CallError` кодом `unavailable`, а провайдер вне приложения это постоянно отсутствующий провайдер. См. [D105](#d105), [D106](#d106).
|
|
628
|
+
|
|
629
|
+
<a id="d105"></a>
|
|
630
|
+
|
|
631
|
+
## D105 — `optional` и `onDemand` сливаются в одно слово
|
|
632
|
+
|
|
633
|
+
`optional` в `imports` и `requires` это слабое ребро: потребитель может жить дольше провайдера, экспорты приходят как `Readable<Lookup<Exports>>`, вызов слабого порта оседает `CallError` кодом `unavailable`, а провайдер вне приложения это постоянно отсутствующий провайдер. Compile-time формы [D99](#d99) и [D101](#d101) удалены, `onDemand` остался только у host-контрактов, слабое ребро не влияет на активацию, тип `Lookup` публичен в форме `selectByKey`. два слова описывали одно — «значения может не быть». Уточняет: [D91](#d91), [D99](#d99), [D101](#d101), [D92](#d92), [D104](#d104), [D106](#d106).
|
|
634
|
+
|
|
635
|
+
<a id="d106"></a>
|
|
636
|
+
|
|
637
|
+
## D106 — см. D105
|
|
638
|
+
|
|
639
|
+
`optional` в `imports` и `requires` это слабое ребро: потребитель может жить дольше провайдера, экспорты приходят как `Readable<Lookup<Exports>>`, вызов слабого порта оседает `CallError` кодом `unavailable`, а провайдер вне приложения это постоянно отсутствующий провайдер. См. [D105](#d105).
|
|
640
|
+
|
|
641
|
+
<a id="d107"></a>
|
|
642
|
+
|
|
643
|
+
## D107 — `ModelContext.cleanup(disposer)`
|
|
644
|
+
|
|
645
|
+
диспозер выполняется в том же drain, что диспозеры узлов модели, в обратном порядке; после фенса регистрация это `TypeError`, как у `timers`. уборку без узла некуда было положить; вложениям член не добавлен — у них есть колбэк `close`.
|
|
646
|
+
|
|
647
|
+
<a id="d108"></a>
|
|
648
|
+
|
|
649
|
+
## D108 — адаптеры сторонних библиотек состояния
|
|
650
|
+
|
|
651
|
+
`@opetope/adapter-effector` и `@opetope/adapter-mobx` строятся как `externalReadable` плюс `adaptRecord` и живут отдельными пакетами вне бюджета трёх входов. ядро не зависит от библиотек; форма зафиксирована, реализация в очередь не входит.
|
|
652
|
+
|
|
653
|
+
<a id="d109"></a>
|
|
654
|
+
|
|
655
|
+
## D109 — `Task*` → `Call*`
|
|
656
|
+
|
|
657
|
+
`TaskExecutor`→`CallExecutor`, `TaskLane`→`CallLane`, `TaskCall`→`CallInvocation`, поле `task` рецепта стало `policy`, метрика `listenerMultiplicity.task`→`.call`; `Attachment`, `Scope`, `Lane`, `Hub` остались. у автора вызов называется `call`, kernel не имеет права звать тот же концепт иначе.
|
|
658
|
+
|
|
659
|
+
<a id="d110"></a>
|
|
660
|
+
|
|
661
|
+
## D110 — `Domain` и `Generation` как имена концептов
|
|
662
|
+
|
|
663
|
+
`DomainExecution`→`ConditionGroupExecution`, `DomainGeneration`→`GroupMemberInstance`, одна жизнь фичи это instance (`openFeatureGeneration`→`openFeatureInstance`); счётчик поколения в kernel-слотах остался — это номер, а не концепт. домены удалены [D102](#d102), поколение как концепт заменено экземпляром ([D81](#d81)).
|
|
664
|
+
|
|
665
|
+
<a id="d111"></a>
|
|
666
|
+
|
|
667
|
+
## D111 — см. D114
|
|
668
|
+
|
|
669
|
+
`module` это единица lowering — фича или ребёнок динамического scope, — поэтому `defineModule`, `instantiateModule` и `Module*Ref` не переименовываются, а гейт запрещает слово в именах безопасных входов и в сообщениях. сплошное переименование давало столкновения с публичным словарём (`ModuleInstanceRef` рядом с `FeatureInstance`); отклонён и промежуточный `Lowered*`. См. [D114](#d114).
|
|
670
|
+
|
|
671
|
+
<a id="d112"></a>
|
|
672
|
+
|
|
673
|
+
## D112 — `step`, поле `instance` и forbidden-word гейт
|
|
674
|
+
|
|
675
|
+
контексты `open` вложений носят член `step`, а не namespace `own`; `FeatureDemandState.generation`→`instance`, `SignalSnapshot`→`ConditionSnapshot`, а гейт запрещает снятому слову выжить в любой позиции идентификатора внутренних входов. слово `own` закреплено за секцией владения, а без гейта снятые слова возвращались.
|
|
676
|
+
|
|
677
|
+
<a id="d113"></a>
|
|
678
|
+
|
|
679
|
+
## D113 — слово `capability` становится `port`
|
|
680
|
+
|
|
681
|
+
`feature-capability.ts`→`feature-port.ts`, `compileApplicationCapabilities`→`compileApplicationPorts`, локальные `capabilities`→`ports`, гейт получил шаблон `[Cc]apabilit`. у автора это `port` ([D9](#d9), [D45](#d45)).
|
|
682
|
+
|
|
683
|
+
<a id="d114"></a>
|
|
684
|
+
|
|
685
|
+
## D114 — `module` остаётся kernel-словом, вариант (б)
|
|
686
|
+
|
|
687
|
+
`module` это единица lowering — фича или ребёнок динамического scope, — поэтому `defineModule`, `instantiateModule` и `Module*Ref` не переименовываются, а гейт запрещает слово в именах безопасных входов и в сообщениях. сплошное переименование давало столкновения с публичным словарём (`ModuleInstanceRef` рядом с `FeatureInstance`); отклонён и промежуточный `Lowered*`. Уточняет: [D111](#d111).
|
|
688
|
+
|
|
689
|
+
<a id="d115"></a>
|
|
690
|
+
|
|
691
|
+
## D115 — ленивая загрузка тела фичи
|
|
692
|
+
|
|
693
|
+
Header/body splitting отделяет описание границы фичи от загрузки кода. Body загружается при открытии; preload не открывает instance. Ready и retirement соблюдают lifetime независимо от общей загрузки. См. [D186](#d186), [D207](#d207), [D208](#d208), [D211](#d211).
|
|
694
|
+
|
|
695
|
+
<a id="d116"></a>
|
|
696
|
+
|
|
697
|
+
## D116 — `useCommand` отдаёт `result`
|
|
698
|
+
|
|
699
|
+
`{ run, inFlight, result, lastError }`: `result` переживает следующий запуск, `lastError` чистит только успех, `cancelled` не меняет ни того, ни другого. отмена это не ответ продукта. Уточняет: [D86](#d86) (исполнение).
|
|
700
|
+
|
|
701
|
+
<a id="d117"></a>
|
|
702
|
+
|
|
703
|
+
## D117 — проверка объявленных моделей вклада
|
|
704
|
+
|
|
705
|
+
Модели UI доступны только через разрешённый contribution frame; declared UI models проверяются типами, runtime и отдельным lint gate. Вклад сохраняет owner by entry; requiresModels описывает потребности компонента. См. [D121](#d121), [D188](#d188), [D214](#d214).
|
|
706
|
+
|
|
707
|
+
<a id="d118"></a>
|
|
708
|
+
|
|
709
|
+
## D118 — per-mount `models` получают `(ctx, props)`, вариант (б)
|
|
710
|
+
|
|
711
|
+
фабрика вклада остаётся фабрикой экземпляра, а per-mount часть это `models`: `model(Decl, create)`, где `create` получает `(ctx, props)` — `Readable` пропсов этого монтирования. фабрика поколения не видит пропсов монтирования; отклонены фабрика на каждое монтирование и отдельный per-mount член. Уточняет: [D87](#d87).
|
|
712
|
+
|
|
713
|
+
<a id="d119"></a>
|
|
714
|
+
|
|
715
|
+
## D119 — см. D120
|
|
716
|
+
|
|
717
|
+
поднят с 29 до 31 кБ как новый ratchet — опускается вместе с диетой рантайма и не поднимается ради прохода. минимальная фича весит 29.86 кБ brotli, а снятие `resource` или `register` меняет вес на 40–140 байт: граф почти монолитен. См. [D120](#d120).
|
|
718
|
+
|
|
719
|
+
<a id="d120"></a>
|
|
720
|
+
|
|
721
|
+
## D120 — бюджет `public feature consumer` 31 кБ
|
|
722
|
+
|
|
723
|
+
поднят с 29 до 31 кБ как новый ratchet — опускается вместе с диетой рантайма и не поднимается ради прохода. минимальная фича весит 29.86 кБ brotli, а снятие `resource` или `register` меняет вес на 40–140 байт: граф почти монолитен. Уточняет: [D119](#d119).
|
|
724
|
+
|
|
725
|
+
<a id="d121"></a>
|
|
726
|
+
|
|
727
|
+
## D121 — монтирование, дошедшее до коммита закрытым, пересобирается
|
|
728
|
+
|
|
729
|
+
Создание UI-моделей и side effects выполняется только после commit. Временное скрытие Suspense сохраняет committed bundle, окончательный unmount его закрывает. Действующий контракт — [D188](#d188), [D209](#d209).
|
|
730
|
+
|
|
731
|
+
<a id="d122"></a>
|
|
732
|
+
|
|
733
|
+
## D122 — форма порта наблюдения Phase 1
|
|
734
|
+
|
|
735
|
+
`createInspectionSession(execution, { ringCapacity })` только на `@opetope/runtime/internal`, связь через `WeakMap`; протокол devtools рантайм реализует, а не импортирует, и диффит записи чтением на коммите. наблюдение не имеет права добавить ни одной подписки.
|
|
736
|
+
|
|
737
|
+
<a id="d123"></a>
|
|
738
|
+
|
|
739
|
+
## D123 — порядок между группами условий и проекция слабого импорта
|
|
740
|
+
|
|
741
|
+
порядок берётся из жёстких рёбер плана и API не меняет: контроллер группы получает `order` с `awaitProvidersReady` перед открытием членов и `awaitConsumersClosed` перед снятием, а проекция слабого импорта держит подписчиков сама. ребро между группами качалось двумя контроллерами, и потребитель открывался, пока провайдер ещё открывался; ждать, а не падать.
|
|
742
|
+
|
|
743
|
+
<a id="d124"></a>
|
|
744
|
+
|
|
745
|
+
## D124 — атомарность публикации вкладов
|
|
746
|
+
|
|
747
|
+
подписка на `when` вынесена в preflight `hub.watch(entries)` до мутаций, отказ откатывает наблюдателей, а охранник видимости ставит `dirty`.
|
|
748
|
+
|
|
749
|
+
<a id="d125"></a>
|
|
750
|
+
|
|
751
|
+
## D125 — присоединение к идущему закрытию
|
|
752
|
+
|
|
753
|
+
`retire()` в состоянии `closing` возвращает handle, ждущий текущий drain; узлы модели после фенса отказывают тем же `TypeError`, что `cleanup` и `timers`.
|
|
754
|
+
|
|
755
|
+
<a id="d126"></a>
|
|
756
|
+
|
|
757
|
+
## D126 — наблюдение не касается жизненного цикла
|
|
758
|
+
|
|
759
|
+
хуки сессии идут внутри охранника, поэтому отказ наблюдающей половины уходит в reporter, а не в `retire()`; потребитель получает фасад с замороженными записями.
|
|
760
|
+
|
|
761
|
+
<a id="d127"></a>
|
|
762
|
+
|
|
763
|
+
## D127 — авторские отказы и реестры
|
|
764
|
+
|
|
765
|
+
`exports: ({ own }) => own` принимается, а член без формы значения падает на своём ключе; запись модели проверяется на открытии, `pipe` различает фабрику и обработчик по арности, реестр id приложений держит определение слабо.
|
|
766
|
+
|
|
767
|
+
<a id="d128"></a>
|
|
768
|
+
|
|
769
|
+
## D128 — публичные типы без kernel-слов
|
|
770
|
+
|
|
771
|
+
`FeatureInstance.instance` получил псевдоним `FeatureInstanceHandle`, поле модели с писателем сужается до `Readable` при пересечении `exports`, план UI-модели сверх пропсов цели отвергается типом.
|
|
772
|
+
|
|
773
|
+
<a id="d129"></a>
|
|
774
|
+
|
|
775
|
+
## D129 — независимые гейты корректности и стоимости
|
|
776
|
+
|
|
777
|
+
Public-surface, types, package consumers и численные бюджеты проверяются независимыми гейтами. Успех одного тестового слоя не заменяет типизацию, реальную упаковку или browser path.
|
|
778
|
+
|
|
779
|
+
<a id="d130"></a>
|
|
780
|
+
|
|
781
|
+
## D130 — измеренная производительность
|
|
782
|
+
|
|
783
|
+
чтение активного чистого узла возвращает осевшее значение сразу — было O(графа) на каждом `getSnapshot`; монтирование вклада мемоизировано, `readyListeners` разделены по индексу фичи.
|
|
784
|
+
|
|
785
|
+
<a id="d131"></a>
|
|
786
|
+
|
|
787
|
+
## D131 — состав чанка вместо ослабления бюджетов
|
|
788
|
+
|
|
789
|
+
Публичный feature API остаётся независимым от конкретного хоста; адаптация внешних сервисов находится за host contracts.
|
|
790
|
+
|
|
791
|
+
<a id="d132"></a>
|
|
792
|
+
|
|
793
|
+
## D132 — граница прикладной интеграции
|
|
794
|
+
|
|
795
|
+
Связь feature с внешним приложением выполняется через integration boundary и explicit imports/requirements.
|
|
796
|
+
|
|
797
|
+
<a id="d133"></a>
|
|
798
|
+
|
|
799
|
+
## D133 — первое прикладное внедрение application graph
|
|
800
|
+
|
|
801
|
+
Application graph собирается из объявленных features и их hard-import closure; конкретный состав графа принадлежит приложению, а не библиотеке.
|
|
802
|
+
|
|
803
|
+
<a id="d134"></a>
|
|
804
|
+
|
|
805
|
+
## D134 — транзакционная активация реактивного графа
|
|
806
|
+
|
|
807
|
+
`scheduler.activate` запоминает активированные узлы и при отказе откатывает их в обратном порядке, агрегируя отказы диспозеров с исходной причиной. отказ на середине оставлял часть графа активной без владельца подписки.
|
|
808
|
+
|
|
809
|
+
<a id="d135"></a>
|
|
810
|
+
|
|
811
|
+
## D135 — ratchet `data layer consumer` до 4.9 кБ
|
|
812
|
+
|
|
813
|
+
бюджет поднят с фиксацией факта: транзакционная активация ([D134](#d134)) стоила фикстуре 0.21 кБ brotli. диета без потери закона дала ноль — brotli на неё не отвечает; цена закона названа в строке, а не спрятана в число.
|
|
814
|
+
|
|
815
|
+
<a id="d136"></a>
|
|
816
|
+
|
|
817
|
+
## D136 — граница адаптера внешнего хранилища
|
|
818
|
+
|
|
819
|
+
Реактивный адаптер сохраняет семантику источника и явно выбирает equals. Pass-through не должен добавлять второе владение или незаметно терять обновления.
|
|
820
|
+
|
|
821
|
+
<a id="d137"></a>
|
|
822
|
+
|
|
823
|
+
## D137 — тексты авторских отказов
|
|
824
|
+
|
|
825
|
+
`FeatureError('retired')` говорит «Feature <id> instance is retired.», тексты `CallError` не говорят «authority», а отказ без провайдера называет исправление; гейт сканирует аргументы классов ошибок.
|
|
826
|
+
|
|
827
|
+
<a id="d138"></a>
|
|
828
|
+
|
|
829
|
+
## D138 — отмена это два кода `CallError`
|
|
830
|
+
|
|
831
|
+
бренд отмены несут только `cancelled` и `closed`; `unavailable` и `publication-rejected` приходят исходом `failed`, а маркер ставится по множеству кодов, а не наследованием.
|
|
832
|
+
|
|
833
|
+
<a id="d139"></a>
|
|
834
|
+
|
|
835
|
+
## D139 — `state` уходит из `own`-builder-а фичи
|
|
836
|
+
|
|
837
|
+
метод удалён целиком; владеемое состояние остаётся только в модели, а фича отдаёт значение полем модели через `exports`.
|
|
838
|
+
|
|
839
|
+
<a id="d140"></a>
|
|
840
|
+
|
|
841
|
+
## D140 — бюджетов размера остаётся пять
|
|
842
|
+
|
|
843
|
+
живут `author primitives consumer` (1.1 кБ), `data layer consumer` (4.9 кБ), `public feature consumer` (31 кБ), `application graph consumer` (48 кБ), `@opetope/react` (18 кБ) и cap чанка 64 кБ.
|
|
844
|
+
|
|
845
|
+
<a id="d141"></a>
|
|
846
|
+
|
|
847
|
+
## D141 — владеемые scope-ы вложения удалены
|
|
848
|
+
|
|
849
|
+
ушли `attach<Value>({ open, close })` без источника и ключ `scopes` у `openFeature`/`openApplication`; значение вложения приходит ровно одним путём — из `imports`.
|
|
850
|
+
|
|
851
|
+
<a id="d142"></a>
|
|
852
|
+
|
|
853
|
+
## D142 — три слова уходят с безопасных входов
|
|
854
|
+
|
|
855
|
+
`createState` и `isCancellation` переехали в `@opetope/core/internal`, `useFeatureError` удалён, контекст boundary несёт только `retry`.
|
|
856
|
+
|
|
857
|
+
<a id="d143"></a>
|
|
858
|
+
|
|
859
|
+
## D143 — `ModelContext.calls(source, keys, { lane? })`
|
|
860
|
+
|
|
861
|
+
семантика и вывод типов как у `calls` в `own`, необязательная lane сериализует набор; типы выбора ключей переехали в `@opetope/core`, поэтому `own.calls` и `ctx.calls` отвергают одно и то же.
|
|
862
|
+
|
|
863
|
+
<a id="d144"></a>
|
|
864
|
+
|
|
865
|
+
## D144 — `Readable` вместо per-mount модели вклада
|
|
866
|
+
|
|
867
|
+
Размеры и задержки оцениваются воспроизводимыми workload; бюджет не заменяет проверку корректности.
|
|
868
|
+
|
|
869
|
+
<a id="d145"></a>
|
|
870
|
+
|
|
871
|
+
## D145 — сахар `retain` у `FeatureBoundary`
|
|
872
|
+
|
|
873
|
+
Authoring sugar должен сохранять типы, lifetime, signal и receiver методов; краткость не создаёт второй путь исполнения. См. [D244](#d244).
|
|
874
|
+
|
|
875
|
+
<a id="d146"></a>
|
|
876
|
+
|
|
877
|
+
## D146 — закрытие распространяется
|
|
878
|
+
|
|
879
|
+
`State.close()` публикует уведомление в обычной транзакции и только потом отпускает слушателей, поэтому активные зависимые пересчитываются в той же транзакции: `derive`, `computed`, `collection` и `selectByKey` бросают `ReadableError` `closed`.
|
|
880
|
+
|
|
881
|
+
<a id="d147"></a>
|
|
882
|
+
|
|
883
|
+
## D147 — документы приведены к формам после ревью
|
|
884
|
+
|
|
885
|
+
§2 показывает форму, которая компилируется (порт остаётся ref-ом в `own` и живым `Call` только у экземпляра); закон включения указывает на `optional`, закрытие экспортированного `Readable` названо фенсом.
|
|
886
|
+
|
|
887
|
+
<a id="d148"></a>
|
|
888
|
+
|
|
889
|
+
## D148 — горячие классы с `#`-полей на TS `private`
|
|
890
|
+
|
|
891
|
+
На hot paths используются TypeScript private fields; native #private оставляются на границах подлинности. При browser downlevel это избегает дополнительных WeakMap lookups; изменение проверяется workload.
|
|
892
|
+
|
|
893
|
+
<a id="d149"></a>
|
|
894
|
+
|
|
895
|
+
## D149 — латентность языковой службы информационна
|
|
896
|
+
|
|
897
|
+
`ide.diagnosticLatencyMs` печатается строкой и валит гейт только выше 2× бюджета; детерминированные бюджеты enforced по своему числу. прогоны одной фикстуры дают 182…262 мс без правок кода, и гейт переключался сам по себе.
|
|
898
|
+
|
|
899
|
+
<a id="d150"></a>
|
|
900
|
+
|
|
901
|
+
## D150 — общие хелперы объявлены один раз
|
|
902
|
+
|
|
903
|
+
хелперы-типы (`Awaitable`, `NoExtraKeys`, `ExactInput`, `ExactKeys`, `ExactVoidResult`, `IsAny`, `ExactType`) живут в `core/src/type-helpers.ts` и на internal-входе ядра; `isReadable`, `reportDetachedError`, `assertPlainRecord` существуют в одном экземпляре; `FeatureOptions` удалён, реализация `defineFeature` типизирована публичным `FeatureInput`.
|
|
904
|
+
|
|
905
|
+
<a id="d151"></a>
|
|
906
|
+
|
|
907
|
+
## D151 — smoke и size-фикстуры следуют текущему API
|
|
908
|
+
|
|
909
|
+
Pack smoke проверяет реальные опубликованные entry points, а size consumers компилируются с noEmitOnError. Ошибка type-check не должна давать green size или package gate.
|
|
910
|
+
|
|
911
|
+
<a id="d152"></a>
|
|
912
|
+
|
|
913
|
+
## D152 — гейты с доказательной силой
|
|
914
|
+
|
|
915
|
+
Гейты проверяют текущий authoring API и реальные entry points. Type-stress enforce-ит instantiations, memory, RSS и diagnostics; timings информационные. См. [D224](#d224).
|
|
916
|
+
|
|
917
|
+
<a id="d153"></a>
|
|
918
|
+
|
|
919
|
+
## D153 — примеры §2 компилируются гейтом
|
|
920
|
+
|
|
921
|
+
`generate-rfc-examples.mjs` поднимает семь блоков §2 в `fixtures/generated/rfc-section-2-*.tsx` с явными прологами и настоящими импортами между блоками; `tsconfig.docs.json` компилируется в `ci:type`, режим `--check` не даёт зафиксировать устаревшую фикстуру. Два примера исправлены: `defineApplication` с `id` и `reporter`, `derive({ from, select })` вместо позиционной формы. сверка спеки с кодом нашла два некомпилируемых примера при обещании [D147](#d147) «примеры компилируются».
|
|
922
|
+
|
|
923
|
+
<a id="d154"></a>
|
|
924
|
+
|
|
925
|
+
## D154 — `backpressure` обязателен и в типе
|
|
926
|
+
|
|
927
|
+
`ModelStreamOptions.backpressure` стал обязательным полем, как у стрима фичи; typetest на отсутствие. тип разрешал опустить то, что рантайм требовал на открытии (`feature-stream.ts`) — расхождение находил рантайм, а не компилятор.
|
|
928
|
+
|
|
929
|
+
<a id="d155"></a>
|
|
930
|
+
|
|
931
|
+
## D155 — SSR, hydration и персистентность — non-goal
|
|
932
|
+
|
|
933
|
+
Opetope не обещает server snapshot/restore состояния моделей и ресурсов. Такое расширение требует отдельного контракта сериализации и владения.
|
|
934
|
+
|
|
935
|
+
<a id="d156"></a>
|
|
936
|
+
|
|
937
|
+
## D156 — отмена на границе внешнего I/O
|
|
938
|
+
|
|
939
|
+
Адаптер I/O обязан явно передавать lifetime AbortSignal в операцию и закрывать ресурсы. Fence прекращает admission; abort не заменяет физический drain.
|
|
940
|
+
|
|
941
|
+
<a id="d157"></a>
|
|
942
|
+
|
|
943
|
+
## D157 — поверхность считается целиком, включая `.tsx`
|
|
944
|
+
|
|
945
|
+
Public-surface gate включает JSX/TSX entry points и сверяет реальные value/type exports с утверждёнными budgets. См. spec §5.
|
|
946
|
+
|
|
947
|
+
<a id="d158"></a>
|
|
948
|
+
|
|
949
|
+
## D158 — выдача моделей: гибрид плюс lint на вложенные
|
|
950
|
+
|
|
951
|
+
Owner-модели доступны всему subtree вклада; per-mount UI-модели объявляют requiresModels. Проверка типов, runtime frame и lint gate дополняют друг друга.
|
|
952
|
+
|
|
953
|
+
<a id="d159"></a>
|
|
954
|
+
|
|
955
|
+
## D159 — internal ABI сужен по факту потребления
|
|
956
|
+
|
|
957
|
+
с `@opetope/core/internal` ушли девять value-экспортов, с `@opetope/runtime/internal` — девятнадцать (в т. ч. `compileApplicationTopology`, `bindFeatureModel`, `createResourceController`, `createStreamController`); value-экспорты core 52 → 43, runtime 39 → 20 при 38 на безопасных входах; имена остались модульными, тесты пакета импортируют их из модулей; гейт печатает число internal values.
|
|
958
|
+
|
|
959
|
+
<a id="d160"></a>
|
|
960
|
+
|
|
961
|
+
## D160 — одна retention и одна backpressure-политика
|
|
962
|
+
|
|
963
|
+
фабрики `drop`, `sample`, `queue` и `observer()` удалены вместе со snapshot-хелперами, ветками `emit` и `StreamQueueOverflowError`; `StreamBackpressure` это только `latest`, `ObserverRetention` свернулась до литерала `{ kind: 'observer' }` (retention по умолчанию), admission стрима — один слот.
|
|
964
|
+
|
|
965
|
+
<a id="d161"></a>
|
|
966
|
+
|
|
967
|
+
## D161 — одна декларация формы вызова
|
|
968
|
+
|
|
969
|
+
ядро принимает авторскую форму опций вызова: `CallExecutorOptions` несёт `once` (`true` или селектор ключа) и `singleFlight` (селектор ключа); типы `CallOnceCache`/`CallSingleFlight`, их snapshot-хелперы и три транслятора между авторской, компиляторной и ядровой формами удалены.
|
|
970
|
+
|
|
971
|
+
<a id="d162"></a>
|
|
972
|
+
|
|
973
|
+
## D162 — наблюдаемая половина контроллера вызова удалена
|
|
974
|
+
|
|
975
|
+
у контроллера вызова остались `activate`, `close`, `diagnostics` и `run`; ушли `getSnapshot`/`subscribe`/`publish`, поля `snapshot`, `listeners`, `latestOrdinal`, типы `CallSnapshot`, `CallCurrentInvocation`, `CallListenerRegistration`, константа `idleSnapshot`.
|
|
976
|
+
|
|
977
|
+
<a id="d163"></a>
|
|
978
|
+
|
|
979
|
+
## D163 — вложения одного scope-а закрываются одной волной
|
|
980
|
+
|
|
981
|
+
граф зависимостей вложений (`after`) удалён: ушли компилятор канонического DAG (`attachment-graph`), план дренажа со счётчиками, волновой планировщик и стартовый worklist; из IR — `afterSlots`/`dependentSlots`, из scope-а — `providerSlots`, из поколения — `remainingProviders` и состояние `blocked`. Вложения одного scope-а стартуют и дренируются одной волной; порядок между фичами держат группы условий и рёбра.
|
|
982
|
+
|
|
983
|
+
<a id="d164"></a>
|
|
984
|
+
|
|
985
|
+
## D164 — одна форма исхода retire внутри рантайма
|
|
986
|
+
|
|
987
|
+
вариант (б): планировщик закрытия перестал быть генериком со своим словарём (`AttachmentRetirementSchedulerOutcome`, `…Failure`, `…FailureOutcome` удалены) и строит результат сразу в форме локального scope-а (`LocalScopeDrainOutcome` с `{ attachmentId, attachmentSlot, outcome }`); проекция `projectRetirementOutcome` исчезла; пара `drain`/`retry` объявлена один раз. Публичный тип исхода retire ([D125](#d125)) не тронут.
|
|
988
|
+
|
|
989
|
+
<a id="d165"></a>
|
|
990
|
+
|
|
991
|
+
## D165 — доказывать факт один раз на пути открытия
|
|
992
|
+
|
|
993
|
+
Факт подлинности и границы фиксируются при admission и повторно проверяются после пользовательского callback, если состояние могло измениться.
|
|
994
|
+
|
|
995
|
+
<a id="d166"></a>
|
|
996
|
+
|
|
997
|
+
## D166 — одна запись экземпляра вместо параллельных индексов
|
|
998
|
+
|
|
999
|
+
у живого экземпляра одна запись: `moduleBindings` (WeakMap handle → биндинги материализации) стал полем `materializationBindings` записи, `scopeInstances` и `scopeHandleStates` свернулись в один `scopeHandles` (Map blueprint → состояние с фасадом), retire очищает одну карту. Публичное поведение не менялось.
|
|
1000
|
+
|
|
1001
|
+
<a id="d167"></a>
|
|
1002
|
+
|
|
1003
|
+
## D167 — порт наблюдения видит смену видимости и фенс владельца
|
|
1004
|
+
|
|
1005
|
+
Inspection отражает опубликованную видимость contribution и fence владельца. Подключённая сессия наблюдает необходимые targets и снимает подписки при close; выключенное наблюдение не выполняет эту работу.
|
|
1006
|
+
|
|
1007
|
+
<a id="d168"></a>
|
|
1008
|
+
|
|
1009
|
+
## D168 — один авторский словарь закрытия, фильтра и требования
|
|
1010
|
+
|
|
1011
|
+
публичный `FeatureInstance` закрывается через `close()`, предикат `effect` называется `when(current, previous)`, обязательный порт задаётся непосредственно `requires: { name: Port }`, а удержание — `scoped({ capacity })` с фиксированным LRU. `FeatureError.retryCleanup?: () => Promise<void>` доступен только для повторяемого карантинного фронтира: перед вызовом проверяется capability; у других ошибок её нет. Старые `retire()`, `effect.condition`, `required(port)`, опция `evict` и `FeatureError.retry` удалены без постоянных алиасов.
|
|
1012
|
+
|
|
1013
|
+
<a id="d169"></a>
|
|
1014
|
+
|
|
1015
|
+
## D169 — модель получает запись готовых зависимостей и может предоставлять порт
|
|
1016
|
+
|
|
1017
|
+
без зависимостей остаётся `model(Decl, create)`; с одной или несколькими используется `model(Decl, { platform: imports.platform, lookup: requires.lookup }, create)`. Фабрика получает readonly-запись разрешённых значений с выведенными типами и объявляет свой интерфейс зависимостей. позиционный единственный импорт заставлял прятать несколько зависимостей в host-контракт или вручную замыкать refs.
|
|
1018
|
+
|
|
1019
|
+
<a id="d170"></a>
|
|
1020
|
+
|
|
1021
|
+
## D170 — отмена не заменяет дренаж, частичная модель уже имеет владельца
|
|
1022
|
+
|
|
1023
|
+
логическая отмена завершает ожидание вызывающего, а физический дренаж отдельно ждёт допущенную работу, включая незавершённое открытие и активный `consume` стрима, до освобождения источника. Участник отката модели регистрируется до вызова фабрики и убирает частично созданные узлы как в feature `own`, так и в UI-монтировании.
|
|
1024
|
+
|
|
1025
|
+
<a id="d171"></a>
|
|
1026
|
+
|
|
1027
|
+
## D171 — devtools ограничивает историю и читает текущий экземпляр
|
|
1028
|
+
|
|
1029
|
+
drain devtools продолжается по продвижению курсора, а не по числу кадров в byte-limited пакете; после восьми pull управление возвращается планировщику. Ошибка первого snapshot сообщает `snapshot-failed`, закрывает сессию и сохраняет исходную причину; поздние ошибки освобождают подписку и сессию идемпотентно.
|
|
1030
|
+
|
|
1031
|
+
<a id="d172"></a>
|
|
1032
|
+
|
|
1033
|
+
## D172 — измерять аллокации отдельно от живой памяти и проверять настоящее ребро
|
|
1034
|
+
|
|
1035
|
+
schema 8 perf-гейта считает `estimatedAllocatedBytesPerOperation` через V8 HeapProfiler Poisson sampling с интервалом 16 384 байта и сохранением samples объектов, собранных minor/major GC. Итог — медиана трёх проходов с измерительной обвязкой, без external backing stores; ноль samples проверяется 95%-ной верхней границей, а не выдаётся за отсутствие аллокаций. прежняя разность post-GC heap не измеряла объекты, уже собранные в ходе нагрузки, а счётчики async hooks не были V8 allocations.
|
|
1036
|
+
|
|
1037
|
+
<a id="d173"></a>
|
|
1038
|
+
|
|
1039
|
+
## D173 — абсолютный setter сохраняет последнее ожидающее значение
|
|
1040
|
+
|
|
1041
|
+
`useCommand(call, { pending: 'latest' })` допускает один переданный запрос и один самый свежий ожидающий. У каждого свои promise исхода, callbacks и signal; вытесненное или отменённое ожидание завершается `cancelled` без уведомления успеха/ошибки.
|
|
1042
|
+
|
|
1043
|
+
<a id="d174"></a>
|
|
1044
|
+
|
|
1045
|
+
## D174 — объектный выбор команд в UI
|
|
1046
|
+
|
|
1047
|
+
выбранный владельцем `useCommands({ save: model.save, remove: other.remove }, options?)` возвращает прежний `CommandHook` для каждого локального имени, с точными типами аргумента и результата. Команды могут быть из разных разрешённых моделей.
|
|
1048
|
+
|
|
1049
|
+
<a id="d175"></a>
|
|
1050
|
+
|
|
1051
|
+
## D175 — две вкладки и фильтр рёбер вместо пяти линз
|
|
1052
|
+
|
|
1053
|
+
панель devtools имеет две вкладки, `Graph` и `Timeline`. Всё, что раньше было отдельной линзой, стало фильтром внутри `Graph`: один чип на вид ребра протокола плюс четыре пресета — «Импорты и порты», «Условия», «Владение», «Точки расширения». пять линз были пятью ответами на один вопрос — какие связи я сейчас смотрю, — и разработчик, которому нужны две сразу, был обязан выбрать одну.
|
|
1054
|
+
|
|
1055
|
+
<a id="d176"></a>
|
|
1056
|
+
|
|
1057
|
+
## D176 — управление ограничено override условия
|
|
1058
|
+
|
|
1059
|
+
порт записи `createControlSession(execution)` живёт на `@opetope/runtime/internal` рядом с портом наблюдения, но отдельной фабрикой и над собственным реестром: держать inspection-сессию не значит иметь право писать. Единственный управляемый субъект — условие и через него его группа. `suspend(conditionId)` ставит debug-override, принудительно читающий условие как `false`; `resume(conditionId)` его снимает, и группа снова следует источнику, но `ready` не обещает; `retryCleanup(instanceId)` повторяет уборку ровно карантинного фронтира существующим retry-контрактом; `close()` снимает все override сессии. прямая запись в узел графа обошла бы планировщик, жёсткие зависимости, вклады и карантин, а «enable» ещё и двусмыслен.
|
|
1060
|
+
|
|
1061
|
+
<a id="d177"></a>
|
|
1062
|
+
|
|
1063
|
+
## D177 — типизированные render-колбэки `FeatureBoundary`
|
|
1064
|
+
|
|
1065
|
+
FeatureBoundary принимает типизированные ready/error render callbacks. Boundary удерживает feature и отражает её состояние; права моделей и команд продолжает задавать contribution frame. См. [D197](#d197), [D198](#d198), [D226](#d226).
|
|
1066
|
+
|
|
1067
|
+
<a id="d178"></a>
|
|
1068
|
+
|
|
1069
|
+
## D178 — удержание терминального `Readable`
|
|
1070
|
+
|
|
1071
|
+
Открытый вопрос: удержанный caller-ом терминальный derived Readable может сохранять последний payload. Это не обещание автоматической очистки пользовательского snapshot после close; изменение требует отдельного контракта.
|
|
1072
|
+
|
|
1073
|
+
<a id="d179"></a>
|
|
1074
|
+
|
|
1075
|
+
## D179 — измерения приложения и библиотечные workloads
|
|
1076
|
+
|
|
1077
|
+
Производительность проверяется на репрезентативном приложении отдельно от microbenchmarks: startup, interaction latency и retained heap нельзя выводить из одних queue/allocation workload. Измеренные бюджеты относятся к конкретному workload и среде.
|
|
1078
|
+
|
|
1079
|
+
<a id="d182"></a>
|
|
1080
|
+
|
|
1081
|
+
## D182 — политика cleanup у приложения
|
|
1082
|
+
|
|
1083
|
+
`openApplication(app, { cleanupFailure })` принимает тот же публичный `CleanupFailurePolicy`, что и `openFeature`, со значением по умолчанию `report`. Политика протягивается контекстом приложения в каждое открытие экземпляра, поэтому `quarantine` включается один раз на весь граф, а не по фиче. без этой опции экземпляры приложения всегда открывались с `report`, поэтому карантинного `FeatureError` в приложении не возникало вовсе и `retryCleanup` порта управления ([D176](#d176)) не имел достижимого положительного пути.
|
|
1084
|
+
|
|
1085
|
+
<a id="d183"></a>
|
|
1086
|
+
|
|
1087
|
+
## D183 — lossless-доставка дельт внешнего источника
|
|
1088
|
+
|
|
1089
|
+
Открытый вопрос: lossless-доставка требует ограниченной очереди и явной overflow policy. Stream хранит актуальную selection; event по умолчанию отбрасывает новый emit при занятых running/pending, а backpressure: latest() заменяет pending. См. [D160](#d160), [D247](#d247).
|
|
1090
|
+
|
|
1091
|
+
<a id="d184"></a>
|
|
1092
|
+
|
|
1093
|
+
## D184 — условие вычисляется из экспорта фичи
|
|
1094
|
+
|
|
1095
|
+
Условие может вычисляться из экспорта provider feature. Ребро provider участвует в планировании; неизвестный или неготовый provider не заменяется предположением.
|
|
1096
|
+
|
|
1097
|
+
<a id="d185"></a>
|
|
1098
|
+
|
|
1099
|
+
## D185 — политика Call задаётся при создании в модели
|
|
1100
|
+
|
|
1101
|
+
Политика latest принадлежит декларации Call; useCommand/useCommands не имеют отдельной очереди. См. [D203](#d203), [D243](#d243).
|
|
1102
|
+
|
|
1103
|
+
<a id="d186"></a>
|
|
1104
|
+
|
|
1105
|
+
## D186 — лёгкое объявление фичи и динамическая загрузка body
|
|
1106
|
+
|
|
1107
|
+
Лёгкий header объявляет границу фичи, body: () => import(...) загружает реализацию. defineFeature.body проверяет соответствие header; preload загружает код без открытия. См. [D207](#d207), [D208](#d208), [D211](#d211).
|
|
1108
|
+
|
|
1109
|
+
<a id="d187"></a>
|
|
1110
|
+
|
|
1111
|
+
## D187 — сахар слабого ребра
|
|
1112
|
+
|
|
1113
|
+
у двух половин слабого ребра появляется по одному слову. `calls(imports.x, keys)` работает и поверх `optional(feature)`: выбранные ключи это экспортированные `Call` провайдера, вызов читает провайдера в момент обращения, проксирует его экспортированный вызов и потому едет вместе с фенсом провайдера, а пока провайдера нет (или он не экспортирует такой вызов) отвечает `CallError` с кодом `unavailable` — ровно как слабый порт ([D105](#d105), [D138](#d138)). `fromOptional(source, select, { missing })` в `@opetope/core` читает данные: `select` выполняется только на `found` и вправе вернуть значение или собственный `Readable` провайдера, вложенный readable читается с отслеживанием зависимости, поэтому отслеживается только пока провайдер есть, а в состоянии `missing` ответом служит заданное значение. Публичная поверхность растёт на одно значение: 38 → 39 при цели 40, причина записана в комментарии гейта. каждый потребитель слабого ребра писал одно и то же: разворачивал `lookup.kind` в `derive`, руками доставал `Call` из `lookup.value` и сам придумывал, что делать, когда провайдера нет.
|
|
1114
|
+
|
|
1115
|
+
<a id="d188"></a>
|
|
1116
|
+
|
|
1117
|
+
## D188 — модели монтирования создаются в коммите, а не в рендере
|
|
1118
|
+
|
|
1119
|
+
`ContributionMount` ничего не создаёт в рендере. Состояние монтирования это `bundle | undefined`: первый проход рендерит `null` без `MountProvider`, `useLayoutEffect` с ключом по идентичности вклада (и фикстур) собирает bundle через `createMountBundle` из закоммитившихся `slotProps` и публикует его через `setBundle` — React сбрасывает этот дополнительный синхронный рендер до paint, — а cleanup того же эффекта его закрывает.
|
|
1120
|
+
|
|
1121
|
+
<a id="d189"></a>
|
|
1122
|
+
|
|
1123
|
+
## D189 — закрытие приложения фенсит admission синхронно
|
|
1124
|
+
|
|
1125
|
+
`close()` приложения синхронно фенсит все живые экземпляры: в том же turn, до первого `await`, каждое живое поколение перестаёт допускать работу (`retirementRequested` плюс `instance.retire()` без дренажа), и только после этого начинается прежний упорядоченный физический дренаж consumer-before-provider. То же делает `close()` группы условий для своих активных участников.
|
|
1126
|
+
|
|
1127
|
+
<a id="d190"></a>
|
|
1128
|
+
|
|
1129
|
+
## D190 — условие это желаемое состояние, а не событие
|
|
1130
|
+
|
|
1131
|
+
рантайм следует последнему снапшоту условия, поэтому краткое `false` с возвратом в `true` внутри одного turn коалесцируется: живое поколение сохраняется, повторного открытия нет. Конец сессии выражается фактом в самом условии (например её id), а не мгновенным `false`. обратное означало бы, что условие несёт события, а не состояние: любой дребезг источника ронял бы и поднимал экземпляры, а потребители получали бы разрыв там, где хост ничего не менял.
|
|
1132
|
+
|
|
1133
|
+
<a id="d191"></a>
|
|
1134
|
+
|
|
1135
|
+
## D191 — ровно одна живая control-сессия на execution
|
|
1136
|
+
|
|
1137
|
+
у одного `ApplicationExecution` одновременно живёт не больше одной сессии управления. Второй `createControlSession(execution)` при живой сессии бросает `TypeError('Application already has a control session.')`; `close()` освобождает слот, поэтому после перезагрузки панели или HMR новую сессию открыть можно.
|
|
1138
|
+
|
|
1139
|
+
<a id="d192"></a>
|
|
1140
|
+
|
|
1141
|
+
## D192 — отказ connect не отменяет уже допущенную работу
|
|
1142
|
+
|
|
1143
|
+
оба пути отказа `connect` у стрима — терминальный и тот, что уходит в повтор — закрывают admission и сохраняют его дренаж: promise ожидания активного `consume` попадает в набор дренажа контроллера, поэтому `close()` ждёт его, а импортированный источник освобождается только после последнего `consume`. Следующая попытка повтора стартует после того, как этот дренаж осел, поэтому преемник не перекрывает потребителя предшественника.
|
|
1144
|
+
|
|
1145
|
+
<a id="d193"></a>
|
|
1146
|
+
|
|
1147
|
+
## D193 — один id называет одно условие
|
|
1148
|
+
|
|
1149
|
+
`defineApplication` отказывает, если в `when` включённых фич встречаются два разных authentic `Condition` с одним id — например host-bound и derived: «Condition <id> is declared twice: one id names one condition, not two». Один и тот же объект, использованный несколькими фичами, остаётся законным: это и есть множество условий одной группы.
|
|
1150
|
+
|
|
1151
|
+
<a id="d194"></a>
|
|
1152
|
+
|
|
1153
|
+
## D194 — публикация `ready` может закрыть стрим, и потребитель тогда не стартует
|
|
1154
|
+
|
|
1155
|
+
`consume` стрима перепроверяет актуальность исполнения после публикации `ready` и не запускается, если подписчик этой самой публикации успел фенсить, закрыть или сменить target/key. Уже начатая работа по-прежнему дренируется: отменяется допуск, а не то, что исполняется.
|
|
1156
|
+
|
|
1157
|
+
<a id="d195"></a>
|
|
1158
|
+
|
|
1159
|
+
## D195 — подписка на target, вернувшаяся после закрытия, освобождается сразу
|
|
1160
|
+
|
|
1161
|
+
`activate` контроллеров ресурса и стрима запоминает номер своей активации, и после возврата `target.subscribe` проверяет, та ли это активация: если владелец успел закрыться, дефенситься или деактивироваться внутри самого `subscribe`, возвращённый disposer освобождается ровно один раз на месте и никуда не записывается; ошибка освобождения уходит репортеру. Живой контроллер по-прежнему хранит disposer и читает target.
|
|
1162
|
+
|
|
1163
|
+
<a id="d196"></a>
|
|
1164
|
+
|
|
1165
|
+
## D196 — видимость фиксируется в коммите публикации, и отказ откатывает подписки
|
|
1166
|
+
|
|
1167
|
+
публикация вклада вычисляет видимость не на этапе подготовки, а в `commit()` — уже после подписки на `when`, внутри той же транзакции; поэтому источник, перевернувший значение прямо в `subscribe`, виден сразу и вклад публикуется в правильной видимости. Публикация на несколько targets остаётся одной транзакцией: каждый hub возвращает откат ровно того, что подписал сам, и если следующий hub отказал, предыдущие откатываются в обратном порядке, а ошибка отката уходит репортеру.
|
|
1168
|
+
|
|
1169
|
+
<a id="d197"></a>
|
|
1170
|
+
|
|
1171
|
+
## D197 — один Call это одна команда монтирования, сколько бы полей его ни называли
|
|
1172
|
+
|
|
1173
|
+
frame монтирования создаёт одну command-запись на различимый authentic Call. Два поля одной модели, называющие один и тот же `ctx.call`, это алиасы: они делят контроллер, активацию и фенс, а не образуют дубликат.
|
|
1174
|
+
|
|
1175
|
+
<a id="d198"></a>
|
|
1176
|
+
|
|
1177
|
+
## D198 — retry прячет ошибку на время попытки, а не до смены объекта ошибки
|
|
1178
|
+
|
|
1179
|
+
`useFeature(...).retry` возвращает `Promise<void>`, который разрешается по завершении начатой попытки, успехом или отказом; второй вызов при живой попытке присоединяется к ней, а не начинает новую (single-flight по источнику сохраняется). `FeatureBoundary` подавляет `error` на время жизни попытки и снимает подавление по её завершении, поэтому дальше показывается то, что говорит состояние. `retry`, который получает поддерево ошибки через `useFeatureRetry`, остаётся `() => void`.
|
|
1180
|
+
|
|
1181
|
+
<a id="d199"></a>
|
|
1182
|
+
|
|
1183
|
+
## D199 — структурный контракт читается через свой объект
|
|
1184
|
+
|
|
1185
|
+
хуки React зовут методы `Readable`, `Resource` и источника спроса через объект, который им передали (`() => resource.getSnapshot()`), а не отдают ссылку на метод в `useSyncExternalStore`. Геттер стабилен по идентичности источника, поэтому замена источника перечитывает снимок, а StrictMode и баланс retain/release не меняются.
|
|
1186
|
+
|
|
1187
|
+
<a id="d200"></a>
|
|
1188
|
+
|
|
1189
|
+
## D200 — диагностический id обратим, а не сведён к допустимым символам
|
|
1190
|
+
|
|
1191
|
+
проекция плана наблюдения экранирует каждую часть id через `_` (`_c` для `:`, `_s` для `/`, `_p` для `|`, `__` для самого `_`, `_u<hex>_` для всего прочего) и только потом собирает узловые и рёберные id через `:`. Экранирование обратимо, поэтому различные части остаются различными, а составной id разбирается однозначно: концы ребра экранируются повторно перед склейкой.
|
|
1192
|
+
|
|
1193
|
+
<a id="d201"></a>
|
|
1194
|
+
|
|
1195
|
+
## D201 — закрытие терминально и для апдейтера, который его вызвал
|
|
1196
|
+
|
|
1197
|
+
`State.update` перепроверяет открытость после возврата пользовательского апдейтера: если апдейтер закрыл состояние по ходу вычисления, его результат отвергается `ReadableError` с кодом `closed`, а состояние остаётся закрытым. Проверка до вызова остаётся на месте.
|
|
1198
|
+
|
|
1199
|
+
<a id="d202"></a>
|
|
1200
|
+
|
|
1201
|
+
## D202 — один Call в двух моделях одного монтирования
|
|
1202
|
+
|
|
1203
|
+
Открытый вопрос: один Call может иметь несколько имён внутри одной модели, но не может быть назначен двум моделям одного mount. Расширение требует единого владельца UI ingress и согласованного identity-контракта. См. [D197](#d197).
|
|
1204
|
+
|
|
1205
|
+
<a id="d203"></a>
|
|
1206
|
+
|
|
1207
|
+
## D203 — у потребителя команды нет своей политики
|
|
1208
|
+
|
|
1209
|
+
`useCommand(call)` и `useCommands({ alias: call })` больше не принимают опцию `pending`. Каждый `run` доходит до вызова, и решает политика, с которой вызов создан (`queue`, `latest`, `parallel`, `once`, `singleFlight`).
|
|
1210
|
+
|
|
1211
|
+
<a id="d204"></a>
|
|
1212
|
+
|
|
1213
|
+
## D204 — один источник и условия с разным смыслом
|
|
1214
|
+
|
|
1215
|
+
Один Readable может участвовать в нескольких conditions, но каждое условие сохраняет собственную identity и смысл. Группировка не объединяет разные conditions только по ссылке источника.
|
|
1216
|
+
|
|
1217
|
+
<a id="d205"></a>
|
|
1218
|
+
|
|
1219
|
+
## D205 — единый выбор данных и команд через useModel
|
|
1220
|
+
|
|
1221
|
+
useModel выбирает Readable/Call поля одной записью. Snapshot стабилен, inline selector выполняется на каждом render; чтение явно оформлено read. useCommand/useCommands остаются самостоятельными consumers. См. [D214](#d214), [D217](#d217).
|
|
1222
|
+
|
|
1223
|
+
<a id="d206"></a>
|
|
1224
|
+
|
|
1225
|
+
## D206 — объяснения причин в devtools и сценарные тесты
|
|
1226
|
+
|
|
1227
|
+
createScenario использует настоящий application/Slot/command ingress и ограниченный observation protocol. Диагностика объясняет наблюдаемые blockers и causal chain; неизвестные ownership facts остаются unknown, counters не доказывают отсутствие всех GC утечек. См. [D215](#d215), [D216](#d216).
|
|
1228
|
+
|
|
1229
|
+
<a id="d207"></a>
|
|
1230
|
+
|
|
1231
|
+
## D207 — заголовок и тело фичи, и загрузка тела при открытии
|
|
1232
|
+
|
|
1233
|
+
`defineFeature` принимает вторую форму — заголовок: `id`, `imports`, `requires`, `when`, `provides` как метаданные (цель каждого вклада с его приоритетом и порт каждого провайдера) и `body: () => import(...)`. Заголовок ни во что не разворачивается: он регистрирует identity, рёбра и объявленную границу, поэтому `defineApplication` компилирует полный граф, циклы и совместимость времени жизни до загрузки тяжёлого кода. consumers и приложение обязаны импортировать identity фичи, а её модели, компоненты и прикладные зависимости — нет.
|
|
1234
|
+
|
|
1235
|
+
<a id="d208"></a>
|
|
1236
|
+
|
|
1237
|
+
## D208 — прогрев кода заголовка без открытия
|
|
1238
|
+
|
|
1239
|
+
`defineFeature.preload(feature)` загружает тело заголовка, ничего не открывая: экземпляра не появляется, удержания и lease не берутся, состояние фичи не меняется, вклады не публикуются. Возвращается промис завершения загрузки; отказ наблюдает вызывающий, и он не кэшируется — следующее открытие снова обращается к loader, как и без прогрева. хост часто знает о будущей нужде раньше графа: наведение на пункт меню, idle-колбэк, предварительная навигация.
|
|
1240
|
+
|
|
1241
|
+
<a id="d209"></a>
|
|
1242
|
+
|
|
1243
|
+
## D209 — скрытие вклада Suspense не уничтожает его владельца
|
|
1244
|
+
|
|
1245
|
+
UI-модели вклада по-прежнему создаются только в commit ([D188](#d188)). Временное скрытие под внешним Suspense сохраняет тот же committed bundle; reveal повторно использует его без сброса React state и пересоздания моделей. layout cleanup вызывается React и при временном hiding.
|
|
1246
|
+
|
|
1247
|
+
<a id="d210"></a>
|
|
1248
|
+
|
|
1249
|
+
## D210 — установка conditions учитывает закрытие внутри чужого callback
|
|
1250
|
+
|
|
1251
|
+
application резервирует shared close Promise до вызова внешних cleanup/fence callbacks. Установка condition source после возврата из subscribe проверяет closing: поздний disposer немедленно освобождается и его ошибка входит в тот же drain; следующая группа не создаётся. subscribe — чужой синхронный код и может закрыть своего владельца до возвращения disposer.
|
|
1252
|
+
|
|
1253
|
+
<a id="d211"></a>
|
|
1254
|
+
|
|
1255
|
+
## D211 — lazy opening соблюдает контракт экземпляра независимо от общей загрузки кода
|
|
1256
|
+
|
|
1257
|
+
обе формы openFeature синхронно проверяют и копируют карту imports, requirements и base options. У lazy instance close немедленно ставит fence уже существующего materialization и возвращает общий Promise закрытия; pending ready получает retired. code fetch принадлежит определению фичи, а bindings и ресурсы — отдельной попытке открытия.
|
|
1258
|
+
|
|
1259
|
+
<a id="d212"></a>
|
|
1260
|
+
|
|
1261
|
+
## D212 — decoder принимает весь числовой домен runtime priority
|
|
1262
|
+
|
|
1263
|
+
contribution priority в inspection принимает любое конечное число, включая отрицательные и дробные значения, как runtime declaration. Sequence, revision и counts остаются неотрицательными safe integers. общий reader счётчика сужал допустимый домен priority, поэтому корректный runtime snapshot не проходил собственный JSON round-trip.
|
|
1264
|
+
|
|
1265
|
+
<a id="d213"></a>
|
|
1266
|
+
|
|
1267
|
+
## D213 — масштаб компиляции графа проверяется отдельно от повторных открытий
|
|
1268
|
+
|
|
1269
|
+
compiler один раз распределяет imports/requirements по consumer, строит порядок групп проходом по canonical order и использует min-heap для доступных вершин вместо полной сортировки после каждого добавления. Обход hard-import closure использует индекс очереди. workload тысячи open/close одного маленького приложения не измеряет compile cost большого графа.
|
|
1270
|
+
|
|
1271
|
+
<a id="d214"></a>
|
|
1272
|
+
|
|
1273
|
+
## D214 — исполнение D205 сохраняет явное чтение и существующие command consumers
|
|
1274
|
+
|
|
1275
|
+
overload `useModel(Declaration, (model, { read }) => record)` выводит readonly типы выбранных полей, authentic Calls переводит в CommandHook через существующий CommandGroup. Данные сравниваются по полям через Object.is; read deduplicates подписку на каждый Readable, не удерживает Resource.
|
|
1276
|
+
|
|
1277
|
+
<a id="d215"></a>
|
|
1278
|
+
|
|
1279
|
+
## D215 — исполнение D206 использует один ограниченный observation protocol
|
|
1280
|
+
|
|
1281
|
+
graph/frame получают revision /3; optional activity имеет собственную schema /1 и ограничивает суммарное число features, Calls, registered resources и nested loads. Записи содержат execution identity, фактическое поколение владельца, lane blocker и physical drain; host demand, UI models и физические stream loads остаются unknown. сообщения ожиданий должны опираться на наблюдаемые identities, а не на догадки или второй runtime.
|
|
1282
|
+
|
|
1283
|
+
<a id="d216"></a>
|
|
1284
|
+
|
|
1285
|
+
## D216 — отсутствие activity в delta-frame сохраняет предыдущее наблюдение
|
|
1286
|
+
|
|
1287
|
+
внутри одной inspection session поле `frame.activity` заменяет activity целиком, а отсутствие поля означает отсутствие изменений. Полный snapshot/reset без activity очищает прежнее наблюдение. producer публикует activity лишь при изменении.
|
|
1288
|
+
|
|
1289
|
+
<a id="d217"></a>
|
|
1290
|
+
|
|
1291
|
+
## D217 — selection принимает интерфейсы, scenario сохраняет props-контракт Slot
|
|
1292
|
+
|
|
1293
|
+
тип результата `useModel` описывает конкретные ключи записи и допускает именованный interface без открытого index signature; readonly, optional и symbol-поля сохраняются. Top-level массивы, callable/constructable и встроенные non-record объекты не становятся выборкой. `scenario.mount` требует `options.props` для target с props и не принимает props у target без них, как обычный `Slot`. вынесенный selector должен иметь ту же допустимость, что эквивалентный литерал.
|
|
1294
|
+
|
|
1295
|
+
<a id="d218"></a>
|
|
1296
|
+
|
|
1297
|
+
## D218 — повторный вход не отменяет fence и атомарность admission
|
|
1298
|
+
|
|
1299
|
+
закрытие приложения синхронно фенсит готовых участников ещё открывающейся condition group; возвращённый после повторного входа member тоже получает fence, а cleanup сохраняет обратный порядок зависимостей. Resource резервирует актуальность операции до abort и проверяет её после внешних callbacks; устаревшая операция не публикует данные и не забирает disposer нового activation. `latest` резервирует нового waiter и его место до уведомления об отмене вытесненного, сохраняя барьеры других Calls и workspace outcome при reentrant close/retire. abort, чтение внешнего источника и уведомление подписчика могут синхронно запустить новую операцию или закрыть владельца.
|
|
1300
|
+
|
|
1301
|
+
<a id="d219"></a>
|
|
1302
|
+
|
|
1303
|
+
## D219 — новая selection потока сохраняется после возврата старого callback
|
|
1304
|
+
|
|
1305
|
+
Stream проверяет актуальность чтения target после внешнего getter и key callback; вложенное чтение или завершение текущего lifetime отменяет право прежнего чтения менять selection. Равный request key не делает старый target актуальным: refresh использует последний принятый target. `key(old)` может синхронно обновить источник до `new`, после чего прежний callback возвращает `old`.
|
|
1306
|
+
|
|
1307
|
+
<a id="d220"></a>
|
|
1308
|
+
|
|
1309
|
+
## D220 — видимость вклада объявляется предикатом экземпляра
|
|
1310
|
+
|
|
1311
|
+
`when` у вклада принимает `Readable<boolean>` либо предикат экземпляра `({ exports, imports, own, read }) => boolean`. Форма выбрана тем, что написал автор: функция это предикат, объект это readable; рантайм не вызывает предикат, чтобы его классифицировать, и не зовёт дважды. автор объявляет факт видимости, а не источник факта.
|
|
1312
|
+
|
|
1313
|
+
<a id="d221"></a>
|
|
1314
|
+
|
|
1315
|
+
## D221 — бюджеты размера и проверки типов растут вместе с реактивным authoring
|
|
1316
|
+
|
|
1317
|
+
cap `public feature consumer` в `@opetope/runtime` поднимается с 31 до 32 kb на всю серию authoring API, а бюджет `01.tscInstantiations` в type-stress — с 9000 до 10000, с перезаписью baseline. Диета сделана до подъёма: понижение предиката хранится одним замыканием на объявление, без объекта-дискриминанта и без второго обхода описаний; отложенная форма проверки опций (условный тип по `Options`) отвергнута, потому что контекстная типизация предиката и такое условие зависят друг от друга.
|
|
1318
|
+
|
|
1319
|
+
<a id="d222"></a>
|
|
1320
|
+
|
|
1321
|
+
## D222 — реактивное чтение называется `read` во всех контекстах
|
|
1322
|
+
|
|
1323
|
+
третий аргумент обработчика `pipe` это `{ read }`, а не `{ get }`; `fold(value, meta, read?)` принимает того же читателя третьим параметром. Публичное breaking-переименование: `getSnapshot`, `subscribe`, `ComputedOptions.read` и прочие методы `get` не трогаются, второй перегрузки не заводится. одно и то же действие — прочитать источник и записать зависимость — теперь встречается в предикате видимости, в обработчике `pipe` и в `useModel`.
|
|
1324
|
+
|
|
1325
|
+
<a id="d223"></a>
|
|
1326
|
+
|
|
1327
|
+
## D223 — обработчик pipe объявляется дескриптором `{ fold }`
|
|
1328
|
+
|
|
1329
|
+
второй аргумент `pipe` это дескриптор `{ fold: (value, meta, context) => next }`, а не фабрика, возвращающая обработчик. `fold` получает тот же контекст вычисления экземпляра, что и предикат `when` ([D220](#d220)): `exports`, `imports`, материализованный `own` и `read`. Дескриптор проверяется по exact-правилам plain record: голая функция, лишний ключ и не-функция в `fold` это ошибка объявления, а не поведение по умолчанию. прежняя фабрика существовала лишь потому, что обработчик — функция, и её нечем было отличить от фабрики экземпляра; автор писал `() =>` без содержания и получал два уровня вложенности там, где объявлял одну свёртку.
|
|
1330
|
+
|
|
1331
|
+
<a id="d224"></a>
|
|
1332
|
+
|
|
1333
|
+
## D224 — миллисекунда не является свойством кода
|
|
1334
|
+
|
|
1335
|
+
в `ci:type-stress` все миллисекундные числа становятся информационными: `tscCheckMs`, `tscTotalMs`, `ideColdCompletionMs`, `ideDiagnosticMs`, `ideWarmCompletionP95Ms`, `ideQuickInfoP95Ms`, а также оба временных ratchet — время проверки против удвоенного baseline и 40 секций против `max(2.75 ×` 20 секций`, 1 000 мс)`. Каждое печатается строкой `actual of reference` и ничего не останавливает; двукратный hard stop у `ideDiagnosticMs` ([D149](#d149)) снят вместе с остальными.
|
|
1336
|
+
|
|
1337
|
+
<a id="d225"></a>
|
|
1338
|
+
|
|
1339
|
+
## D225 — публикация читает только свои `when` и отпускает наблюдателей после коммита
|
|
1340
|
+
|
|
1341
|
+
транзакция публикации держит весь чужой код вне записей. Подписка на `when` и его чтение идут до того, как хоть одна цель тронула `entries`; освобождение наблюдателя ушедшей записи (`unwatch` — disposer чужого `subscribe`) идёт после того, как зафиксированы entries, snapshot и статус всех целей, поэтому снятие публикации, сделанное из такого disposer, работает поверх зафиксированного состояния, а не отменяется последующим коммитом. «единственный шаг, исполняющий чужой код» было неправдой в трёх местах сразу, и каждое давало наблюдаемый дефект: disposer первой цели воскрешал вклад, снятый им же у соседа; чтение чужого предиката, ушедшего в ошибку, блокировало обязательную уборку закрывающегося владельца; а проекция, снятая до чужого getter, коммитила видимость, которой уже не было.
|
|
1342
|
+
|
|
1343
|
+
<a id="d226"></a>
|
|
1344
|
+
|
|
1345
|
+
## D226 — отказ acquisition это завершившаяся попытка, а не исключение вызывающего
|
|
1346
|
+
|
|
1347
|
+
`useFeature(...).retry` не бросает синхронно. Если `acquire()` источника отказывает броском, попытка считается завершившейся: резервирование освобождается, а `retry` отдаёт тот же зарезервированный промис, который уже разрешён. [D198](#d198) обещает, что `retry` отвечает промисом завершения попытки независимо от исхода, а граница прячет ошибку только на время попытки.
|
|
1348
|
+
|
|
1349
|
+
<a id="d227"></a>
|
|
1350
|
+
|
|
1351
|
+
## D227 — правила письма поставляются вместе с библиотекой
|
|
1352
|
+
|
|
1353
|
+
проверяемая часть правил письма на Opetope живёт в самой библиотеке, отдельным пакетом `@opetope/lint`. Это ESLint-плагин без зависимости на `@opetope/core`, `@opetope/runtime` и `@opetope/react`, без чтения типов и без знания о конкретном приложении. законы §2 и §3 сейчас проверяет только чтение чужого кода, и автор узнаёт о нарушении тогда, когда его уже нужно объяснять словами.
|
|
1354
|
+
|
|
1355
|
+
<a id="d240"></a>
|
|
1356
|
+
|
|
1357
|
+
## D240 — размер и корректность диагностического протокола
|
|
1358
|
+
|
|
1359
|
+
Size budgets фиксируются в конфигурации пакетов и проверяются на реальных consumers. Decoder принимает весь объявленный протокол: bucket/kind, numeric domains и limits ID должны совпадать с producer. См. [D200](#d200).
|
|
1360
|
+
|
|
1361
|
+
<a id="d241"></a>
|
|
1362
|
+
|
|
1363
|
+
## D241 — панель платит за собственные отказы
|
|
1364
|
+
|
|
1365
|
+
cap панели поднимается с 20 до 21 kb. Поднятие покрывает обработку отказов, которой у панели не было: копирование диагностического id сообщает исход вместо потерянного rejection, ленивая поверхность (легенда, control, хронология, выгрузка) имеет состояния pending/loaded/failed с локальным повтором, а незавершённая загрузка кэшируется как один запрос. промах загрузки чанка и отказ clipboard — это то, что панель обязана показать своему читателю, а не то, о чём он узнаёт из консоли хоста.
|
|
1366
|
+
|
|
1367
|
+
<a id="d242"></a>
|
|
1368
|
+
|
|
1369
|
+
## D242 — пересчёт и наблюдение сохраняют точные границы состояния
|
|
1370
|
+
|
|
1371
|
+
пересчёт видимости проверяет состав entries и ревизию после каждого getter; устаревшая проекция отбрасывается до следующего чтения и публикации. Повторный вход из getter или listener ограничен 100 перезапусками с освобождением guard после ошибки. проверка перед пользовательским callback не гарантирует актуальность после его возврата.
|
|
1372
|
+
|
|
1373
|
+
<a id="d243"></a>
|
|
1374
|
+
|
|
1375
|
+
## D243 — команда объявляется через call, исполняется через invoke
|
|
1376
|
+
|
|
1377
|
+
существующее поле `call(target, input)` во всех контекстах исполнения переименовано в `invoke(target, input)` без совместимого алиаса. Это `ModelCallContext`, `FeatureCallContext`, `AttachmentExecutionContext` и `ModuleAttachmentExecutionContext`, включая контекст исполнения, который получает `step`.
|
|
1378
|
+
|
|
1379
|
+
<a id="d244"></a>
|
|
1380
|
+
|
|
1381
|
+
## D244 — обычные методы не требуют фиктивного signal, отмена остаётся явной
|
|
1382
|
+
|
|
1383
|
+
`calls` в модели и фиче принимает обычные методы форм `() => Output`, `(input) => Output` и `(input, signal: AbortSignal) => Output`, включая безопасные необязательные параметры. Метод без аргументов даёт `Call<void, Awaited<Output>>`; единственный параметр всегда input, второй — только точный `AbortSignal` или `AbortSignal | undefined`. простому setter или синхронному преобразованию нечего отменять, а требование `_signal` только увеличивало объём адаптеров.
|
|
1384
|
+
|
|
1385
|
+
<a id="d245"></a>
|
|
1386
|
+
|
|
1387
|
+
## D245 — линейные горячие пути и проверяемое освобождение ожиданий
|
|
1388
|
+
|
|
1389
|
+
публикация использует индексы принадлежности entries, сохраняя singleton без дополнительного Set; `latest` хранит связанный список ожидающих executions и проверяет хвост общей lane без полного поиска. Инспекция использует скомпилированные зависимости владельца и индекс вкладов, пересобирает edges только после изменения экземпляров и повторно отдаёт неизменный runtime snapshot. обычная серия коротких операций не обнаруживала повторный поиск по накопленной коллекции; закрытый facade мог исчезнуть из реестра, но остаться в Promise reaction или lexical scope cleanup.
|
|
1390
|
+
|
|
1391
|
+
<a id="d247"></a>
|
|
1392
|
+
|
|
1393
|
+
## D247 — `event` допускает `backpressure: latest()`, дефолт не меняется
|
|
1394
|
+
|
|
1395
|
+
у `event` появляется необязательная опция `backpressure` с тем же публичным словом `latest()`, которое требует `stream`: пока `run` исполняется и один payload ждёт, новый payload заменяет ожидающего и запись отказа не пишется. Дефолт без опции остаётся прежним: слот принадлежит payload, занявшему его первым, а новый `emit` отбрасывается разделяемой записью `queue-capacity`.
|
|
1396
|
+
|
|
1397
|
+
<a id="d248"></a>
|
|
1398
|
+
|
|
1399
|
+
## D248 — приложение подключает devtools одним вызовом
|
|
1400
|
+
|
|
1401
|
+
`installDevtools({ execution, mode, container, sessionOptions, theme })` принимает `ApplicationExecution`, который вернул `openApplication`, и сам открывает порт наблюдения `createInspectionSession(execution)`, а при `mode: 'control'` — и порт записи `createControlSession(execution)`. Публичные поля `session` и `control` из опций убраны, совместимой формы рядом нет ([D35](#d35)). чтобы подключить панель, приложение импортировало `/internal` и создавало обе сессии само, поэтому внутренний ABI библиотеки держали два прикладных потребителя, а владение сессиями было размазано между хостом и панелью.
|
|
1402
|
+
|
|
1403
|
+
<a id="d249"></a>
|
|
1404
|
+
|
|
1405
|
+
## D249 — самостоятельная тема Devtools
|
|
1406
|
+
|
|
1407
|
+
`defaultTheme` задаёт нейтральную палитру, не требующую CSS-переменных приложения. Потребитель передаёт собственные значения через `DevtoolsTheme`; `themeMapping` ограничивает их корнем панели. Явная тема и настройки приложения используют один контракт, а установка панели без темы сохраняет её встроенные defaults.
|
|
1408
|
+
|
|
1409
|
+
<a id="d250"></a>
|
|
1410
|
+
|
|
1411
|
+
## D250 — декларации UI-моделей проверяет публичный lint
|
|
1412
|
+
|
|
1413
|
+
`@opetope/lint` поставляет `opetope/require-declared-models` и включает его в `recommended`. Проверка относится к видимым `slot`-вкладам `defineFeature`/`defineFeature.body`: локальный компонент с UI-моделями и каждый видимый reader такой модели объявляют требования через `requiresModels`. Owner-модели сохраняют неявную доступность. Анализ учитывает aliases импортов, именованные компоненты и лексические bindings, ограничен одним модулем и не считает отсутствие диагностики доказательством для импортированных реализаций, динамических списков и непрозрачных helpers. Пакет не получает runtime-зависимостей и не читает типы; типы и runtime frame остаются самостоятельными проверками. Уточняет [D158](#d158), [D227](#d227).
|
|
1414
|
+
|
|
1415
|
+
<a id="d251"></a>
|
|
1416
|
+
|
|
1417
|
+
## D251 — нижняя граница React 19.0 проверяется на tarball-пакетах
|
|
1418
|
+
|
|
1419
|
+
`@opetope/react` принимает peer `react >=19.0.0 <20`; UI и браузерная интеграция `@opetope/devtools` принимают согласованные `react` и `react-dom` в этом диапазоне. Production API не требует возможностей React 19.2. Contributor toolchain сохраняет более новые точные версии, а приёмка устанавливает все пять tarball-пакетов отдельно с React/React DOM и их типами `19.0.0`, проверяет NodeNext/Bundler, рендеринг моделей и команд, demand, монтирование и закрытие Devtools. Тот же consumer исполняется на Node `20.19.0`; новое использование React API не может незаметно поднять заявленную нижнюю границу.
|
|
1420
|
+
|
|
1421
|
+
<a id="d252"></a>
|
|
1422
|
+
|
|
1423
|
+
## D252 — стабильный замер полного application lifecycle в perf-гейте
|
|
1424
|
+
|
|
1425
|
+
Размер 1 000 application open/close проходит один полный прогрев без замера, затем три независимых инструментированных прохода по 1 000 операций. `durationMs` — медиана трёх значений, `peakLiveBytesPerOperation` и `retainedMb` — максимумы. Все raw samples, объём и метод остаются в отчёте; checksum должен совпасть с прогревом, невалидный результат и ошибка завершают гейт без повторов до прохождения. Прежний абсолютный бюджет 1 200 мс и schema 10 не меняются. Метод уменьшает влияние единичного шума shared CI на wall-clock с forced GC; сам по себе он не является свидетельством ускорения runtime. Полный последний отчёт и список нарушений сохраняются отдельно от принятого baseline; при отказе краткая сводка идёт после JSON в том же stdout.
|
|
1426
|
+
|
|
1427
|
+
<a id="d253"></a>
|
|
1428
|
+
|
|
1429
|
+
## D253 — время workload измеряется отдельно от памяти
|
|
1430
|
+
|
|
1431
|
+
Schema 11 заменяет смешанный метод [D252](#d252): для каждой нагрузки и размера в `results` выполняются один полный прогрев, три timing-прохода без heap probes и три memory-прохода с прежним post-GC sampling. Таймер охватывает полный workload, включая setup, awaited cleanup и естественный GC; предварительная сборка заканчивается до окна. Время GC не вычитается из инструментированного результата. Время — медиана, peak-live и retained memory — максимумы. Сохраняются все timing/memory samples, instrumentedDurationMs и счётчики проб; ошибки и несогласованные checksum завершают гейт без retry-until-pass. Численные бюджеты и размеры не меняются, reference переснимается явно; данные schema 10 нельзя сравнивать с новой длительностью и выдавать разницу за ускорение runtime. Baseline проверяется по схеме; enforcement использует абсолютные caps и scaling текущего запуска.
|
|
1432
|
+
|
|
1433
|
+
<a id="d254"></a>
|
|
1434
|
+
|
|
1435
|
+
## D254 — npm поставляет минифицированный ESM с исходными картами
|
|
1436
|
+
|
|
1437
|
+
Пакеты собирают JavaScript с `minify: true` и `keepNames: false`; декларации `.d.ts` сохраняются отдельно, source maps включают исходный TypeScript в `sourcesContent`. Значения `fn.name` и `constructor.name`, полученные через рефлексию, не входят в стабильный API. Явные ID деклараций, публичные `error.name`/`error.code` и проверки `instanceof` с экспортируемыми классами ошибок сохраняют контракт и проверяются на реальных tarball-потребителях. Source-map-aware инструменты позволяют найти исходный TypeScript; карты раскрывают реализацию, а не скрывают её. Политика уменьшает несжатый JavaScript, не обещая уменьшения tarball или итогового бандла хоста: эти размеры измеряются отдельно.
|