@scotthuang/agent-knock-knock 0.13.17 → 0.14.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 +38 -0
- package/CONTRIBUTING.md +212 -0
- package/README.md +105 -166
- package/connectors/deepseek-harness/LICENSE +21 -0
- package/connectors/deepseek-harness/README.md +406 -0
- package/connectors/pi/LICENSE +21 -0
- package/connectors/pi/README.md +446 -0
- package/dist/src/backend-recovery-semantic.d.ts +16 -0
- package/dist/src/backend-recovery-semantic.js +113 -0
- package/dist/src/backend-recovery-semantic.js.map +1 -0
- package/dist/src/backend-task-recovery.d.ts +103 -0
- package/dist/src/backend-task-recovery.js +142 -0
- package/dist/src/backend-task-recovery.js.map +1 -0
- package/dist/src/callback-transport.d.ts +8 -0
- package/dist/src/callback-transport.js +14 -0
- package/dist/src/callback-transport.js.map +1 -1
- package/dist/src/cli-core.js +18 -8
- package/dist/src/cli-core.js.map +1 -1
- package/dist/src/cli-runtime-context.d.ts +5 -0
- package/dist/src/cli-runtime-context.js.map +1 -1
- package/dist/src/codex-async-question-adapter.js +14 -4
- package/dist/src/codex-async-question-adapter.js.map +1 -1
- package/dist/src/codex-lifecycle-compatibility.d.ts +1 -1
- package/dist/src/codex-lifecycle-compatibility.js +9 -3
- package/dist/src/codex-lifecycle-compatibility.js.map +1 -1
- package/dist/src/codex-native-cli-adapter.d.ts +6 -0
- package/dist/src/codex-native-cli-adapter.js +273 -0
- package/dist/src/codex-native-cli-adapter.js.map +1 -0
- package/dist/src/codex-native-client-interactions.d.ts +6 -0
- package/dist/src/codex-native-client-interactions.js +124 -0
- package/dist/src/codex-native-client-interactions.js.map +1 -0
- package/dist/src/codex-native-client-rpc.d.ts +21 -0
- package/dist/src/codex-native-client-rpc.js +137 -0
- package/dist/src/codex-native-client-rpc.js.map +1 -0
- package/dist/src/codex-native-client.d.ts +42 -0
- package/dist/src/codex-native-client.js +326 -0
- package/dist/src/codex-native-client.js.map +1 -0
- package/dist/src/codex-native-identity.d.ts +6 -0
- package/dist/src/codex-native-identity.js +42 -0
- package/dist/src/codex-native-identity.js.map +1 -0
- package/dist/src/codex-native-monitor.d.ts +4 -0
- package/dist/src/codex-native-monitor.js +92 -0
- package/dist/src/codex-native-monitor.js.map +1 -0
- package/dist/src/codex-native-outbox.d.ts +16 -0
- package/dist/src/codex-native-outbox.js +120 -0
- package/dist/src/codex-native-outbox.js.map +1 -0
- package/dist/src/codex-native-public-projection.d.ts +545 -0
- package/dist/src/codex-native-public-projection.js +182 -0
- package/dist/src/codex-native-public-projection.js.map +1 -0
- package/dist/src/codex-native-record-store.d.ts +27 -0
- package/dist/src/codex-native-record-store.js +111 -0
- package/dist/src/codex-native-record-store.js.map +1 -0
- package/dist/src/codex-native-response-service.d.ts +69 -0
- package/dist/src/codex-native-response-service.js +244 -0
- package/dist/src/codex-native-response-service.js.map +1 -0
- package/dist/src/codex-native-runtime.d.ts +46 -0
- package/dist/src/codex-native-runtime.js +112 -0
- package/dist/src/codex-native-runtime.js.map +1 -0
- package/dist/src/codex-native-semantic.d.ts +17 -0
- package/dist/src/codex-native-semantic.js +175 -0
- package/dist/src/codex-native-semantic.js.map +1 -0
- package/dist/src/codex-native-snapshot.d.ts +19 -0
- package/dist/src/codex-native-snapshot.js +160 -0
- package/dist/src/codex-native-snapshot.js.map +1 -0
- package/dist/src/codex-native-state-store.d.ts +61 -0
- package/dist/src/codex-native-state-store.js +132 -0
- package/dist/src/codex-native-state-store.js.map +1 -0
- package/dist/src/codex-native-task-service.d.ts +71 -0
- package/dist/src/codex-native-task-service.js +502 -0
- package/dist/src/codex-native-task-service.js.map +1 -0
- package/dist/src/codex-native-types.d.ts +92 -0
- package/dist/src/codex-native-types.js +15 -0
- package/dist/src/codex-native-types.js.map +1 -0
- package/dist/src/codex-permission-surface.d.ts +1 -1
- package/dist/src/codex-permission-surface.js +1 -1
- package/dist/src/codex-permission-surface.js.map +1 -1
- package/dist/src/codex-terminal-agent-adapter.js +3 -1
- package/dist/src/codex-terminal-agent-adapter.js.map +1 -1
- package/dist/src/conversation-list.d.ts +12 -0
- package/dist/src/conversation-list.js +30 -0
- package/dist/src/conversation-list.js.map +1 -0
- package/dist/src/conversation-route-dispatch.d.ts +13 -0
- package/dist/src/conversation-route-dispatch.js +66 -0
- package/dist/src/conversation-route-dispatch.js.map +1 -0
- package/dist/src/conversation-route-legacy.d.ts +18 -0
- package/dist/src/conversation-route-legacy.js +54 -0
- package/dist/src/conversation-route-legacy.js.map +1 -0
- package/dist/src/conversation-route-store.d.ts +51 -0
- package/dist/src/conversation-route-store.js +126 -0
- package/dist/src/conversation-route-store.js.map +1 -0
- package/dist/src/conversation-routing-cli-adapter.d.ts +12 -0
- package/dist/src/conversation-routing-cli-adapter.js +211 -0
- package/dist/src/conversation-routing-cli-adapter.js.map +1 -0
- package/dist/src/conversation-routing-commands.d.ts +11 -0
- package/dist/src/conversation-routing-commands.js +85 -0
- package/dist/src/conversation-routing-commands.js.map +1 -0
- package/dist/src/conversation-routing-home.d.ts +26 -0
- package/dist/src/conversation-routing-home.js +105 -0
- package/dist/src/conversation-routing-home.js.map +1 -0
- package/dist/src/conversation-routing-identity.d.ts +40 -0
- package/dist/src/conversation-routing-identity.js +174 -0
- package/dist/src/conversation-routing-identity.js.map +1 -0
- package/dist/src/conversation-runtime-route-store.d.ts +11 -0
- package/dist/src/conversation-runtime-route-store.js +118 -0
- package/dist/src/conversation-runtime-route-store.js.map +1 -0
- package/dist/src/desktop-async-interactions.d.ts +15 -0
- package/dist/src/desktop-async-interactions.js +88 -0
- package/dist/src/desktop-async-interactions.js.map +1 -0
- package/dist/src/desktop-async-state.d.ts +5 -0
- package/dist/src/desktop-async-state.js +53 -0
- package/dist/src/desktop-async-state.js.map +1 -0
- package/dist/src/desktop-cli-adapter.d.ts +7 -0
- package/dist/src/desktop-cli-adapter.js +322 -0
- package/dist/src/desktop-cli-adapter.js.map +1 -0
- package/dist/src/desktop-cli-controls.d.ts +9 -0
- package/dist/src/desktop-cli-controls.js +45 -0
- package/dist/src/desktop-cli-controls.js.map +1 -0
- package/dist/src/desktop-command-presentation.d.ts +2 -0
- package/dist/src/desktop-command-presentation.js +31 -0
- package/dist/src/desktop-command-presentation.js.map +1 -0
- package/dist/src/desktop-control-semantic.d.ts +8 -0
- package/dist/src/desktop-control-semantic.js +68 -0
- package/dist/src/desktop-control-semantic.js.map +1 -0
- package/dist/src/desktop-identity.d.ts +5 -0
- package/dist/src/desktop-identity.js +40 -0
- package/dist/src/desktop-identity.js.map +1 -0
- package/dist/src/desktop-interaction-projection.d.ts +57 -0
- package/dist/src/desktop-interaction-projection.js +196 -0
- package/dist/src/desktop-interaction-projection.js.map +1 -0
- package/dist/src/desktop-interaction-state.d.ts +3 -0
- package/dist/src/desktop-interaction-state.js +48 -0
- package/dist/src/desktop-interaction-state.js.map +1 -0
- package/dist/src/desktop-ipc-async-answer.d.ts +9 -0
- package/dist/src/desktop-ipc-async-answer.js +71 -0
- package/dist/src/desktop-ipc-async-answer.js.map +1 -0
- package/dist/src/desktop-ipc-client.d.ts +47 -0
- package/dist/src/desktop-ipc-client.js +400 -0
- package/dist/src/desktop-ipc-client.js.map +1 -0
- package/dist/src/desktop-ipc-native-operations.d.ts +11 -0
- package/dist/src/desktop-ipc-native-operations.js +126 -0
- package/dist/src/desktop-ipc-native-operations.js.map +1 -0
- package/dist/src/desktop-ipc-transport.d.ts +13 -0
- package/dist/src/desktop-ipc-transport.js +123 -0
- package/dist/src/desktop-ipc-transport.js.map +1 -0
- package/dist/src/desktop-list.d.ts +25 -0
- package/dist/src/desktop-list.js +55 -0
- package/dist/src/desktop-list.js.map +1 -0
- package/dist/src/desktop-metadata-reader.d.ts +30 -0
- package/dist/src/desktop-metadata-reader.js +182 -0
- package/dist/src/desktop-metadata-reader.js.map +1 -0
- package/dist/src/desktop-monitor.d.ts +4 -0
- package/dist/src/desktop-monitor.js +101 -0
- package/dist/src/desktop-monitor.js.map +1 -0
- package/dist/src/desktop-public-projection.d.ts +6 -0
- package/dist/src/desktop-public-projection.js +134 -0
- package/dist/src/desktop-public-projection.js.map +1 -0
- package/dist/src/desktop-request-interactions.d.ts +14 -0
- package/dist/src/desktop-request-interactions.js +144 -0
- package/dist/src/desktop-request-interactions.js.map +1 -0
- package/dist/src/desktop-response-dispatch.d.ts +14 -0
- package/dist/src/desktop-response-dispatch.js +19 -0
- package/dist/src/desktop-response-dispatch.js.map +1 -0
- package/dist/src/desktop-response-evidence.d.ts +4 -0
- package/dist/src/desktop-response-evidence.js +19 -0
- package/dist/src/desktop-response-evidence.js.map +1 -0
- package/dist/src/desktop-response-service.d.ts +11 -0
- package/dist/src/desktop-response-service.js +188 -0
- package/dist/src/desktop-response-service.js.map +1 -0
- package/dist/src/desktop-response-store.d.ts +35 -0
- package/dist/src/desktop-response-store.js +58 -0
- package/dist/src/desktop-response-store.js.map +1 -0
- package/dist/src/desktop-response-types.d.ts +20 -0
- package/dist/src/desktop-response-types.js +2 -0
- package/dist/src/desktop-response-types.js.map +1 -0
- package/dist/src/desktop-response-value.d.ts +6 -0
- package/dist/src/desktop-response-value.js +31 -0
- package/dist/src/desktop-response-value.js.map +1 -0
- package/dist/src/desktop-runtime.d.ts +153 -0
- package/dist/src/desktop-runtime.js +88 -0
- package/dist/src/desktop-runtime.js.map +1 -0
- package/dist/src/desktop-semantic.d.ts +21 -0
- package/dist/src/desktop-semantic.js +140 -0
- package/dist/src/desktop-semantic.js.map +1 -0
- package/dist/src/desktop-session-catalog.d.ts +68 -0
- package/dist/src/desktop-session-catalog.js +225 -0
- package/dist/src/desktop-session-catalog.js.map +1 -0
- package/dist/src/desktop-session-controls.d.ts +145 -0
- package/dist/src/desktop-session-controls.js +176 -0
- package/dist/src/desktop-session-controls.js.map +1 -0
- package/dist/src/desktop-sidebar-metadata.d.ts +27 -0
- package/dist/src/desktop-sidebar-metadata.js +83 -0
- package/dist/src/desktop-sidebar-metadata.js.map +1 -0
- package/dist/src/desktop-sidebar-projects.d.ts +10 -0
- package/dist/src/desktop-sidebar-projects.js +31 -0
- package/dist/src/desktop-sidebar-projects.js.map +1 -0
- package/dist/src/desktop-sidebar-selection.d.ts +28 -0
- package/dist/src/desktop-sidebar-selection.js +85 -0
- package/dist/src/desktop-sidebar-selection.js.map +1 -0
- package/dist/src/desktop-snapshot-details.d.ts +4 -0
- package/dist/src/desktop-snapshot-details.js +116 -0
- package/dist/src/desktop-snapshot-details.js.map +1 -0
- package/dist/src/desktop-snapshot.d.ts +11 -0
- package/dist/src/desktop-snapshot.js +276 -0
- package/dist/src/desktop-snapshot.js.map +1 -0
- package/dist/src/desktop-state-store.d.ts +72 -0
- package/dist/src/desktop-state-store.js +269 -0
- package/dist/src/desktop-state-store.js.map +1 -0
- package/dist/src/desktop-task-interactions.d.ts +10 -0
- package/dist/src/desktop-task-interactions.js +93 -0
- package/dist/src/desktop-task-interactions.js.map +1 -0
- package/dist/src/desktop-task-recovery.d.ts +38 -0
- package/dist/src/desktop-task-recovery.js +171 -0
- package/dist/src/desktop-task-recovery.js.map +1 -0
- package/dist/src/desktop-task-service.d.ts +54 -0
- package/dist/src/desktop-task-service.js +441 -0
- package/dist/src/desktop-task-service.js.map +1 -0
- package/dist/src/desktop-types.d.ts +281 -0
- package/dist/src/desktop-types.js +13 -0
- package/dist/src/desktop-types.js.map +1 -0
- package/dist/src/host-monitor-reconciliation.js +36 -4
- package/dist/src/host-monitor-reconciliation.js.map +1 -1
- package/dist/src/host-profile-runtime.js +7 -3
- package/dist/src/host-profile-runtime.js.map +1 -1
- package/dist/src/local-codex-cli-adapter.d.ts +7 -0
- package/dist/src/local-codex-cli-adapter.js +13 -0
- package/dist/src/local-codex-cli-adapter.js.map +1 -0
- package/dist/src/openclaw-callback-transport.js +2 -1
- package/dist/src/openclaw-callback-transport.js.map +1 -1
- package/dist/src/semantic-conversation-target.d.ts +4 -0
- package/dist/src/semantic-conversation-target.js +20 -0
- package/dist/src/semantic-conversation-target.js.map +1 -0
- package/dist/src/semantic-permission-control.js +47 -9
- package/dist/src/semantic-permission-control.js.map +1 -1
- package/dist/src/semantic-private-authority-offers.d.ts +1 -1
- package/dist/src/semantic-private-authority-offers.js +3 -1
- package/dist/src/semantic-private-authority-offers.js.map +1 -1
- package/dist/src/semantic-tool-command-helpers.d.ts +6 -0
- package/dist/src/semantic-tool-command-helpers.js +199 -78
- package/dist/src/semantic-tool-command-helpers.js.map +1 -1
- package/dist/src/semantic-tool-descriptions.d.ts +2 -1
- package/dist/src/semantic-tool-descriptions.js +81 -35
- package/dist/src/semantic-tool-descriptions.js.map +1 -1
- package/dist/src/semantic-tool-list-projection.js +66 -2
- package/dist/src/semantic-tool-list-projection.js.map +1 -1
- package/dist/src/semantic-tool-presentation.js +76 -7
- package/dist/src/semantic-tool-presentation.js.map +1 -1
- package/dist/src/semantic-tool-runtime.js +129 -29
- package/dist/src/semantic-tool-runtime.js.map +1 -1
- package/dist/src/semantic-tool-schemas.d.ts +410 -27
- package/dist/src/semantic-tool-schemas.js +176 -88
- package/dist/src/semantic-tool-schemas.js.map +1 -1
- package/dist/src/terminal-action-contracts.js +10 -6
- package/dist/src/terminal-action-contracts.js.map +1 -1
- package/dist/src/terminal-list-cli-adapter.d.ts +1 -0
- package/dist/src/terminal-list-cli-adapter.js +6 -3
- package/dist/src/terminal-list-cli-adapter.js.map +1 -1
- package/dist/src/terminal-model-control-profile.d.ts +3 -1
- package/dist/src/terminal-model-control-profile.js +15 -7
- package/dist/src/terminal-model-control-profile.js.map +1 -1
- package/dist/src/terminal-monitor-decision-policy.d.ts +1 -1
- package/dist/src/terminal-native-inspection-profile.js +4 -0
- package/dist/src/terminal-native-inspection-profile.js.map +1 -1
- package/dist/src/terminal-permission-control-list-projection.d.ts +1 -1
- package/dist/src/terminal-permission-control.js +5 -1
- package/dist/src/terminal-permission-control.js.map +1 -1
- package/dist/src/terminal-questionnaire-adapter.js +5 -2
- package/dist/src/terminal-questionnaire-adapter.js.map +1 -1
- package/dist/src/terminal-user-send-intent.d.ts +2 -0
- package/dist/src/terminal-user-send-intent.js +11 -3
- package/dist/src/terminal-user-send-intent.js.map +1 -1
- package/docs/architecture/current-architecture.md +313 -0
- package/docs/architecture/interactive-terminal-response.md +276 -0
- package/docs/architecture/issue-126-final-report.md +248 -0
- package/docs/architecture/orchestration-refactor-history.md +2987 -0
- package/docs/architecture/orchestration-refactor.md +21 -0
- package/docs/backend-task-recovery.md +89 -0
- package/docs/bidirectional-agent-protocol.md +260 -0
- package/docs/codex-0.160.0-compatibility.md +126 -0
- package/docs/codex-cli-native-compatibility.md +246 -0
- package/docs/codex-desktop-compatibility.md +414 -0
- package/docs/codex-permissions.md +12 -1
- package/docs/openclaw-operations.md +281 -0
- package/docs/openclaw-session-turn-delivery-requirement.md +45 -0
- package/docs/operator-guide.md +543 -0
- package/docs/storage-and-logging.md +91 -0
- package/docs/test-performance-issue-108.md +80 -0
- package/docs/test-performance-issue-120.md +226 -0
- package/docs/testing.md +628 -0
- package/openclaw.plugin.json +7 -3
- package/package.json +6 -12
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +69 -18
|
@@ -0,0 +1,2987 @@
|
|
|
1
|
+
# Historical Issue #126 orchestration refactor ledger
|
|
2
|
+
|
|
3
|
+
> Immutable historical record: this document records the v0.12.11 / Issue #126
|
|
4
|
+
> plan, its chronological phase reports, and later dated addenda. Tool counts,
|
|
5
|
+
> action-contract versions, Watch schemas, writer protocols, module sizes, and
|
|
6
|
+
> pending-work statements are true only for the snapshot named by their
|
|
7
|
+
> section. See [current-architecture.md](./current-architecture.md) for the
|
|
8
|
+
> authoritative current architecture, budgets, and refactor workflow.
|
|
9
|
+
|
|
10
|
+
Status: architecture implementation and enforceable static gates are complete
|
|
11
|
+
at the current closeout;
|
|
12
|
+
[issue #126](https://github.com/scotthuang/agent-knock-knock/issues/126)
|
|
13
|
+
remains open for longitudinal acceptance. The final timed
|
|
14
|
+
fast/integration/full profile, dynamic subprocess runtime attestation, and one
|
|
15
|
+
local OpenClaw install are separate pending final-evidence steps; this status
|
|
16
|
+
does not claim they have run.
|
|
17
|
+
|
|
18
|
+
The four remaining criteria require observations after the refactor:
|
|
19
|
+
|
|
20
|
+
- at least 70% of normal product changes no longer modify `cli-core.ts`;
|
|
21
|
+
- at least 80% of normal affected-test loops complete in 60 seconds or less;
|
|
22
|
+
- five post-refactor product changes reduce median ready-to-release lead time
|
|
23
|
+
by at least 40%; and
|
|
24
|
+
- repeated full-suite flaky failures remain below 1%.
|
|
25
|
+
|
|
26
|
+
The frozen ten-change selector replay proves selector behavior, and a
|
|
27
|
+
point-in-time suite profile proves only that measured revision. Neither can
|
|
28
|
+
substitute for these four longitudinal samples.
|
|
29
|
+
|
|
30
|
+
Snapshot: `main@ea592a88d7af4a709e7a7a1b989dd29e61932935` / `v0.12.11`, measured 2026-08-14
|
|
31
|
+
|
|
32
|
+
Machine-readable measurements: [orchestration-baseline.json](./orchestration-baseline.json)
|
|
33
|
+
|
|
34
|
+
## Purpose
|
|
35
|
+
|
|
36
|
+
This document defines the boundaries, dependency direction, transaction rules,
|
|
37
|
+
and compatibility contract for the incremental orchestration refactor. It is a
|
|
38
|
+
design constraint for the PR sequence, not a claim that the current source tree
|
|
39
|
+
already satisfies the target architecture.
|
|
40
|
+
|
|
41
|
+
The objective is to make ordinary product changes local and reviewable while
|
|
42
|
+
preserving AKK's safety model. `src/cli-core.ts` must become a stable command
|
|
43
|
+
facade over typed services instead of remaining the owner of terminal authority,
|
|
44
|
+
dispatch, lifecycle, monitor, callback, persistence, and recovery state machines.
|
|
45
|
+
|
|
46
|
+
This work is a strangler refactor. Each PR extracts and characterizes existing
|
|
47
|
+
behavior behind a typed boundary before callers switch to that boundary. A
|
|
48
|
+
ground-up rewrite, protocol redesign, or safety simplification is out of scope.
|
|
49
|
+
|
|
50
|
+
## Current baseline and concentration
|
|
51
|
+
|
|
52
|
+
The production scope is the 38 checked-in `src/**/*.ts` files. Tests, generated
|
|
53
|
+
`dist`, scripts, templates, and vendored dependencies are excluded.
|
|
54
|
+
|
|
55
|
+
| Metric | Current baseline |
|
|
56
|
+
| --- | ---: |
|
|
57
|
+
| Production physical LOC | 73,792 |
|
|
58
|
+
| Functions/methods with bodies | 2,449 |
|
|
59
|
+
| Files over 1,000 LOC | 16 |
|
|
60
|
+
| Functions over 100 LOC | 167 |
|
|
61
|
+
| Functions over 200 LOC | 57 |
|
|
62
|
+
| Functions over 500 LOC | 9 |
|
|
63
|
+
| Approximate complexity over 20 | 150 |
|
|
64
|
+
| Production import cycles | 0 |
|
|
65
|
+
|
|
66
|
+
`src/cli-core.ts` is the dominant risk concentration:
|
|
67
|
+
|
|
68
|
+
| Metric | `src/cli-core.ts` |
|
|
69
|
+
| --- | ---: |
|
|
70
|
+
| Physical LOC | 38,005 (51.5% of production source) |
|
|
71
|
+
| Functions/methods with bodies | 913 |
|
|
72
|
+
| Functions over 100 / 200 / 500 LOC | 116 / 43 / 8 |
|
|
73
|
+
| Approximate complexity over 20 | 98 |
|
|
74
|
+
| Import declarations | 37 |
|
|
75
|
+
| Distinct internal modules imported | 30 |
|
|
76
|
+
| `Record<string, any>` type references | 246 |
|
|
77
|
+
| Functions receiving an `options` bag | 152 |
|
|
78
|
+
| Distinct `options.<property>` names | 117 |
|
|
79
|
+
| Durable mutation calls | 204 |
|
|
80
|
+
| Lock or writer-lease acquisition calls | 91 |
|
|
81
|
+
|
|
82
|
+
The largest current paths are:
|
|
83
|
+
|
|
84
|
+
- `runTerminalControlSend` at `src/cli-core.ts:19838`: 1,886 lines,
|
|
85
|
+
approximate complexity 242.
|
|
86
|
+
- `runTerminalBridgeMonitorWithLock` at `src/cli-core.ts:27647`: 1,444
|
|
87
|
+
lines, approximate complexity 203.
|
|
88
|
+
- `terminalFirstListProjection` at `src/cli-core.ts:4931`: 1,283 lines;
|
|
89
|
+
its terminal projection callback is 1,162 lines with approximate complexity
|
|
90
|
+
302.
|
|
91
|
+
- `runNativeThreadTransition` at `src/cli-core.ts:16516`: 812 lines; its
|
|
92
|
+
transaction callback is 790 lines.
|
|
93
|
+
- `runSend` at `src/cli-core.ts:18077`: 721 lines.
|
|
94
|
+
- `runApprove` at `src/cli-core.ts:19041`: 635 lines.
|
|
95
|
+
|
|
96
|
+
The problem is concentrated orchestration, not uniform source quality. The
|
|
97
|
+
import graph is currently acyclic and the public imported surface of
|
|
98
|
+
`cli-core.ts` is small, so behavior can be replaced behind that facade without
|
|
99
|
+
forcing consumers to migrate in one step.
|
|
100
|
+
|
|
101
|
+
The test cost is similarly concentrated. At the `v0.12.11` baseline, 71
|
|
102
|
+
TypeScript test files contain 71,902 physical lines. Three clean fast-tier runs
|
|
103
|
+
at concurrency four completed in 8.68, 8.70, and 8.85 seconds (median 8.70
|
|
104
|
+
seconds). Two clean integration-tier runs took 922.01 and 985.75 seconds; one
|
|
105
|
+
was green and one exposed the pre-existing monitor-singleton supersession
|
|
106
|
+
timeout. In both runs, `test/codex-no-rollout-binding-cli.test.ts` alone took
|
|
107
|
+
921.81–985.56 seconds. Refactoring success therefore requires narrower affected
|
|
108
|
+
selection and lighter deterministic fixtures, not fewer safety invariants.
|
|
109
|
+
|
|
110
|
+
## Architectural vocabulary
|
|
111
|
+
|
|
112
|
+
- **Facade**: stable CLI-facing API that parses a command, selects a handler,
|
|
113
|
+
formats output, and maps failures to the existing process contract.
|
|
114
|
+
- **Observation**: immutable facts sampled from Store, terminal, process, agent,
|
|
115
|
+
and transcript sources. An observation is evidence, not durable authority by
|
|
116
|
+
itself.
|
|
117
|
+
- **Authority decision**: a pure, typed allow/deny/recovery result derived from
|
|
118
|
+
an observation and a specific operation. It carries exact reasons and the
|
|
119
|
+
snapshot-bound tokens required for later revalidation.
|
|
120
|
+
- **Use case**: one command-level orchestration operation such as send, approve,
|
|
121
|
+
new thread, callback delivery, or one monitor step.
|
|
122
|
+
- **Transaction shell**: the only layer allowed to acquire mutation locks,
|
|
123
|
+
perform CAS writes, and execute ordered durable effects.
|
|
124
|
+
- **Port**: a typed interface used by a use case for time, Store, terminal,
|
|
125
|
+
process, transcript, or callback transport access.
|
|
126
|
+
- **Adapter**: an implementation of a port. Codex-, Claude-, tmux-, Herdr-,
|
|
127
|
+
filesystem-, and OpenClaw-specific behavior belongs here.
|
|
128
|
+
|
|
129
|
+
## Target module ownership
|
|
130
|
+
|
|
131
|
+
The path names below describe ownership. A PR may choose nearby names, but it
|
|
132
|
+
must preserve the responsibility and dependency rules.
|
|
133
|
+
|
|
134
|
+
| Boundary | Owns | Must not own |
|
|
135
|
+
| --- | --- | --- |
|
|
136
|
+
| `cli.ts` | Process argv, stdout/stderr forwarding, process exit | Business decisions, Store or terminal access |
|
|
137
|
+
| CLI runtime and command registry | Per-execution context, typed parsing, command registration, output envelope | Terminal authority, lifecycle or callback state machines |
|
|
138
|
+
| `cli-core.ts` | Compatibility exports `parseCliCommand` and `executeCliCommand`; temporary routing shims | New state machines, new persistence codecs, new direct lock code |
|
|
139
|
+
| Terminal observation | Typed terminal/process/agent snapshots and normalization | Permission decisions or mutations |
|
|
140
|
+
| Authority and action projection | Binding match/conflict, ownership, selectors, tokens, `available_actions`, handoff decisions | I/O, clocks, filesystem paths, terminal input |
|
|
141
|
+
| Persistence repositories/codecs | Backward-compatible decoding, validation, atomic write primitives, revisions and CAS | Product policy or terminal input |
|
|
142
|
+
| Transaction/lock kernel | Canonical lock acquisition/release and per-transaction capabilities consumed by gated mutation ports | Business decisions, durable effect ordering, command parsing, or agent-specific screen logic |
|
|
143
|
+
| Dispatch service | Send/respond/approve/cancel preparation, exact input stages, acceptance receipt decisions | CLI formatting, callback transport, native-thread lifecycle policy |
|
|
144
|
+
| Lifecycle service | New/resume/adopt/reconcile classifications and transition reducer | Ordinary task submission or callback delivery |
|
|
145
|
+
| Callback/outbox service | Immutable callback message, attempt lease, retry and delivery settlement | Monitor polling or terminal authority projection |
|
|
146
|
+
| Monitor service | Poll scheduling, pure completion/question/approval/stall decisions, reconciliation effects | Gateway transport details or duplicated dispatch policy |
|
|
147
|
+
| Agent adapters | Codex/Claude process classification, composer/status/transcript profiles, native identity evidence | Store transactions or CLI response schemas |
|
|
148
|
+
| Terminal-control adapters | tmux/Herdr discovery, screen capture, exact terminal mutation | Session/Turn policy or Store writes |
|
|
149
|
+
| OpenClaw plugin | Tool schemas, argument mapping, command registration, Gateway integration | A second copy of CLI authority or action projection |
|
|
150
|
+
|
|
151
|
+
Existing cohesive modules such as `store.ts`, `session-store.ts`,
|
|
152
|
+
`terminal-control-provider.ts`, `terminal-agent-adapter.ts`, and agent-specific
|
|
153
|
+
adapters are retained behind ports. Extraction may split their codecs from
|
|
154
|
+
repositories, but it must not funnel their responsibilities back through the
|
|
155
|
+
CLI facade.
|
|
156
|
+
|
|
157
|
+
## Dependency direction
|
|
158
|
+
|
|
159
|
+
The allowed direction is:
|
|
160
|
+
|
|
161
|
+
```text
|
|
162
|
+
CLI / OpenClaw entrypoints
|
|
163
|
+
|
|
|
164
|
+
v
|
|
165
|
+
typed command facade and composition root
|
|
166
|
+
|
|
|
167
|
+
v
|
|
168
|
+
dispatch | lifecycle | callback | monitor use cases
|
|
169
|
+
|
|
|
170
|
+
v
|
|
171
|
+
pure authority, action, and state-transition policies
|
|
172
|
+
|
|
|
173
|
+
v
|
|
174
|
+
typed domain values and port interfaces
|
|
175
|
+
^
|
|
176
|
+
|
|
|
177
|
+
filesystem, tmux, Herdr, Codex, Claude, and Gateway adapters
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The arrows represent compile-time dependencies. Infrastructure implements ports
|
|
181
|
+
defined inward; domain and use-case modules never import infrastructure or the
|
|
182
|
+
CLI facade.
|
|
183
|
+
|
|
184
|
+
Required rules:
|
|
185
|
+
|
|
186
|
+
1. No new service may import `cli-core.ts`.
|
|
187
|
+
2. Pure policy/reducer modules may not import `node:fs`, `node:child_process`,
|
|
188
|
+
environment access, wall clocks, or sleep functions.
|
|
189
|
+
3. `cli-core.ts` and the OpenClaw plugin consume the same action and authority
|
|
190
|
+
result; neither reconstructs permission rules from output fields.
|
|
191
|
+
4. Agent-specific composer, native-status, and transcript behavior stays behind
|
|
192
|
+
the agent-adapter boundary.
|
|
193
|
+
5. Store codecs accept retained legacy formats at the boundary. Use cases
|
|
194
|
+
consume validated current domain values.
|
|
195
|
+
6. The production import graph must remain acyclic. A cycle is a release
|
|
196
|
+
blocker, not an acceptable transitional state.
|
|
197
|
+
7. Both `cli-core.ts` physical LOC and total `src/**/*.ts` physical LOC are
|
|
198
|
+
exact ratchets in the ownership manifest. An extraction may lower either
|
|
199
|
+
value, but cannot silently grow it back; any intentional increase requires
|
|
200
|
+
an explicit architecture review and manifest diff.
|
|
201
|
+
|
|
202
|
+
## Canonical lock order
|
|
203
|
+
|
|
204
|
+
All newly extracted mutation code uses this acquisition order, skipping a scope
|
|
205
|
+
only when that resource is not involved:
|
|
206
|
+
|
|
207
|
+
```text
|
|
208
|
+
terminal dispatch lock -> Store writer lease -> conversation state lock
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Locks are released in reverse order. An operation must never acquire a lock to
|
|
212
|
+
the left while it already holds a lock to the right.
|
|
213
|
+
|
|
214
|
+
- The terminal dispatch lock serializes all input and lifecycle effects for one
|
|
215
|
+
canonical terminal endpoint/incarnation.
|
|
216
|
+
- The Store writer lease fences incompatible writers and serializes mutations
|
|
217
|
+
across authoritative Session, Turn, transition, and transfer records.
|
|
218
|
+
- The conversation state lock protects one Turn state/event transaction and its
|
|
219
|
+
compare-before-write checks.
|
|
220
|
+
|
|
221
|
+
The transaction shell creates fresh opaque terminal, Store-writer, and optional
|
|
222
|
+
conversation-state scopes for every invocation. Capability-gated repositories
|
|
223
|
+
validate that every required scope is authentic, active, and belongs to the
|
|
224
|
+
same transaction and exact canonical terminal, Store, or state resource.
|
|
225
|
+
Repositories take their raw target from the verified frozen resource handle,
|
|
226
|
+
so a caller cannot pair a valid scope with a different path or terminal.
|
|
227
|
+
Scopes expire before lock release begins, so a leaked scope cannot authorize a
|
|
228
|
+
later write. Boolean parameters such as
|
|
229
|
+
`terminalSendLockHeld`, `terminalStateLockHeld`, and `storeWriterLeaseHeld` must
|
|
230
|
+
not be reproduced in new services.
|
|
231
|
+
|
|
232
|
+
Read-only observation must not take mutation locks merely for convenience.
|
|
233
|
+
Before a side effect, the transaction shell re-observes and revalidates exact
|
|
234
|
+
endpoint, process incarnation, binding generation, owner, composer, approval,
|
|
235
|
+
and snapshot/token authority under the required locks.
|
|
236
|
+
|
|
237
|
+
### Current lock-order exceptions
|
|
238
|
+
|
|
239
|
+
The canonical order above is a target constraint, not a statement that every
|
|
240
|
+
`v0.12.11` path already conforms. Known structural exceptions at the baseline
|
|
241
|
+
include:
|
|
242
|
+
|
|
243
|
+
- `runTerminalControlSend` (`src/cli-core.ts:19838`) can express
|
|
244
|
+
terminal -> state -> writer through recursive `*LockHeld` flags.
|
|
245
|
+
- `runTerminalControlCancel` (`src/cli-core.ts:26274`) acquires terminal, then
|
|
246
|
+
state, then enters the writer lease.
|
|
247
|
+
|
|
248
|
+
Behavior-preserving extraction must inventory every reachable exception. It may
|
|
249
|
+
wrap an existing order temporarily, with a named compatibility note and focused
|
|
250
|
+
deadlock/crash tests, but it must not add another instance. Reordering an
|
|
251
|
+
existing transaction is a separate focused change with proof at every durable
|
|
252
|
+
write boundary; it must not be hidden inside a file move.
|
|
253
|
+
|
|
254
|
+
## Transaction phases
|
|
255
|
+
|
|
256
|
+
### Ordinary terminal dispatch
|
|
257
|
+
|
|
258
|
+
The target dispatch transaction is explicit and monotonic:
|
|
259
|
+
|
|
260
|
+
1. **Resolve**: select the exact Session/Turn/terminal and capture observations.
|
|
261
|
+
2. **Authorize**: derive one typed authority decision and required token set.
|
|
262
|
+
3. **Lock and revalidate**: acquire terminal -> writer -> state and prove the
|
|
263
|
+
same endpoint, owner, process incarnation, binding generation, request, and
|
|
264
|
+
composer boundary.
|
|
265
|
+
4. **Prepare**: persist the immutable request identity and `prepared` dispatch
|
|
266
|
+
ledger before terminal input.
|
|
267
|
+
5. **Inject text**: record `text_injected` only after exact text injection is
|
|
268
|
+
acknowledged.
|
|
269
|
+
6. **Dispatch Enter**: send exactly one Enter and durably record
|
|
270
|
+
`enter_dispatched`. Legacy `submitted` is compatibility evidence for this
|
|
271
|
+
stage, not proof of native acceptance.
|
|
272
|
+
7. **Observe acceptance**: record `agent_accepted` only with exact supported
|
|
273
|
+
native evidence. Record `not_accepted` or `uncertain` when that is what the
|
|
274
|
+
evidence proves.
|
|
275
|
+
8. **Commit and monitor**: commit Session/Turn/binding effects and start or
|
|
276
|
+
reconcile the monitor from durable state.
|
|
277
|
+
|
|
278
|
+
Before input, a proven rollback may end as `aborted` with `safe_to_retry=true`.
|
|
279
|
+
After input may have begun, ambiguous outcomes are `uncertain` with
|
|
280
|
+
`do_not_retry=true`. No extraction may collapse these two cases.
|
|
281
|
+
|
|
282
|
+
### Native-thread lifecycle
|
|
283
|
+
|
|
284
|
+
New, resume, and adopted external handoff use a separate transition state
|
|
285
|
+
machine:
|
|
286
|
+
|
|
287
|
+
```text
|
|
288
|
+
prepared -> dispatching -> submitted -> verified -> committed
|
|
289
|
+
| | |
|
|
290
|
+
+----------> uncertain <---+
|
|
291
|
+
|
|
|
292
|
+
+----------> aborted (only with zero-input proof)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
`prepared` transition and lifecycle ledger records precede terminal input.
|
|
296
|
+
`verified` requires exact postcondition identity. Session binding changes commit
|
|
297
|
+
with revision/CAS evidence before the lifecycle ledger becomes `resolved`.
|
|
298
|
+
Human-observed adoption is evidence and must never replay terminal input.
|
|
299
|
+
|
|
300
|
+
### Deferred foreground transfer
|
|
301
|
+
|
|
302
|
+
The Codex follow-current path retains its own durable transfer receipt:
|
|
303
|
+
|
|
304
|
+
```text
|
|
305
|
+
prepared -> source_reserved -> target_prepared -> dispatch_started
|
|
306
|
+
-> committed -> resolved
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Its input substage is monotonic:
|
|
310
|
+
|
|
311
|
+
```text
|
|
312
|
+
none -> dispatch_started -> text_injected -> enter_dispatched -> agent_accepted
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Only zero-input proof may reach `aborted`/`abort_resolved`. Possible input with
|
|
316
|
+
an unproved outcome reaches `uncertain`; recovery may later prove and commit the
|
|
317
|
+
same dispatch but may not send it again.
|
|
318
|
+
|
|
319
|
+
### Callback/outbox
|
|
320
|
+
|
|
321
|
+
1. Resolve one trusted, versioned, secretless callback route; a present invalid
|
|
322
|
+
route fails closed and never falls back to legacy host fields.
|
|
323
|
+
2. Prepare one immutable callback envelope and deterministic delivery/idempotency
|
|
324
|
+
identity.
|
|
325
|
+
3. Persist the envelope, route snapshot, pending outbox state, and attempt lease
|
|
326
|
+
before transport.
|
|
327
|
+
4. Resolve the route to a concrete adapter at the composition root. The current
|
|
328
|
+
adapter preserves the OpenClaw Gateway behavior; core services do not select
|
|
329
|
+
or construct it.
|
|
330
|
+
5. Persist an explicit accepted, retryable-failure, permanent-failure, or
|
|
331
|
+
uncertain attempt outcome. Only retryable failure schedules another attempt;
|
|
332
|
+
accepted checkpoints survive a later wake/observation failure.
|
|
333
|
+
6. Reconciliation resumes only the same persisted route, envelope,
|
|
334
|
+
message, and attempt authority. Current CLI options or Conversation fields
|
|
335
|
+
cannot redirect an existing outbox.
|
|
336
|
+
|
|
337
|
+
Callback transport state does not own or rewrite the semantic Turn phase.
|
|
338
|
+
Cross-Session callback delivery remains strictly isolated.
|
|
339
|
+
|
|
340
|
+
The first host-neutral slice retains the existing OpenClaw fields and Turn
|
|
341
|
+
status names as a read/write compatibility projection. OpenClaw's trusted
|
|
342
|
+
plugin still supplies the controller session identity; model-facing tools never
|
|
343
|
+
accept a callback destination or profile. A standalone supervisor and new host
|
|
344
|
+
adapters remain separate follow-on work.
|
|
345
|
+
|
|
346
|
+
### Monitor step
|
|
347
|
+
|
|
348
|
+
A monitor iteration becomes `observe -> decide -> execute effects -> persist`.
|
|
349
|
+
The decision is pure and may yield wait, diagnostic, approval notification,
|
|
350
|
+
question, completion claim, verified-dead stall/close recovery, timeout stall,
|
|
351
|
+
or dispatch-ledger reconciliation. The I/O shell is responsible for locks and
|
|
352
|
+
idempotent effect execution. Polling never becomes authority to replay input.
|
|
353
|
+
|
|
354
|
+
## Durable write points
|
|
355
|
+
|
|
356
|
+
The following records are externally observable recovery authorities. Their
|
|
357
|
+
ordering and compatibility are behavior, not implementation detail.
|
|
358
|
+
|
|
359
|
+
| Durable record | Current location | Authority retained during extraction |
|
|
360
|
+
| --- | --- | --- |
|
|
361
|
+
| Store manifest | `<store>/manifest.json` | Format/writer compatibility and writer fencing |
|
|
362
|
+
| Managed Session | `<store>/sessions/<session>/state.json` | Binding, native identity, revision/CAS, lineage |
|
|
363
|
+
| Turn/conversation state | `<store>/conversations/<turn>/state.json` | Semantic Turn phase, submission receipt, callback outbox |
|
|
364
|
+
| Turn event log | `<store>/conversations/<turn>/events.ndjson` | Append-only audit and recovery evidence |
|
|
365
|
+
| Native transition | `<store>/transitions/<transition>/state.json` | Lifecycle generation, input outcome, verification and commit |
|
|
366
|
+
| Deferred foreground transfer | `<store>/deferred-foreground-transfers/<transfer>/state.json` | Follow-current reservation, input stage, commit/abort authority |
|
|
367
|
+
| Terminal dispatch ledger | `<runtime-v2>/terminal-dispatch/terminal-dispatch-<key>.json` | Terminal-wide input owner and strongest transport receipt |
|
|
368
|
+
| Terminal/monitor lock files | `<runtime-v2>/terminal-locks` and monitor lock paths | Live serialization only; never semantic authority by themselves |
|
|
369
|
+
|
|
370
|
+
For every extracted transaction, the PR must include a durable write map that
|
|
371
|
+
states:
|
|
372
|
+
|
|
373
|
+
- the precondition and held lock scopes (and, once enforced by a gated port,
|
|
374
|
+
capabilities);
|
|
375
|
+
- the record and expected revision/generation;
|
|
376
|
+
- whether terminal input is definitely zero, possible, or accepted;
|
|
377
|
+
- the crash point immediately before and after the write;
|
|
378
|
+
- the single allowed reconciliation direction;
|
|
379
|
+
- whether retry is safe, forbidden, or requires explicit recovery authority.
|
|
380
|
+
|
|
381
|
+
The strongest durable proof is never overwritten by weaker observation. Event
|
|
382
|
+
write failure after a stronger state/ledger commit is reconciled as lagging
|
|
383
|
+
audit, not by downgrading the committed fact.
|
|
384
|
+
|
|
385
|
+
### Transaction capability write map
|
|
386
|
+
|
|
387
|
+
PR3 applies the kernel only to operations that already use the target lock
|
|
388
|
+
order. Their business callbacks remain in `cli-core.ts`; the kernel owns scope
|
|
389
|
+
authenticity and lifetime, not these records or effects.
|
|
390
|
+
|
|
391
|
+
| Repository boundary | Required capabilities | Composition adapter retained |
|
|
392
|
+
| --- | --- | --- |
|
|
393
|
+
| Conversation state load / save / event append | state / writer + state / writer + state | existing Store filesystem and JSON functions |
|
|
394
|
+
| Terminal dispatch-ledger load / save / resolve / reconcile | terminal / terminal + writer | existing runtime-ledger filesystem and lifecycle reconciliation functions |
|
|
395
|
+
| Managed Session load / CAS save | writer | existing Session repository functions |
|
|
396
|
+
|
|
397
|
+
Lifecycle recovery and reconciliation receive both the exact locked terminal
|
|
398
|
+
and canonical Store path from a paired repository capability. A recorded
|
|
399
|
+
`store_dir` is comparison evidence only: a mismatch fails closed before any
|
|
400
|
+
transition read, quarantine, Session write, or lifecycle-ledger resolution.
|
|
401
|
+
|
|
402
|
+
| Operation | Held lock scopes | Durable writes and existing order | Terminal input | Crash/retry direction |
|
|
403
|
+
| --- | --- | --- | --- | --- |
|
|
404
|
+
| `runReconcileBinding` | terminal -> writer | one managed Session CAS detach at the listed revision | definitely zero | before CAS, refresh and reauthorize; after CAS, detached is final and a stale token cannot retry |
|
|
405
|
+
| `runTerminalConversationCancel` | terminal -> writer | none; runtime audit and JSON output remain after the adapter call | possible ordered cancel keys | before input, a fresh cancel may retry; after an unacknowledged transport attempt, adapter semantics remain authoritative |
|
|
406
|
+
| `runObservedHandoffClose` | terminal -> writer -> state | Turn state `closed` -> exact dispatch-ledger resolution -> close event | definitely zero | advance only toward ledger/event reconciliation; stale handoff authority cannot start a second close |
|
|
407
|
+
| `runTerminalDispatchClose` | terminal -> writer | lifecycle reconciliation keeps its existing writes; orphan recovery writes one exact dispatch-ledger generation as `resolved` | definitely zero | advance only toward resolved; refresh is required after the recorded generation changes |
|
|
408
|
+
|
|
409
|
+
Each callback continues to perform the same observations, compare-before-write
|
|
410
|
+
checks, output, and error text under the same lock scopes. Handoff close routes
|
|
411
|
+
its fresh Turn/Session/ledger loads, state save, ledger resolution, and event
|
|
412
|
+
append through the gated repositories. Dispatch close routes its
|
|
413
|
+
pane-incarnation load/resolution and later reconciliation writes through them;
|
|
414
|
+
binding reconciliation uses
|
|
415
|
+
the managed-Session adapter for its fresh reads and CAS detach. The transaction
|
|
416
|
+
module supplies no effect DSL and cannot construct Store or protocol state.
|
|
417
|
+
Native-transition and raw/managed-send entry points use the same paired
|
|
418
|
+
capability for lifecycle-fence recovery; unrelated dispatch and lifecycle
|
|
419
|
+
writes remain in their existing shells for their later service milestones.
|
|
420
|
+
|
|
421
|
+
### Initial native-thread transition policy slice
|
|
422
|
+
|
|
423
|
+
PR5a introduces `native-thread-transition-policy.ts` as a 297-line pure typed
|
|
424
|
+
decision module. It owns lifecycle capability eligibility, exact resume
|
|
425
|
+
candidate and target-Session decisions, explicit binding-reconciliation
|
|
426
|
+
eligibility, prepared transition construction, the six in-memory transition
|
|
427
|
+
phase projections, and the durable failure-phase priority. `cli-core.ts`
|
|
428
|
+
remains at its 37,873-line ratchet: this first slice moves one authority source
|
|
429
|
+
without using formatting changes to claim a size reduction.
|
|
430
|
+
|
|
431
|
+
The module has only type dependencies on managed Session/transition state and
|
|
432
|
+
terminal identity. It imports no filesystem, process, terminal-control, Store,
|
|
433
|
+
clock, or lock implementation. The shell still owns every public error string,
|
|
434
|
+
terminal/process observation, token comparison input, clock read, and effect.
|
|
435
|
+
The existing `terminal -> Store writer` lock scope is unchanged. Durable order
|
|
436
|
+
also remains transition `prepared` before lifecycle ledger `prepared`, each
|
|
437
|
+
transition phase CAS before its matching ledger phase, target ownership proof
|
|
438
|
+
before commit, and verified Session commit before transition/ledger resolution.
|
|
439
|
+
|
|
440
|
+
The focused fast table covers new/resume construction (including null versus
|
|
441
|
+
existing target revision), all six phase events, failure priority, candidate
|
|
442
|
+
and target eligibility, and reconciliation. Affected-test selection binds this
|
|
443
|
+
module to `codex-no-rollout-binding-cli`, `human-handoff-adoption-cli`,
|
|
444
|
+
`native-thread-lifecycle-cli`, and `native-thread-lifecycle-recovery-cli`.
|
|
445
|
+
|
|
446
|
+
### Initial dispatch-ledger codec slice
|
|
447
|
+
|
|
448
|
+
PR4b introduces `terminal-dispatch-ledger-codec.ts` as a pure document codec
|
|
449
|
+
and append-only receipt reducer. It owns v1/v2 in-memory document validation,
|
|
450
|
+
lifecycle-document classification, receipt history validation/candidate
|
|
451
|
+
projection/strength-preserving merge, and construction of the next JSON
|
|
452
|
+
document. This lowers `cli-core.ts` from 37,809 to 37,481 physical lines.
|
|
453
|
+
|
|
454
|
+
The shell still chooses canonical and legacy runtime keys and paths and owns
|
|
455
|
+
every filesystem observation and effect: dual-path conflict checks, symlink and
|
|
456
|
+
regular-file fences, reads, promotion rename, directory fsync, exclusive temp
|
|
457
|
+
creation, chmod, write/fsync, atomic rename, and cleanup. The codec receives
|
|
458
|
+
already-read bytes and precomputed document identity. Native `JSON.parse`
|
|
459
|
+
failures, invalid-ledger text, v1/v2 field presence and insertion order,
|
|
460
|
+
historical terminal-incarnation evidence, immutable receipt fields, strongest
|
|
461
|
+
receipt proof, and the one proven-safe abort retry generation remain unchanged.
|
|
462
|
+
|
|
463
|
+
Focused tables characterize malformed and duplicate histories, every lifecycle
|
|
464
|
+
discriminator and receipt status, immutable-field and terminal-incarnation
|
|
465
|
+
conflicts, proof downgrade prevention, safe-abort chronology, and v1/v2 JSON
|
|
466
|
+
ordering. The affected integration map covers dispatch authority, recovery,
|
|
467
|
+
receipt fences, terminal send gates, control locks, Codex no-rollout binding,
|
|
468
|
+
handoff adoption, and native lifecycle recovery.
|
|
469
|
+
|
|
470
|
+
### PR4B1 dispatch receipt and application seam
|
|
471
|
+
|
|
472
|
+
PR4B1 introduces `terminal-dispatch-receipt.ts` for pure terminal bridge state
|
|
473
|
+
and append-only receipt construction and `terminal-dispatch-application.ts` as
|
|
474
|
+
a typed application seam for already-authorized ordinary dispatch writes. It
|
|
475
|
+
composes the existing ordinary-ledger codec and zero-input abort reducer behind
|
|
476
|
+
five local responsibility groups: irreversible-stage synchronization, state,
|
|
477
|
+
ledger, domain audit, and pre-input rollback. It imports no CLI option type,
|
|
478
|
+
raw JSON or filesystem adapter, lock implementation, terminal transport,
|
|
479
|
+
acceptance poller, native binding authority, or public presenter.
|
|
480
|
+
|
|
481
|
+
Measured against exact head `22a379e60329d19ed884264b532106149116726d`,
|
|
482
|
+
this seam lowers `cli-core.ts` from 32,146 to 31,321 physical lines. The
|
|
483
|
+
492-line receipt module and 731-line application module bring total production
|
|
484
|
+
from 76,076 to 76,474 lines, a reviewed 398-line typed-boundary overhead. The
|
|
485
|
+
largest new function is the 164-line receipt reducer; the largest application
|
|
486
|
+
method is the 118-line zero-input abort method. All new functions remain below
|
|
487
|
+
the hard 500-line and approximate-complexity-50 gates.
|
|
488
|
+
|
|
489
|
+
PR4B1 deliberately preserves the legacy fallback lock acquisition order:
|
|
490
|
+
terminal send lock, Turn-state lock, then Store-writer lease. The composition
|
|
491
|
+
root continues to own those locks and supplies raw state, ledger, event,
|
|
492
|
+
rollback, clock, and crash-hook adapters. Application ports are invoked only
|
|
493
|
+
inside that existing scope and do not expose lock handles or repositories. The
|
|
494
|
+
stage synchronization port only copies the staged conversation and irreversible
|
|
495
|
+
stage timestamp into local core catch variables before state, ledger, or
|
|
496
|
+
deferred/handoff effects; it performs no I/O and cannot escape the invocation.
|
|
497
|
+
|
|
498
|
+
The composition root also retains terminal input and Enter, acceptance
|
|
499
|
+
observation and polling, deferred-transfer and native-binding authority,
|
|
500
|
+
collateral stalling, and every CLI/OpenClaw JSON result. Only durable object
|
|
501
|
+
construction and ordered application moved:
|
|
502
|
+
|
|
503
|
+
- prepared remains ledger then state; either failure restores the prior ledger,
|
|
504
|
+
rolls back the provisional raw attach, and rethrows before terminal input;
|
|
505
|
+
- each transport stage remains state then ledger, followed by the core-owned
|
|
506
|
+
deferred/handoff boundary, then a best-effort domain event; its irreversible
|
|
507
|
+
progress is synchronized to the core immediately before those effects;
|
|
508
|
+
- native identity failure remains core quarantine/deferred marking, ledger,
|
|
509
|
+
state, event, log; generic uncertainty remains ledger, state, event before
|
|
510
|
+
core collateral stalling and presentation;
|
|
511
|
+
- final acceptance remains state, best-effort final ledger, then best-effort
|
|
512
|
+
event, so a lagging ledger cannot downgrade the strongest state receipt; and
|
|
513
|
+
- zero input remains deferred abort or ledger restore, raw rollback, best-effort
|
|
514
|
+
aborted state, the shared abort reducer, best-effort event, then domain log.
|
|
515
|
+
|
|
516
|
+
Direct fast proofs compare `Object.keys` and newline-terminated pretty JSON
|
|
517
|
+
bytes for the bridge state, prepared receipt, and final ledger. They also lock
|
|
518
|
+
the write sequences above, text-stage state/ledger/boundary failures carrying a
|
|
519
|
+
`TerminalInputNotStartedError` without being reclassified as zero input,
|
|
520
|
+
final-ledger failure behavior, immutable receipt history, and the intentional
|
|
521
|
+
authority difference where setup presentation uses the initially constructed
|
|
522
|
+
aborted receipt while transport presentation uses the reducer-reported receipt.
|
|
523
|
+
The owner map selects exactly recovery, receipt-fence, session-acceptance,
|
|
524
|
+
terminal-send, and Codex virgin-binding integration suites. Dispatch-authority
|
|
525
|
+
remains a core lock/authority boundary rather than an application owner.
|
|
526
|
+
|
|
527
|
+
### PR4C canonical dispatch transaction and execution seam
|
|
528
|
+
|
|
529
|
+
PR4C reuses the PR4B1 application seam as the only implementation of durable
|
|
530
|
+
dispatch ordering. Measured against exact head
|
|
531
|
+
`7a7987f038ac2d96f6c8dca22dcc07db4d8f1e6c`, it lowers `cli-core.ts` from
|
|
532
|
+
30,640 to 29,281 physical lines (-1,359). Total production grows from 76,649
|
|
533
|
+
to 77,792 lines (+1,143, 84.11 percent of the core reduction). The reviewed
|
|
534
|
+
increase beyond the iteration budget is the exact-resource repair: authentic
|
|
535
|
+
cross-Store state scopes, canonical terminal/writer key-value pairs, malformed
|
|
536
|
+
resources, raw-attach rollback, and
|
|
537
|
+
post-input Session/deferred writes now fail closed before their repository I/O.
|
|
538
|
+
The largest remaining dispatch entry stage is 477 lines with approximate
|
|
539
|
+
complexity 34;
|
|
540
|
+
all new and split functions remain below 500 lines and complexity 50.
|
|
541
|
+
|
|
542
|
+
Ordinary terminal dispatch now acquires the canonical terminal resource, then
|
|
543
|
+
the exact Store writer, and derives any Turn-state scope from that same live
|
|
544
|
+
transaction. The state callback is awaited and the capability expires when it
|
|
545
|
+
returns. Both the dynamic send path and the static writer/state helper reject a
|
|
546
|
+
wrong Store, wrong event log, mixed transaction, released scope, or forged
|
|
547
|
+
resource before lock acquisition or filesystem I/O. Application repositories
|
|
548
|
+
consume those exact active capabilities for every state, ledger, event, and
|
|
549
|
+
rollback operation; they accept no free Store, path, terminal, or lock handle.
|
|
550
|
+
|
|
551
|
+
`terminal-dispatch-execution.ts` owns preflight, transport lifecycle, native
|
|
552
|
+
identity, acceptance, and authority orchestration behind five typed port
|
|
553
|
+
groups: clock, native observation, acceptance, terminal proof, and Turn
|
|
554
|
+
authority. Codex anchor capture/detection and Claude transcript detection are
|
|
555
|
+
implemented by the core-owned adapter; the service has no filesystem, Store,
|
|
556
|
+
raw-lock, public-JSON presenter, or concrete terminal-bridge dependency. Its
|
|
557
|
+
direct fake-port tables lock short-circuit order, exactly one Enter stage,
|
|
558
|
+
before/after-text failure classification, late acceptance and bounded pending
|
|
559
|
+
results, native identity outcomes, and Turn revalidation.
|
|
560
|
+
|
|
561
|
+
Raw terminal input, public CLI/OpenClaw JSON, acceptance adapter construction,
|
|
562
|
+
and authority composition remain in `cli-core.ts`. At the PR4C slice, the
|
|
563
|
+
82-line `terminal-dispatch-composition.ts` file was explicitly recorded as a
|
|
564
|
+
temporary CLI-infrastructure type bridge owned by `terminal-dispatch-core`,
|
|
565
|
+
not an application service: it still named a concrete resolved terminal type
|
|
566
|
+
and the legacy `Record<string, any>` options bag, with PR7 assigned to remove
|
|
567
|
+
that leakage while moving the remaining facade.
|
|
568
|
+
|
|
569
|
+
The final PR7 decision keeps `TerminalDispatchTerminal` as a structural
|
|
570
|
+
CLI-infrastructure carrier only and eliminates the untyped options bag through
|
|
571
|
+
the six-field, unknown-valued `TerminalControlSendOptions` boundary. Business
|
|
572
|
+
services still receive explicit terminal fact projections, authenticated
|
|
573
|
+
routes, repositories, and typed ports; neither the structural carrier nor the
|
|
574
|
+
CLI options object crosses an execution, application, capability, or deferred
|
|
575
|
+
foreground service boundary.
|
|
576
|
+
|
|
577
|
+
The `terminal-dispatch-application` owner retains exactly five affected
|
|
578
|
+
integration witnesses: Codex no-rollout binding, dispatch recovery, receipt
|
|
579
|
+
fences, session acceptance, and terminal send gates. Focused direct tables also
|
|
580
|
+
prove the canonical resource identities and the preserved PR4B1 durable write
|
|
581
|
+
and error-priority sequences without introducing a second state machine.
|
|
582
|
+
|
|
583
|
+
## Immutable public and safety contracts
|
|
584
|
+
|
|
585
|
+
The refactor must preserve all of the following unless a separate product issue
|
|
586
|
+
explicitly approves a change.
|
|
587
|
+
|
|
588
|
+
### Public surfaces
|
|
589
|
+
|
|
590
|
+
- npm package `@scotthuang/agent-knock-knock` and executable
|
|
591
|
+
`agent-knock-knock`.
|
|
592
|
+
- Imported facade functions `parseCliCommand` and `executeCliCommand`, including
|
|
593
|
+
per-execution dependency isolation.
|
|
594
|
+
- Existing CLI command names, aliases, arguments, JSON field meanings, stdout,
|
|
595
|
+
and exit behavior. This includes `delegate`, `list`, `status`, `send`,
|
|
596
|
+
`new-thread`/`clear-thread`, `list-resumable-threads`/`threads`,
|
|
597
|
+
`native-inspect`/`native-status`, `resume-thread`, `reconcile-binding`,
|
|
598
|
+
`respond`, `approve`, `cancel`, `renew`, `reconcile-monitors`, `close`,
|
|
599
|
+
`transcript`, `install-openclaw`, `doctor`, `callback`, `retry-callback`, and
|
|
600
|
+
the internal `monitor` entrypoint.
|
|
601
|
+
- OpenClaw plugin id `agent-knock-knock`, `/akk`, and these 14 tool names:
|
|
602
|
+
`agent_knock_knock_list`, `agent_knock_knock_list_resumable_threads`,
|
|
603
|
+
`agent_knock_knock_native_inspect`, `agent_knock_knock_new_thread`,
|
|
604
|
+
`agent_knock_knock_reconcile_binding`, `agent_knock_knock_resume_thread`,
|
|
605
|
+
`agent_knock_knock_status`, `agent_knock_knock_send`,
|
|
606
|
+
`agent_knock_knock_respond`, `agent_knock_knock_renew`,
|
|
607
|
+
`agent_knock_knock_retry_callback`, `agent_knock_knock_cancel`,
|
|
608
|
+
`agent_knock_knock_close`, and `agent_knock_knock_approve`.
|
|
609
|
+
- The machine-readable `list` action contract, prefilled arguments, selectors,
|
|
610
|
+
and token semantics used by both CLI and OpenClaw.
|
|
611
|
+
- tmux and exact-version Herdr support, plus current Codex and Claude adapter
|
|
612
|
+
compatibility behavior.
|
|
613
|
+
|
|
614
|
+
### Persistence and recovery
|
|
615
|
+
|
|
616
|
+
- Current and retained legacy Store readability/migration, including Store
|
|
617
|
+
format 1, writer protocol 5, and Session-authority protocol 3 behavior.
|
|
618
|
+
- Existing Session, Turn, native-transition, deferred-transfer, dispatch-ledger,
|
|
619
|
+
callback-outbox, and event schemas and their on-disk identities.
|
|
620
|
+
- Monotonic Session/transition/transfer revisions, binding-generation CAS, and
|
|
621
|
+
crash recovery.
|
|
622
|
+
- Idempotent message, dispatch, completion, and callback identities.
|
|
623
|
+
- Strict Store, Session, Turn, terminal-incarnation, and OpenClaw-session
|
|
624
|
+
isolation.
|
|
625
|
+
|
|
626
|
+
### Terminal safety
|
|
627
|
+
|
|
628
|
+
- Full native UUID and process-incarnation authority; complete Codex rollout
|
|
629
|
+
identity where required.
|
|
630
|
+
- Fresh snapshot, candidate, binding, handoff, approval, and terminal tokens.
|
|
631
|
+
- Endpoint, route, pane/resource, PID/process-birth, cwd/workspace, owner,
|
|
632
|
+
approval, idle, and composer fences.
|
|
633
|
+
- `prepared -> text_injected -> enter_dispatched -> agent_accepted` evidence;
|
|
634
|
+
exactly one Enter after exact composer proof.
|
|
635
|
+
- No blind retry after possible input, uncertain submission, uncertain approval,
|
|
636
|
+
or uncertain lifecycle transition.
|
|
637
|
+
- Human input and explicit handoff remain higher priority than stale automation.
|
|
638
|
+
- `list` remains read-only unless reconciliation was explicitly requested.
|
|
639
|
+
- AKK never starts a coding-agent process.
|
|
640
|
+
|
|
641
|
+
## Milestones and PR gates
|
|
642
|
+
|
|
643
|
+
Each milestone is independently reviewable and behavior-preserving. Later work
|
|
644
|
+
does not need to wait for every cleanup within an earlier module, but it may not
|
|
645
|
+
bypass an unfinished safety boundary.
|
|
646
|
+
|
|
647
|
+
1. **PR0 — baseline and architecture**: this document, machine-readable
|
|
648
|
+
measurements, current ownership and contract inventory.
|
|
649
|
+
2. **PR1 — terminal observation and binding authority**: extract the shared pure
|
|
650
|
+
exact-binding decision first while list and mutation each retain fresh,
|
|
651
|
+
purpose-built observations and mutation revalidation.
|
|
652
|
+
3. **PR2 — verified-dead agent and orphan-turn policy**: one pure decision source
|
|
653
|
+
shared by managed close, startup reconciliation, and the direct monitor; keep
|
|
654
|
+
process, transcript, Store, terminal, and callback I/O in their existing shell.
|
|
655
|
+
4. **PR3 — repositories and transaction kernel**: typed codecs/ports, lock
|
|
656
|
+
capabilities, durable write maps; initially preserve legacy ordering where a
|
|
657
|
+
documented exception requires it.
|
|
658
|
+
5. **PR4 — dispatch service**: send/respond/approve/cancel transaction phases and
|
|
659
|
+
acceptance evidence behind the stable facade.
|
|
660
|
+
6. **PR5 — lifecycle service**: new/resume/adopt/reconcile reducer and bounded I/O
|
|
661
|
+
shell, including deferred foreground transfer recovery.
|
|
662
|
+
7. **PR6 — callback/outbox and monitor/reconciliation services**: extract these
|
|
663
|
+
as separate reviewable commits behind their existing durable boundaries;
|
|
664
|
+
callback preparation/settlement and monitor polling remain distinct services.
|
|
665
|
+
8. **PR7 — typed facade and secondary cleanup**: finish the command registry,
|
|
666
|
+
keep only stable facade exports in `cli-core.ts`, split remaining OpenClaw
|
|
667
|
+
adapter glue, and remove only compatibility shims proven dead by tests.
|
|
668
|
+
|
|
669
|
+
Every PR records before/after metrics, responsibility movement, dependency
|
|
670
|
+
edges, lock order, durable write points, and the focused tests that protect the
|
|
671
|
+
moved boundary. Every production function must stay strictly below 500
|
|
672
|
+
physical lines and approximate complexity 50; reaching either boundary fails
|
|
673
|
+
the zero-allowlist hard gate. The normal target is under 100 lines and
|
|
674
|
+
complexity under 20.
|
|
675
|
+
|
|
676
|
+
The completion target remains:
|
|
677
|
+
|
|
678
|
+
- `cli-core.ts` at or below 8,000 physical lines and acting only as facade/router;
|
|
679
|
+
- no `Record<string, any>` or implicit `any` in new service APIs;
|
|
680
|
+
- no direct lock acquisition or JSON persistence in orchestration services;
|
|
681
|
+
- one authority/action decision source;
|
|
682
|
+
- zero production import cycles;
|
|
683
|
+
- unchanged black-box public contracts and full release gate.
|
|
684
|
+
|
|
685
|
+
## Phase 1 review snapshot
|
|
686
|
+
|
|
687
|
+
This branch is the first bounded delivery for issue #126, not the completion of
|
|
688
|
+
the issue. It establishes enforceable architecture constraints and moves a set
|
|
689
|
+
of behavior-preserving decisions behind typed seams. The dispatch-service
|
|
690
|
+
experiment was explicitly retracted when review found that it owned CLI and
|
|
691
|
+
OpenClaw presentation. PR4 through PR7 therefore remain open work, and this
|
|
692
|
+
phase must not close issue #126.
|
|
693
|
+
|
|
694
|
+
Measured against `main@ea592a8` on 2026-08-14:
|
|
695
|
+
|
|
696
|
+
| Metric | Baseline | Phase 1 | Delta |
|
|
697
|
+
| --- | ---: | ---: | ---: |
|
|
698
|
+
| Production physical LOC | 73,792 | 75,848 | +2,056 (+2.79%) |
|
|
699
|
+
| `src/cli-core.ts` physical LOC | 38,005 | 35,608 | -2,397 (-6.31%) |
|
|
700
|
+
| `cli-core.ts` production share | 51.5% | 46.95% | -4.55 pp |
|
|
701
|
+
| Production modules | 38 | 52 | +14 |
|
|
702
|
+
| Production import edges / cycles | 95 / 0 | 130 / 0 | +35 / 0 |
|
|
703
|
+
| Functions over 100 / 200 / 500 LOC | 167 / 57 / 9 | 164 / 58 / 9 | -3 / +1 / 0 |
|
|
704
|
+
| Approximate complexity over 20 | 150 | 143 | -7 |
|
|
705
|
+
| Test TypeScript physical LOC | 71,902 | 76,108 | +4,206 (+5.85%) |
|
|
706
|
+
| Test TypeScript files | 71 | 86 | +15 |
|
|
707
|
+
|
|
708
|
+
The result is a reduction in orchestration risk concentration, not a reduction
|
|
709
|
+
in total code size. The exact `cli-core.ts` and production totals are ratcheted
|
|
710
|
+
in `config/production-module-ownership.json`; later phases must reduce them
|
|
711
|
+
rather than conceal extraction overhead. The focused test loop remains about
|
|
712
|
+
ten seconds, while the real-process integration tier remains the dominant
|
|
713
|
+
delivery cost.
|
|
714
|
+
|
|
715
|
+
### Responsibility and dependency movement
|
|
716
|
+
|
|
717
|
+
| Seam | Responsibility moved inward | I/O, locks, and durable effects deliberately retained outside | Focused proof |
|
|
718
|
+
| --- | --- | --- | --- |
|
|
719
|
+
| Terminal binding authority | Exact binding-match decisions and typed list/mutation observations | Fresh terminal/process sampling and mutation revalidation remain in `cli-core.ts` | authority table tests plus list, lifecycle, handoff, and send integration |
|
|
720
|
+
| Verified-dead agent policy | Process-death proof validation, event replay, stall eligibility, completion tri-state | Process/transcript probes and terminal -> writer -> state orchestration remain in the shell | Codex/Claude completion-wins, fail-closed, deferred-transfer, and crash-replay tests |
|
|
721
|
+
| Canonical mutation kernel | Canonical acquisition/release plus fresh resource-bound terminal, writer, and optional state capabilities for four migrated paths | Business write ordering and raw filesystem/JSON adapters remain in composition | authenticity, lifetime, wrong-resource, cross-transaction, lock-order, error-precedence, and control-lock tests |
|
|
722
|
+
| Dispatch policy, zero-input abort reducer, and ledger codec | Pure preflight/abort precedence plus v1/v2 decode, construction, receipt merge, and validation | Ledger path selection, no-follow reads, atomic rename/fsync, Store locks, terminal input, and CLI formatting remain in the shell | reducer tables, codec byte/order tests, replay, receipt-fence, send-gate, and recovery tests; codec changes select the full tier |
|
|
723
|
+
| Lifecycle transition policy | Candidate/target classification and transition phase reduction | Terminal observation, transition CAS, deferred transfer, input, and recovery writes remain in the shell | transition tables and lifecycle/recovery integration |
|
|
724
|
+
| Callback policy, transport, and settlement | Retry decisions; Gateway process adapter; delivery progress/success/failure settlement | CLI composition owns the clock, state transaction, retry launcher, output, and callback preparation | retry matrix, exact transport call ordering, settlement write-order tests, and callback integration |
|
|
725
|
+
| Monitor seams | Approval clearing/suppression/notification, activity/completion/death/timeout decisions, fingerprint facts, and launch/ownership plans | Poll I/O, supervision process management, state/event writes, callback preparation, and terminal locks remain in the shell | decision/poll/launch tables and monitor recovery/lifecycle/approval integration |
|
|
726
|
+
| Terminal list renderer | Pure managed-Turn and action-contract projection from sampled facts | Store, process, ledger, Session, approval, and token observations remain in `cli-core.ts`; mutation never consumes list authority | exact v16 action order plus list/session/handoff integration |
|
|
727
|
+
| Conversation trace | Bounded executor-log parsing, secret redaction, and monitor-event projection | Status routing and conversation/event loading remain in `cli-core.ts`; the module performs only the existing optional read of the selected output log | exact parser/redaction/fallback unit tests plus management CLI integration |
|
|
728
|
+
| CLI runtime context | Per-execution dependency, output, clock, sleep, exit, and logging context | No business policy or persistent state moved into the runtime | nested and concurrent async-context isolation tests |
|
|
729
|
+
| Install and doctor adapters | OpenClaw plugin install/configure/restart/verify ordering plus typed doctor report composition | The shared CLI command runtime retains PATH/HOME lookup, package-root resolution, output redaction, and async-local exit/output authority; terminal, lifecycle, and dispatch logic are not imported | direct argv/effect-order, exact JSON bytes/key-order, exit-code, PATH/HOME isolation, and retained CLI boundary tests |
|
|
730
|
+
|
|
731
|
+
The new compile-time direction is
|
|
732
|
+
`cli-core composition -> callback settlement -> callback policy`, while the
|
|
733
|
+
OpenClaw child-process transport independently depends on the callback policy's
|
|
734
|
+
delivery outcome type. Settlement does not import the transport adapter or CLI
|
|
735
|
+
runtime.
|
|
736
|
+
|
|
737
|
+
### Lock and durable-write parity
|
|
738
|
+
|
|
739
|
+
No Store, Session, transition, dispatch-ledger, callback-outbox, or public
|
|
740
|
+
protocol version changes in Phase 1. The extraction keeps the existing lock
|
|
741
|
+
scope and durable ordering at each migrated call site. In particular:
|
|
742
|
+
|
|
743
|
+
- verified-dead reconciliation continues to acquire terminal dispatch lock,
|
|
744
|
+
Store writer lease, then conversation state lock; callback execution stays
|
|
745
|
+
outside those locks;
|
|
746
|
+
- callback settlement still executes progress as load -> save -> event,
|
|
747
|
+
success as load -> save -> event, and failure as load -> retry-monitor launch
|
|
748
|
+
-> save -> failure event -> monitor event;
|
|
749
|
+
- terminal dispatch still records prepared state/ledger/evidence before input,
|
|
750
|
+
preserves `text_injected -> enter_dispatched -> agent_accepted`, and never
|
|
751
|
+
retries an uncertain input;
|
|
752
|
+
- lifecycle transition and deferred-transfer CAS/write/crash boundaries remain
|
|
753
|
+
in their original shell; and
|
|
754
|
+
- dispatch-ledger filesystem open/no-follow, temporary write, fsync, rename,
|
|
755
|
+
directory fsync, and cleanup behavior was not moved into a generic repository.
|
|
756
|
+
|
|
757
|
+
The Phase 1 review gate is architecture validation, typecheck/build, focused
|
|
758
|
+
policy and adapter tests, and one exact-head full test run. Packaging,
|
|
759
|
+
publishing, installation, protocol upgrades, and issue closure are not part of
|
|
760
|
+
this phase.
|
|
761
|
+
|
|
762
|
+
### Reproducible refactor evidence guard
|
|
763
|
+
|
|
764
|
+
Run the local, non-integration evidence gate with:
|
|
765
|
+
|
|
766
|
+
```sh
|
|
767
|
+
npm run validate:refactor-evidence
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
`config/refactor-test-evidence.json` freezes two review inputs. First, it counts
|
|
771
|
+
static subprocess-startup call sites in `test/**/*.ts` for the immutable
|
|
772
|
+
`v0.12.11` baseline and the current tree. The included metric is CLI-process
|
|
773
|
+
plus fake-Node-process startup sites; other adapter/process calls are reported
|
|
774
|
+
separately. This is a deterministic source metric, not a claim about dynamic
|
|
775
|
+
process executions in one test run. The initial eight callback cases, the CLI
|
|
776
|
+
UX, native-ownership, management, selector, Session-binding, deterministic
|
|
777
|
+
dispatch-admission, and 20 normal callback invocations now use the imported
|
|
778
|
+
command service. The multilingual composer not-accepted witness now uses the
|
|
779
|
+
same imported command service while retaining the real tmux adapter and its
|
|
780
|
+
exactly-one-Enter assertion. The final slice also imports redundant callback,
|
|
781
|
+
installer, verifier/guard, Claude recovery, and nested approval wrappers. The
|
|
782
|
+
product-test value is now 19 of 48 baseline sites, a 60.42% reduction, and its
|
|
783
|
+
`final_threshold.required` flag is `true`. Measurement self-tests are reported
|
|
784
|
+
separately (baseline zero; current ten included fake-Node probes) under one
|
|
785
|
+
fixed diagnostic path applied to both revisions; they cannot dilute the
|
|
786
|
+
product migration ratio.
|
|
787
|
+
|
|
788
|
+
Second, the manifest freezes the exact changed paths and subjects of ten
|
|
789
|
+
pre-`v0.12.11` product/test commits and replays them through the current
|
|
790
|
+
affected-test selector. Eight changes now select owned integration witnesses;
|
|
791
|
+
the two commits that changed exact `src/store.ts` authority remain full. The
|
|
792
|
+
measured fallback is therefore 2 of 10 (20%), meeting the completion target.
|
|
793
|
+
Every normal production domain is capped at five integration witnesses, while
|
|
794
|
+
unknown paths, `src/store.ts`, `src/protocol.ts`, and shared kernels remain
|
|
795
|
+
full. Known test helpers resolve through an explicit transitive consumer map.
|
|
796
|
+
Tier-manifest additions and synchronized package-version bumps narrow only from
|
|
797
|
+
Git parent/current blob proof; deletion, movement, reordering, dependency
|
|
798
|
+
changes, or an unproved caller object fail closed. The validator fails if Git
|
|
799
|
+
history, a frozen path list, the measured count, or a replay result drifts, and
|
|
800
|
+
`affected_selector_replay.final_threshold.required` is now `true`.
|
|
801
|
+
|
|
802
|
+
`config/public-contract-witnesses.json` is the machine-readable compatibility
|
|
803
|
+
inventory. It pins the package executable and facade, CLI commands/JSON
|
|
804
|
+
witnesses, list action contract v16, all 14 OpenClaw tools, Store format 1 and
|
|
805
|
+
writer protocols 1 through 5, and eleven mappings from old executable tests to
|
|
806
|
+
focused service invariants and retained boundary witnesses. Every authority and
|
|
807
|
+
witness path must exist, each witness must remain in its declared test tier and
|
|
808
|
+
contain its named assertion, and unknown or missing manifest fields fail
|
|
809
|
+
closed.
|
|
810
|
+
|
|
811
|
+
`npm run validate:architecture` invokes the same evidence guard after the
|
|
812
|
+
ownership/import/LOC checks. Intentional contract or evidence changes therefore
|
|
813
|
+
require a reviewed manifest diff; changing only a number to conceal a failed
|
|
814
|
+
measurement does not pass because the validator reproduces it from source and
|
|
815
|
+
Git history.
|
|
816
|
+
|
|
817
|
+
### Codex no-rollout process-contract consolidation
|
|
818
|
+
|
|
819
|
+
The canonical integration witness
|
|
820
|
+
`test/codex-no-rollout-binding-cli.test.ts` declares 102 named
|
|
821
|
+
tests with their original assertions. `config/test-file-shards.json` assigns
|
|
822
|
+
every declaration to exactly one of eight worker entrypoints. Test-tier
|
|
823
|
+
selection, production ownership, affected-test selection, public-contract
|
|
824
|
+
evidence, and dynamic subprocess evidence continue to name the canonical path;
|
|
825
|
+
the tier runner expands that one path to every compiled shard and fails closed
|
|
826
|
+
for a missing, duplicate, unused, out-of-range, or uncompiled shard. A targeted
|
|
827
|
+
canonical selection also rejects a shard query that does not match its actual
|
|
828
|
+
worker entry, so it can never execute only a subset while claiming the whole
|
|
829
|
+
witness.
|
|
830
|
+
|
|
831
|
+
Repeated executable invocations now use the same imported parser/command
|
|
832
|
+
boundary and fixture-scoped virtual clock as the surrounding invariant tests.
|
|
833
|
+
For injected exit checkpoints, the fixture freezes the exact durable filesystem
|
|
834
|
+
image at `cliExit`, rewrites active lock ownership to the simulated dead CLI
|
|
835
|
+
PID, and restores files without changing surviving rollout inodes before the
|
|
836
|
+
next recovery command. Ordinary exception compensation after the injected exit
|
|
837
|
+
therefore cannot forge the crash state, while recovery still proves lock
|
|
838
|
+
reclamation, descriptor identity, exact CAS state, and zero replay.
|
|
839
|
+
|
|
840
|
+
| Former repeated executable role | Same retained invariant | Authoritative real-process witness |
|
|
841
|
+
| --- | --- | --- |
|
|
842
|
+
| Virgin attach, terminal send, and status variants | Exact parser/command routing, terminal text plus one Enter, acceptance binding, and no Store mutation | `doctor exits non-zero when required package files are missing` in `cli-ux.test.ts` retains argv/exit; `raw background send durably prepares its terminal submission before tmux accepts it` in the composer-replay shard retains real terminal-adapter input |
|
|
843
|
+
| Deferred preparation, commit, acceptance-backfill, and recovery crash variants | Exact durable image at every named `cliExit(86)` checkpoint; subsequent recovery retains Session/Turn/ledger/transfer state and never replays input | `zero-input deferred source Session reservation before its transfer receipt recovery aborts safely before one refreshed retry` retains the real Store crash and exit-86 boundary used by dynamic evidence |
|
|
844
|
+
| Startup candidate-monitor reconciliation | Exact pending Turn is accepted and completed once, its transfer and dispatch ledger resolve, and no callback state appears | `startup reconciliation relaunches one pending candidate monitor without replay` retains detached monitor PID launch, liveness, and process exit |
|
|
845
|
+
|
|
846
|
+
The no-rollout suite retains two explicit `runCliSubprocess` call sites for its
|
|
847
|
+
unique Store-crash and detached-monitor process boundaries. Consolidation does not
|
|
848
|
+
shorten a production timeout, raise test concurrency, remove a test or
|
|
849
|
+
assertion, or replace the separate OpenClaw callback process boundaries.
|
|
850
|
+
|
|
851
|
+
## Callback/outbox application service
|
|
852
|
+
|
|
853
|
+
The callback milestone now has one typed application boundary for generic
|
|
854
|
+
callback preparation and execution, retry classification and monitoring,
|
|
855
|
+
startup reconciliation, terminal-completion outbox preparation, and approval
|
|
856
|
+
notification outbox preparation. The service composes the existing pure retry
|
|
857
|
+
policy, OpenClaw delivery contract, and settlement service; it does not import
|
|
858
|
+
`cli-core.ts`, filesystem or process adapters, CLI presentation, or raw locks.
|
|
859
|
+
The OpenClaw child-process transport implements the policy-owned delivery
|
|
860
|
+
contract rather than exporting an infrastructure type back into the service.
|
|
861
|
+
|
|
862
|
+
Measured against its exact pre-extraction head, this vertical moves 1,133
|
|
863
|
+
physical lines out of `cli-core.ts` while adding 387 physical production lines
|
|
864
|
+
overall. The reviewed overhead is the explicit typed port/result surface and
|
|
865
|
+
the direct service boundary; it is not hidden by unrelated cleanup or compact
|
|
866
|
+
formatting. The hard maxima are 396 physical lines and approximate complexity
|
|
867
|
+
32, below the 500/50 gates. The preparation span (277/32, including its nested
|
|
868
|
+
persistence phase), persistence phase (145/30), reconciliation callback
|
|
869
|
+
(129/20), and terminal-completion preparation (131/8) remain reviewed
|
|
870
|
+
exceptions to the default 100/20 target so their durable short-circuit and write
|
|
871
|
+
order stays visible. The production import graph remains acyclic.
|
|
872
|
+
|
|
873
|
+
The composition root still owns terminal and Store-writer locks, state-lock
|
|
874
|
+
implementation, Store/path resolution, JSON/event persistence adapters, retry
|
|
875
|
+
process launch, clock/process observation, Gateway transport construction, and
|
|
876
|
+
all public JSON. Terminal completion preserves state-lock scope across claim,
|
|
877
|
+
detected/message/outbox writes, and the record-only crash checkpoint, releases
|
|
878
|
+
that lock before settling the terminal dispatch ledger, and never replays
|
|
879
|
+
terminal input. Approval persistence still records the stable message id and
|
|
880
|
+
timestamp before invoking the service; the service either prepares that exact
|
|
881
|
+
message id or returns the same message without an outbox when no Gateway route
|
|
882
|
+
exists. Delivery settlement retains progress `load -> save -> event`, success
|
|
883
|
+
`load -> save -> event`, and failure `load -> retry-monitor -> save -> events`
|
|
884
|
+
ordering through the existing settlement service.
|
|
885
|
+
|
|
886
|
+
Direct fast proofs cover fresh/duplicate/non-retryable outbox preparation,
|
|
887
|
+
completion claim success/conflict and lock release, stable approval identity,
|
|
888
|
+
and the no-Gateway branch. Existing policy, settlement, transport, callback,
|
|
889
|
+
Claude, approval, monitor lifecycle, monitor recovery, and OpenClaw contract
|
|
890
|
+
witnesses remain the black-box boundary set.
|
|
891
|
+
|
|
892
|
+
## Terminal monitor decision policy
|
|
893
|
+
|
|
894
|
+
The monitor decision milestone moves one pure policy boundary out of the CLI
|
|
895
|
+
composition root. It owns completion-first poll reduction, approval prompt
|
|
896
|
+
clearing, question/error classification, every consumed-prompt suppression,
|
|
897
|
+
verified-dead completion classification, post-effect timeout classification,
|
|
898
|
+
activity cadence, and stable approval/activity/screen identity facts. It
|
|
899
|
+
directly composes the existing poll and verified-dead policies and performs no
|
|
900
|
+
I/O, locking, process access, callback delivery, or CLI presentation.
|
|
901
|
+
|
|
902
|
+
Measured against exact head `e62a79cc94428ddb9a5c264600f259ca4d05ee0c`,
|
|
903
|
+
the extraction reduces `src/cli-core.ts` from 32,398 to 32,146 physical lines
|
|
904
|
+
(-252) and changes total production TypeScript from 75,934 to 76,076 (+142).
|
|
905
|
+
The 42-line excess over the preferred +100 budget is the reviewed, explicit
|
|
906
|
+
typed decision surface and direct proofability; no formatting compression or
|
|
907
|
+
unrelated responsibility movement is used. The 394-line module remains below
|
|
908
|
+
the 500-line hard boundary, every new function remains below 100 physical
|
|
909
|
+
lines, and the hard approximate-complexity maximum is 27. The approval reducer
|
|
910
|
+
(67/27) and consumed-approval classifier (58/23) are transparent exceptions to
|
|
911
|
+
the default complexity-20 target: their branch tables stay cohesive and direct
|
|
912
|
+
tests lock every precedence path.
|
|
913
|
+
|
|
914
|
+
The composition root still owns terminal singleton, Store-writer and state
|
|
915
|
+
locks; terminal observation and input adapters; process launch and death
|
|
916
|
+
probing; state/event/outbox writes; callback continuation; clocks and sleeping;
|
|
917
|
+
and public JSON/log presentation. Approval effects retain their asymmetric
|
|
918
|
+
durable order: question follows `fingerprint -> event -> record`, while an
|
|
919
|
+
unapprovable or evidence error follows `event -> fingerprint -> record`.
|
|
920
|
+
Polling retains `activity -> completion -> verified-dead -> fresh clock ->
|
|
921
|
+
timeout`, so work performed by persistence or the death probe can cross a
|
|
922
|
+
deadline without deferring the timeout by one poll. Application orchestration
|
|
923
|
+
and those effect ports remain the follow-on monitor service milestone.
|
|
924
|
+
|
|
925
|
+
## Terminal monitor application service
|
|
926
|
+
|
|
927
|
+
The monitor application milestone moves the singleton-owned retry loop and the
|
|
928
|
+
complete locked monitor state machine behind five typed port groups: state,
|
|
929
|
+
authority, callbacks, runtime, and presentation. The service owns initialization,
|
|
930
|
+
submission reconciliation, binding deferral, observation application, approval
|
|
931
|
+
continuation, activity persistence, stable completion, verified-dead fallback,
|
|
932
|
+
and timeout routing. It composes the canonical monitor decision and poll policies;
|
|
933
|
+
it does not import `cli-core.ts`, filesystem or process modules, raw lock or JSON
|
|
934
|
+
persistence implementations, a callback transport, or a public JSON presenter.
|
|
935
|
+
|
|
936
|
+
Measured against exact head
|
|
937
|
+
`b637c012cfa87315380c150405a3384d653ac847`, the extraction reduces
|
|
938
|
+
`src/cli-core.ts` from 28,336 to 27,319 physical lines (-1,017). Total
|
|
939
|
+
production TypeScript changes from 79,308 to 80,554 lines (+1,246, 122.52
|
|
940
|
+
percent of the core reduction). The transparent overhead is the 1,583-line
|
|
941
|
+
typed application boundary, the 680-line CLI adapter and presenter boundary,
|
|
942
|
+
and their direct trace types; no unrelated deletion or compressed formatting is
|
|
943
|
+
used to hide that cost. Every new function remains within the preferred
|
|
944
|
+
100-line/complexity-20 target. The largest is the 98-line/c20 public-result
|
|
945
|
+
presenter; the largest service function is the 89-line/c11 approval application,
|
|
946
|
+
and the service complexity maximum is c13. The production import graph remains
|
|
947
|
+
acyclic.
|
|
948
|
+
|
|
949
|
+
`cli-core.ts` still resolves the exact state and event paths, acquires the
|
|
950
|
+
singleton owner, and supplies the concrete terminal, Store-writer and Turn-state
|
|
951
|
+
lock functions. It also supplies state/event/ledger repositories, live process
|
|
952
|
+
and death probes, terminal observation, callback transport construction, clock
|
|
953
|
+
and crash hooks, and the public JSON/log writer. The CLI adapter accepts only
|
|
954
|
+
those invocation-local capabilities, applies them in the legacy lock order, and
|
|
955
|
+
cannot manufacture a path, Store, terminal route, or lock.
|
|
956
|
+
|
|
957
|
+
The application order remains `initialize -> submission reconciliation -> poll
|
|
958
|
+
-> detector/approval -> activity -> stable completion -> independent verified
|
|
959
|
+
death -> fresh clock -> timeout`. A completion persisted immediately before
|
|
960
|
+
process exit therefore still wins over orphan cleanup, and work performed by a
|
|
961
|
+
death probe can cross a deadline without postponing timeout classification by
|
|
962
|
+
one poll. Approval effects keep their intentional asymmetry: question is
|
|
963
|
+
`fingerprint -> event -> record`, while an unapprovable/evidence error is
|
|
964
|
+
`event -> fingerprint -> record`. Stale notifications sleep and retry without
|
|
965
|
+
callback execution; duplicates present without delivery; a consumed question
|
|
966
|
+
callback resumes the same generation; callback and completion claims remain
|
|
967
|
+
outside the Turn-state lock exactly as before.
|
|
968
|
+
|
|
969
|
+
Direct fast traces prove live-dispatcher PID gating before terminal I/O, two-poll
|
|
970
|
+
completion stability, exactly one status/screen snapshot per poll with the legacy
|
|
971
|
+
completion-metadata read order, death-before-fresh-clock ordering, both approval
|
|
972
|
+
effect orders, executor-to-callback actor mapping, prepared-recovery release
|
|
973
|
+
order (`state -> writer -> terminal`), and zero terminal I/O on a fresh-state
|
|
974
|
+
retry. Acceptance errors and not-accepted/fenced presentations remain inside
|
|
975
|
+
the terminal send lock; pending acceptance releases that lock before backoff.
|
|
976
|
+
The retained lifecycle, approval and
|
|
977
|
+
recovery shards provide 21 executable boundary cases for singleton ownership,
|
|
978
|
+
Store-lock deferral, callback concurrency, detector diagnostics, durable
|
|
979
|
+
completion, verified death, timeout, duplicate settlement, handoff and monitor
|
|
980
|
+
relaunch behavior.
|
|
981
|
+
|
|
982
|
+
## Native-thread lifecycle query slice
|
|
983
|
+
|
|
984
|
+
The first native-thread lifecycle application slice moves only read-side
|
|
985
|
+
candidate discovery, active-owner observation, exact candidate-token
|
|
986
|
+
revalidation, restorable-origin eligibility, and previous-thread projection
|
|
987
|
+
behind `NativeThreadLifecycleQueryPorts`. New-thread and resume-thread mutation,
|
|
988
|
+
handoff, verified-empty recovery, reconciliation, dispatch recovery, selection
|
|
989
|
+
snapshot persistence, and public JSON presentation remain in `cli-core.ts`.
|
|
990
|
+
The query service has no transaction, lock, capability, Store-save, snapshot-save,
|
|
991
|
+
terminal-input, recovery, or presenter port.
|
|
992
|
+
|
|
993
|
+
Measured against exact head `ceb1e2fbb9ffa65af139182b36ea0bd527f4fe1e`,
|
|
994
|
+
the slice reduces `src/cli-core.ts` from 31,321 to 30,775 physical lines (-546)
|
|
995
|
+
and changes total production TypeScript from 76,474 to 76,569 (+95). The query
|
|
996
|
+
service is 495 physical lines. No function reaches 500 lines; architecture
|
|
997
|
+
validation retains the hard approximate-complexity ceiling of 50. The
|
|
998
|
+
production import graph remains acyclic and the module has one targeted
|
|
999
|
+
ownership domain, `native-thread-lifecycle-query`, with five retained lifecycle
|
|
1000
|
+
integration witnesses.
|
|
1001
|
+
|
|
1002
|
+
The default approximate-complexity target remains 20. The reviewed cohesive
|
|
1003
|
+
exceptions are `activeNativeThreadOwners` (93 LOC/c28),
|
|
1004
|
+
`verifiedPreviousResumeCandidate` (68 LOC/c24), and
|
|
1005
|
+
`decodeThreadCandidateToken` (38 LOC/c21); all remain below 100 LOC and c50.
|
|
1006
|
+
|
|
1007
|
+
The composition root implements the read port with frozen method-only adapters.
|
|
1008
|
+
It continues to own filesystem/process observation, terminal and agent adapters,
|
|
1009
|
+
Store path selection, selection snapshot writes, clock sampling, and public JSON.
|
|
1010
|
+
Store path selection is lazy and memoized at the first Store observation; token
|
|
1011
|
+
revalidation that fails before a Store read cannot resolve or inspect that path.
|
|
1012
|
+
Candidate observation preserves `active process ownership -> managed Session
|
|
1013
|
+
observation -> exact running version -> provider discovery`. Invalid UUID and
|
|
1014
|
+
Store-authority errors precede terminal scanning; an active external owner
|
|
1015
|
+
precedes managed-Session conflict observation. Version failure never calls the
|
|
1016
|
+
candidate provider. Candidate tokens retain baseline `JSON.stringify` byte and
|
|
1017
|
+
key-order semantics; no canonicalization was introduced. Their codec, candidate
|
|
1018
|
+
sorting, committed-previous policy, and pure snapshot assertions live in the
|
|
1019
|
+
adapter-neutral `native-thread-resume-snapshot-policy.ts`, so importing the
|
|
1020
|
+
query service cannot load snapshot filesystem persistence.
|
|
1021
|
+
|
|
1022
|
+
The direct fast table locks version short-circuit, observation order,
|
|
1023
|
+
deduplication and sorting, exact token mismatch precedence and bytes, Store then
|
|
1024
|
+
terminal ownership error priority, and one exact committed-transition read for
|
|
1025
|
+
the previous resume candidate. Snapshot assertion traces additionally lock lazy
|
|
1026
|
+
cwd and clock callbacks, terminal-evidence order, fingerprint-before-row
|
|
1027
|
+
short-circuiting, ordered-row equality, and rollout `JSON.stringify` field-order
|
|
1028
|
+
sensitivity. Since this slice writes nothing, it adds no durable-write or crash
|
|
1029
|
+
window; the existing core snapshot write and lifecycle mutation/recovery
|
|
1030
|
+
witnesses remain authoritative until the separate mutation application slice.
|
|
1031
|
+
|
|
1032
|
+
## Terminal monitor startup eligibility policy
|
|
1033
|
+
|
|
1034
|
+
Startup, handoff, and locked launch preparation now share one pure staged
|
|
1035
|
+
eligibility policy. The policy owns candidate priority and exact reason text for
|
|
1036
|
+
terminal-bridge identity, dispatch authority, blocking submission, runtime
|
|
1037
|
+
identity, deferred-transfer acceptance, and deadline metadata. Its generator
|
|
1038
|
+
yields only the next typed observation, so the CLI composition root does not
|
|
1039
|
+
touch terminal control, the dispatch ledger, Store path authority, runtime
|
|
1040
|
+
identity, or a deferred transfer until every earlier candidate has passed.
|
|
1041
|
+
The policy has no ports, filesystem or process access, locks, mutation, or CLI
|
|
1042
|
+
presentation.
|
|
1043
|
+
|
|
1044
|
+
Measured against exact head `8e5c636604845d42f4f0e0af28b36621974e75b6`,
|
|
1045
|
+
the extraction reduces `src/cli-core.ts` from 30,775 to 30,640 physical lines
|
|
1046
|
+
(-135) and changes total production TypeScript from 76,569 to 76,649 (+80).
|
|
1047
|
+
The new policy is 195 physical lines. Its 135-line staged reducer has approximate
|
|
1048
|
+
complexity 48: this is a reviewed transparent exception to the preferred 100/20 target,
|
|
1049
|
+
while remaining below the hard 500/50 gate. Keeping the precedence in one
|
|
1050
|
+
reducer makes every short circuit directly table-testable without concealing
|
|
1051
|
+
branches in I/O adapters. The shared, I/O-free `terminal-submission-facts.ts`
|
|
1052
|
+
owns the submission projection and typed Codex anchor codec; its 99-line
|
|
1053
|
+
validator has approximate complexity 49, a reviewed transparent exception to
|
|
1054
|
+
the preferred complexity-20 target and still below the hard gate. All other
|
|
1055
|
+
new functions are below 15 lines and complexity 5.
|
|
1056
|
+
|
|
1057
|
+
The composition root remains the sole owner of terminal-control decoding,
|
|
1058
|
+
dispatch-ledger and deferred-transfer reads, Store path derivation and symlink
|
|
1059
|
+
validation, runtime identity observation, locks, mutation, monitor launch, and
|
|
1060
|
+
public JSON/log presentation. Observation order remains `bridge/status ->
|
|
1061
|
+
message -> terminal control -> dispatch ledger -> conversation state path ->
|
|
1062
|
+
Store derivation -> submission -> runtime -> Store derivation -> deferred
|
|
1063
|
+
transfer -> deadline`. In particular, non-terminal and inactive candidates
|
|
1064
|
+
never derive a Store, while a malformed Store path still fails before an
|
|
1065
|
+
already-invalid dispatch ledger is classified, preserving the prior error
|
|
1066
|
+
precedence. Dispatch `state_path` is not observed until the earlier ledger,
|
|
1067
|
+
message, control, conversation, Session, and Turn predicates have passed.
|
|
1068
|
+
|
|
1069
|
+
## Native-thread transition verification and settlement
|
|
1070
|
+
|
|
1071
|
+
The second native-thread lifecycle slice moves the mutation's typed
|
|
1072
|
+
verification and settlement seam out of the CLI composition root. Before any
|
|
1073
|
+
durable transition is prepared, the verification adapter preserves lifecycle
|
|
1074
|
+
eligibility, plan selection, initial idle status, the exact Claude agents-row
|
|
1075
|
+
proof, and the single Codex `/status` probe. After core has durably recorded
|
|
1076
|
+
`command_submitted`, the settlement service owns stable identity verification,
|
|
1077
|
+
verified-transition persistence, the verified crash checkpoint, exclusive
|
|
1078
|
+
target ownership, Session commit, committed-transition persistence, resolved
|
|
1079
|
+
ledger persistence, and final presentation. Dispatch preparation, composer
|
|
1080
|
+
revalidation, terminal input, raw lock acquisition, recovery, handoff, and
|
|
1081
|
+
verified-empty reconciliation remain in `cli-core.ts`.
|
|
1082
|
+
|
|
1083
|
+
Measured against exact head `a96bfbb2c6d011e4bdbe53f883e01250ad1e4023`,
|
|
1084
|
+
the slice reduces `src/cli-core.ts` from 29,281 to 28,610 physical lines
|
|
1085
|
+
(-671) and changes total production TypeScript from 77,792 to 78,388 (+596).
|
|
1086
|
+
The transparent typed-capability overhead is 88.8% of the core movement. Issue
|
|
1087
|
+
#126 has no production-zero-growth requirement; the added lines are the five
|
|
1088
|
+
explicit port groups, exact verification adapter, capability-scoped repository
|
|
1089
|
+
surface, post-lock terminal/Store resource adapter, and reusable direct evidence
|
|
1090
|
+
rather than formatting compression or an unrelated responsibility move.
|
|
1091
|
+
|
|
1092
|
+
`runNativeThreadTransition` is 421 LOC/c1, with its transaction callback at
|
|
1093
|
+
412 LOC/c44. The settlement service is 331 physical lines; its largest function
|
|
1094
|
+
is `settleFailedNativeThreadTransition` at 124 LOC/c9. The verification adapter
|
|
1095
|
+
is 707 physical lines; its largest function is
|
|
1096
|
+
`verifyNativeThreadTransition` at 201 LOC/c45. Every function remains below the
|
|
1097
|
+
hard 500 LOC/c50 gates. Reviewed exceptions to the default 100 LOC/c20 target
|
|
1098
|
+
are the cohesive transaction wrapper/callback (421/c1 and 412/c44), core port
|
|
1099
|
+
wiring (173/c1), failure settlement (124/c9), verification polling state
|
|
1100
|
+
machine (201/c45), and shared known-root reducer (94/c24). Keeping these order
|
|
1101
|
+
tables intact makes their fail-closed precedence visible and directly testable.
|
|
1102
|
+
The 100-line resource adapter's exported operation is 77 LOC/c1 and its inner
|
|
1103
|
+
capability gate is 55 LOC/c14, so it requires no default-threshold exception.
|
|
1104
|
+
|
|
1105
|
+
The service imports no filesystem or path API, raw lock, Store directory,
|
|
1106
|
+
public JSON, terminal bridge, `any`, or `Record<string, any>`. Core still owns
|
|
1107
|
+
argv and public JSON, constructs concrete terminal and Store adapters, acquires
|
|
1108
|
+
terminal then writer locks, and invokes the presenter before leaving the
|
|
1109
|
+
transaction callback. Every service repository operation receives the same
|
|
1110
|
+
authentic `CanonicalMutationScopes` and `CanonicalMutationResources`; the
|
|
1111
|
+
capability-gated repositories bind every verification, ownership, transition,
|
|
1112
|
+
Session, and ledger operation to both locked resources. Before observation or
|
|
1113
|
+
I/O, the adapter verifies active scopes, the post-lock terminal's exact resource
|
|
1114
|
+
key and process incarnation, and the captured Store resolving to the active
|
|
1115
|
+
canonical writer. Lifecycle ledger
|
|
1116
|
+
construction and save form one scoped port; its `store_dir` must strictly equal
|
|
1117
|
+
the active writer Store, and persistence uses the post-lock fresh terminal route.
|
|
1118
|
+
The lifecycle resource adapter reuses the common mutation pair gate and
|
|
1119
|
+
`terminalRuntimeResourceKey`; it imports no terminal-dispatch domain module.
|
|
1120
|
+
Agent kind and PID come only from that resolved terminal and are absent from the
|
|
1121
|
+
service verification request.
|
|
1122
|
+
Lifecycle and dispatch compatibility exports share one adapter-neutral native
|
|
1123
|
+
identity fence, matcher, and strict complete-rollout predicate in
|
|
1124
|
+
`terminal-binding-authority.ts`. Blank or malformed runtime rollout fields fail
|
|
1125
|
+
closed before path comparison and cannot escape as a `TypeError`.
|
|
1126
|
+
|
|
1127
|
+
Verified success retains `verify -> verified transition -> crash hook ->
|
|
1128
|
+
ownership -> Session commit -> committed transition -> resolved ledger ->
|
|
1129
|
+
present`. Failure retains committed-bookkeeping error precedence, verified
|
|
1130
|
+
recovery without roll-forward, proven-zero-input abort plus source restoration,
|
|
1131
|
+
and possible-input uncertainty plus source quarantine. A five-case recording
|
|
1132
|
+
port table asserts those orders, exact scope/resource forwarding, and
|
|
1133
|
+
presentation before writer and terminal lock release. The no-rollout identity
|
|
1134
|
+
case separately proves that a legitimate status-card or pre-materialization
|
|
1135
|
+
observation returns false without reading a missing rollout or throwing. One
|
|
1136
|
+
targeted ownership domain retains five native lifecycle integration witnesses.
|
|
1137
|
+
Direct resource-adapter cases additionally prove moved-route fresh bytes and
|
|
1138
|
+
zero verification/ownership/ledger I/O for wrong incarnation, malformed or
|
|
1139
|
+
key-mismatched terminal/writer resources, captured-Store mismatch, and released
|
|
1140
|
+
scopes. Adapter cases pin Codex probe/companion ordering, Claude rows-before-status
|
|
1141
|
+
ordering, and the no-revalidation callback's original synchronous invocation.
|
|
1142
|
+
|
|
1143
|
+
## Terminal list and action authority projection
|
|
1144
|
+
|
|
1145
|
+
The terminal-list milestone gives list projection and fresh mutation
|
|
1146
|
+
preparation one canonical send-authority reducer. `terminal-action-projection.ts`
|
|
1147
|
+
owns Session-claim conflict precedence, dispatch/Session conflict composition,
|
|
1148
|
+
send authority, safe action selection, management facts, and handoff/recovery
|
|
1149
|
+
projection. `terminal-authority-policy.ts` owns provider-neutral terminal and
|
|
1150
|
+
process-incarnation facts, managed-binding conflict classification, Codex
|
|
1151
|
+
companion fences, exact deferred-source authority, stored Turn identity, and
|
|
1152
|
+
the byte-sensitive verified-empty, deferred-foreground, observed-handoff, and
|
|
1153
|
+
active-Turn token codecs. Both modules are typed and have no filesystem,
|
|
1154
|
+
process, lock, CLI-option, concrete-adapter, or public-JSON input boundary.
|
|
1155
|
+
The adapter-neutral complete-rollout predicate, identity fence and matcher from
|
|
1156
|
+
the lifecycle slice remain canonical in `terminal-binding-authority.ts`;
|
|
1157
|
+
authority policy directly imports and re-exports them. That module also owns
|
|
1158
|
+
the single status-card predicate and neutral binding-conflict/candidate helpers.
|
|
1159
|
+
PR4C's dispatch execution service imports those identity decisions from binding
|
|
1160
|
+
authority and its process-incarnation and companion decisions from authority
|
|
1161
|
+
policy, so production has one implementation for each decision and no cycle.
|
|
1162
|
+
|
|
1163
|
+
Measured against exact lifecycle head
|
|
1164
|
+
`10b2b9c60a8f5635961156bf9951472ea5542a48`, this slice reduces
|
|
1165
|
+
`src/cli-core.ts` from 28,610 to 28,336 physical lines (-274) and changes total
|
|
1166
|
+
production TypeScript from 78,388 to 79,308 (+920).
|
|
1167
|
+
The overhead is reported rather than hidden by compact formatting: it is the
|
|
1168
|
+
explicit typed observation handoff needed to keep Store and terminal reads in
|
|
1169
|
+
the composition root while making each authority stage independently bounded
|
|
1170
|
+
and testable. The production graph has 78 modules, 307 static import edges, and
|
|
1171
|
+
zero cycles. Targeted ownership is split honestly across
|
|
1172
|
+
`terminal-action-projection` and `terminal-authority-policy` with five retained
|
|
1173
|
+
integration witnesses each; the pre-existing binding-authority and
|
|
1174
|
+
dispatch-policy owners are also reduced to five witnesses each.
|
|
1175
|
+
|
|
1176
|
+
The old 1,162-line terminal projection callback is now a sequence of bounded
|
|
1177
|
+
stages. The final TypeScript AST spans are binding observation 298 lines,
|
|
1178
|
+
verified-empty authority 97, deferred-source authority 77, deferred action
|
|
1179
|
+
authority 106, handoff authority 139, terminal-scoped approval authority 96,
|
|
1180
|
+
authority composition 23, public rendering 256, and the outer list projection
|
|
1181
|
+
144.
|
|
1182
|
+
No touched or extracted function reaches the hard 500-line boundary. The
|
|
1183
|
+
TypeScript AST approximate-complexity maximum across the touched and extracted
|
|
1184
|
+
production functions is 48, below the hard approximate-complexity-50 gate.
|
|
1185
|
+
Binding observation, deferred action authority, handoff authority, and
|
|
1186
|
+
public rendering are reviewed exceptions to the preferred 100-line and/or
|
|
1187
|
+
complexity-20 targets: further splitting them would duplicate the staged facts
|
|
1188
|
+
or move Store reads across a safety short circuit.
|
|
1189
|
+
|
|
1190
|
+
The composition root continues to own deferred-transfer, managed-Session,
|
|
1191
|
+
managed-Turn, transition, and dispatch-ledger reads; terminal/process
|
|
1192
|
+
collection; Codex inventory and identity observation; terminal-scoped approval
|
|
1193
|
+
boundary I/O; runtime logging; and the final public JSON shell. The staged calls
|
|
1194
|
+
preserve the old left-to-right read order. In particular, a Session-authority
|
|
1195
|
+
conflict never reads the dispatch owner's Session id, a genuine mismatch keeps
|
|
1196
|
+
the old two `sessionIdForConversation` calls, and every unresolved-transition
|
|
1197
|
+
read remains behind the same verified-empty, reconcile, external-handoff, or
|
|
1198
|
+
active-Turn preconditions. Listed tokens remain stale snapshots; mutation paths
|
|
1199
|
+
repeat fresh observation and invoke the same canonical send reducer before a
|
|
1200
|
+
side effect. Blocking Turn statuses do not inspect callback delivery, current
|
|
1201
|
+
approval actions are retargeted before reading the live terminal approval
|
|
1202
|
+
state, and stored native rollout fields remain unread until all earlier Turn
|
|
1203
|
+
identity exits have passed.
|
|
1204
|
+
|
|
1205
|
+
Direct fast proofs compare the old and new `JSON.stringify` action bytes and
|
|
1206
|
+
key order, verified-empty and deferred v2/v5 token hashes, active-Turn handoff
|
|
1207
|
+
hashes, conflict precedence with lazy managed-Turn facts, selector alias and
|
|
1208
|
+
process-incarnation behavior, and list-snapshot versus fresh-mutation send
|
|
1209
|
+
decisions. Getter-backed fixtures make the three lazy-read fences executable,
|
|
1210
|
+
and ordinary fixtures compare canonical results with the previous decisions.
|
|
1211
|
+
Existing binding-authority, dispatch-policy, list-renderer, and
|
|
1212
|
+
terminal-send boundary witnesses remain in place; this slice changes no action
|
|
1213
|
+
name, action order, error string, token field order, Store format, or public
|
|
1214
|
+
contract version.
|
|
1215
|
+
## Native-thread lifecycle crash recovery and reconciliation
|
|
1216
|
+
|
|
1217
|
+
The third native-thread lifecycle slice moves one crash-recovery state machine
|
|
1218
|
+
from `recoverLifecycleFenceBeforeMutation` through fail-closed lifecycle-ledger
|
|
1219
|
+
reconciliation into `native-thread-lifecycle-recovery-service.ts`. It includes
|
|
1220
|
+
human-observed ledger rebuild, prepared rollback, verified roll-forward,
|
|
1221
|
+
committed/aborted replay, possible-input quarantine, and operator-authorized
|
|
1222
|
+
Claude/Codex identity reconciliation. Ordinary deferred foreground-dispatch
|
|
1223
|
+
recovery remains a core-owned state machine behind one scoped call. Verified
|
|
1224
|
+
empty recovery, observed external-handoff send/adoption, lifecycle mutation,
|
|
1225
|
+
monitor/callback orchestration, and public presentation remain outside this
|
|
1226
|
+
service.
|
|
1227
|
+
|
|
1228
|
+
Measured against exact head `29446b0649555c4bfca8ee23a4f2f0d9523c9fcf`,
|
|
1229
|
+
the slice reduces `src/cli-core.ts` from 27,319 to 26,095 physical lines
|
|
1230
|
+
(-1,224, -4.48%) and changes total production TypeScript from 80,554 to
|
|
1231
|
+
81,427 (+873, +1.08%). The transparent typed-boundary overhead is 71.3% of
|
|
1232
|
+
the core movement. It consists of the four port groups, direct recording
|
|
1233
|
+
surface, fresh-route composition, normalized probe facts, and the core-side
|
|
1234
|
+
raw terminal adapter; issue #126 does not impose a zero-production-growth
|
|
1235
|
+
target. The production graph has 82 modules, 339 static import edges, and zero
|
|
1236
|
+
cycles.
|
|
1237
|
+
|
|
1238
|
+
The recovery service is 1,834 physical lines and its infrastructure adapter is
|
|
1239
|
+
263 lines. The largest function remains the 211-line/c32 reconciliation reducer
|
|
1240
|
+
and the highest conservative approximate complexity is c37 in the 186-line
|
|
1241
|
+
manual Codex probe reducer. Every function is below the hard 500 LOC/c50 gates.
|
|
1242
|
+
The reviewed exceptions to the default 100 LOC/c20 target are:
|
|
1243
|
+
|
|
1244
|
+
- reconciliation (211/c32), whose ordered status and catch precedence is one
|
|
1245
|
+
directly recorded state machine;
|
|
1246
|
+
- prepared human-observed handoff recovery (116/c21), which keeps its source
|
|
1247
|
+
CAS, identity observation, rollback, and verified checkpoint together;
|
|
1248
|
+
- stored ledger/transition comparison (66/c36) and live-terminal/adapter
|
|
1249
|
+
comparison (68/c25), split only at the side-effect boundary so boolean
|
|
1250
|
+
short-circuit order is unchanged;
|
|
1251
|
+
- verified after-binding revalidation (143/c36), uncertain manual settlement
|
|
1252
|
+
(140/c15), Claude stable identity probing (115/c27), and Codex stable identity
|
|
1253
|
+
probing (186/c37), whose polling and exact-incarnation precedence remain
|
|
1254
|
+
visible as cohesive reducers;
|
|
1255
|
+
- the core-side probe adapter factory (110/c1), which keeps its closed raw
|
|
1256
|
+
capability, bridge preparation, normalization, and ordered observations in
|
|
1257
|
+
one infrastructure boundary while each returned method remains short.
|
|
1258
|
+
|
|
1259
|
+
The service imports no CLI core, filesystem/path API, raw lock, raw repository,
|
|
1260
|
+
raw JSON persistence, public presenter, `TerminalAgentAdapter`, terminal-agent
|
|
1261
|
+
bridge type or value, `any`, or `Record<..., any>`. It contains no raw screen
|
|
1262
|
+
excerpt or composer grammar. Its public request contains only fresh terminal
|
|
1263
|
+
facts; Store directory and path authority are absent. The four typed port
|
|
1264
|
+
groups are scoped authority, persistence, terminal/process evidence, and
|
|
1265
|
+
clock/sleep. Core retains terminal then writer lock acquisition, the ordinary
|
|
1266
|
+
deferred-recovery implementation, raw transition/Session/ledger repositories,
|
|
1267
|
+
terminal bridge and process probes, Store/path canonicalization, CLI logging,
|
|
1268
|
+
and JSON output. The core-side recovery adapter exposes only normalized
|
|
1269
|
+
status/probe facts and closed plan steps through separately scoped
|
|
1270
|
+
`probeThreadLifecycle`, `planThreadLifecycle`, and `observeThreadLifecycle`
|
|
1271
|
+
ports; the full terminal adapter is never returned to business code. Before
|
|
1272
|
+
either service entry, core projects the fresh resolved terminal into a new
|
|
1273
|
+
runtime object with exactly `conversationId`, `agent`, `pid`, and
|
|
1274
|
+
`terminalControl`; the broad resolved terminal remains captured only by the
|
|
1275
|
+
core ports closure.
|
|
1276
|
+
|
|
1277
|
+
Every authority, repository, process, and terminal port call receives the same
|
|
1278
|
+
active `CanonicalMutationScopes` and `CanonicalMutationResources`. Before the
|
|
1279
|
+
service is entered, core authenticates both scopes, resolves the terminal again
|
|
1280
|
+
after lock acquisition, proves the captured and fresh terminal/process
|
|
1281
|
+
incarnations match, and captures the canonical writer Store. The shared native
|
|
1282
|
+
thread resource adapter repeats those checks for every port call, including
|
|
1283
|
+
reads and probes as well as transition, Session, and ledger writes. Thus a
|
|
1284
|
+
request cannot retain free terminal-control, Store, cwd, or path authority, and
|
|
1285
|
+
released, cross-transaction, wrong-route, or wrong-Store capabilities fail
|
|
1286
|
+
before business I/O. Lifecycle ledger construction remains in the core adapter;
|
|
1287
|
+
rebuild phases replace their control with the post-lock fresh route and every
|
|
1288
|
+
persisted ledger Store must equal the canonical writer resource.
|
|
1289
|
+
|
|
1290
|
+
### Recovery order and durable checkpoints
|
|
1291
|
+
|
|
1292
|
+
The extraction preserves these existing sequences inside the terminal ->
|
|
1293
|
+
writer lock scope:
|
|
1294
|
+
|
|
1295
|
+
| Recovery path | Exact effect order retained |
|
|
1296
|
+
| --- | --- |
|
|
1297
|
+
| Fence entry | authenticate/fresh terminal -> ordinary deferred recovery -> ledger load -> optional rebuild -> lifecycle classification -> reconcile |
|
|
1298
|
+
| Missing/resolved human-handoff ledger | transition list -> typed ledger build -> complete transition/terminal/adapter validation -> compare-and-save rebuild ledger -> reload |
|
|
1299
|
+
| Live automatic dispatcher | dispatcher process probe -> unchanged ledger; no Store transition read, probe bridge, or write |
|
|
1300
|
+
| Wrong Store / unavailable transition | Store comparison or transition load -> fail-closed uncertain-ledger CAS -> reload; a failed fail-closed CAS returns the original ledger |
|
|
1301
|
+
| Prepared, zero possible input | ledger/terminal/adapter validation -> exact before-owner proof -> target/source reads and source restoration -> aborted transition CAS -> resolved-ledger CAS -> reload |
|
|
1302
|
+
| Verified | after-binding/live identity verification -> exact target-owner proof -> Session commit -> committed transition CAS -> resolved-with-binding ledger CAS -> reload |
|
|
1303
|
+
| Committed / aborted replay | live verification and owner/target assertion or before-owner/source restoration -> resolved-ledger CAS -> reload |
|
|
1304
|
+
| Dispatching/submitted automatic recovery | uncertain transition CAS -> source quarantine Session CAS -> uncertain-ledger CAS -> reload |
|
|
1305
|
+
| Operator-authorized uncertain recovery | exact stable manual probe -> process/rollout assertion -> before rollback, or target verification -> target-owner proof -> Session commit -> committed transition CAS -> resolved-ledger CAS -> reload |
|
|
1306
|
+
| Inner recovery failure | source quarantine attempt -> fail-closed uncertain-ledger CAS -> reload/original ledger |
|
|
1307
|
+
|
|
1308
|
+
Bridge construction remains at the old probe checkpoints: after the verified
|
|
1309
|
+
human-handoff early return, after Claude prepare-time process validation, and
|
|
1310
|
+
after the Codex-agent guard but before root/runtime observation. Raw terminal
|
|
1311
|
+
status, clear-line, `/status` input, agents rows, resolver, and process-birth
|
|
1312
|
+
operations stay in core or its recovery adapter. A Claude sample performs
|
|
1313
|
+
agents-row load then lifecycle observation inside one scoped call, and business
|
|
1314
|
+
recovery performs terminal status only afterward. A Codex post-`/status` sample
|
|
1315
|
+
performs one raw status call and only then raw-screen lifecycle observation
|
|
1316
|
+
inside the same scoped adapter call; it returns normalized status plus the
|
|
1317
|
+
optional observation. No raw screen or composer decision crosses into the
|
|
1318
|
+
service. No new durable checkpoint or retry permission is introduced. Manual
|
|
1319
|
+
terminal-close JSON is still emitted by core before the writer and terminal
|
|
1320
|
+
scopes are released.
|
|
1321
|
+
|
|
1322
|
+
The direct fast recording table fixes five precedence witnesses: live
|
|
1323
|
+
dispatcher short-circuit; wrong-Store fail closed before transition load;
|
|
1324
|
+
prepared rollback; dispatching possible-input quarantine; and verified
|
|
1325
|
+
roll-forward. It asserts the exact transition/Session/ledger phase order, CAS
|
|
1326
|
+
expectations, probe-before-plan order, probe preparation point, and
|
|
1327
|
+
reference-equal forwarding of the same active scopes/resources on every port
|
|
1328
|
+
call. Direct adapter witnesses fix Claude rows -> observe and Codex status ->
|
|
1329
|
+
observe order, while the static boundary witness rejects bridge imports, full
|
|
1330
|
+
terminal-adapter capability, raw screen excerpts, or composer helpers in the
|
|
1331
|
+
service. A runtime-shape witness also fixes the four projected request keys and
|
|
1332
|
+
proves that neither `adapter` nor `legacy` survives projection. Existing
|
|
1333
|
+
lifecycle recovery, human handoff, no-rollout, lifecycle, and ownership
|
|
1334
|
+
integration witnesses remain the retained black-box boundary set.
|
|
1335
|
+
|
|
1336
|
+
## Deferred Codex foreground application and recovery
|
|
1337
|
+
|
|
1338
|
+
This slice moves the complete deferred Codex foreground application vertical
|
|
1339
|
+
out of `cli-core.ts`: preparation and fresh-authority publication; source
|
|
1340
|
+
reservation and target preparation; dispatch begin/stage advancement;
|
|
1341
|
+
zero-input abort and rollback; accepted commit and resolution; uncertain
|
|
1342
|
+
settlement; and prepared, accepted, and committed crash recovery. The typed
|
|
1343
|
+
implementation is split across the application, preparation, and recovery
|
|
1344
|
+
services plus their CLI adapters, a data-only boundary module, and the
|
|
1345
|
+
invocation-scoped repository capability. Observed handoff, native-thread
|
|
1346
|
+
lifecycle recovery, ordinary dispatch, monitor/callback behavior, public
|
|
1347
|
+
presentation, and raw terminal I/O remain outside this vertical.
|
|
1348
|
+
|
|
1349
|
+
Measured against exact head
|
|
1350
|
+
`257950022ea40e343808ef68c903c6f874497a09`, the slice reduces
|
|
1351
|
+
`src/cli-core.ts` from 26,095 to 23,124 physical lines (-2,971, -11.39%) and
|
|
1352
|
+
changes total production TypeScript from 81,427 to 84,241 (+2,814, +3.46%).
|
|
1353
|
+
Typed production overhead is 94.7% of core movement, leaving 157 lines of
|
|
1354
|
+
positive movement margin. The production graph has 90 modules, 417 static
|
|
1355
|
+
import edges, and zero cycles.
|
|
1356
|
+
|
|
1357
|
+
Across the eight new production modules, the TypeScript AST inventory contains
|
|
1358
|
+
219 functions. No function reaches the default 100 LOC/c20 review threshold;
|
|
1359
|
+
the maxima are 92 LOC and c19. Consequently there is no 500 LOC/c50 hard-gate
|
|
1360
|
+
exception. Application and preparation each expose three typed port groups;
|
|
1361
|
+
recovery exposes four. No service imports CLI core, Node filesystem/process
|
|
1362
|
+
APIs, raw JSON/lock helpers, a presenter, `ResolvedTerminalConversation`,
|
|
1363
|
+
`TerminalAgentAdapter`, or the concrete capability adapter. The service-side
|
|
1364
|
+
repository scope is a narrow interface in `deferred-foreground-boundary.ts`;
|
|
1365
|
+
its implementation is module-private and can only be obtained through the
|
|
1366
|
+
production terminal/writer or terminal/writer/state binders.
|
|
1367
|
+
|
|
1368
|
+
The preparation request receives a projected terminal object with exactly
|
|
1369
|
+
`conversationId`, `agent`, `pid`, optional `workspace`, `target`, `resourceKey`,
|
|
1370
|
+
optional endpoint evidence, and `canonicalEndpoint`. The returned application
|
|
1371
|
+
boundary contains only those terminal facts and immutable transfer/session,
|
|
1372
|
+
process-incarnation, dispatch-snapshot, rollout-authority, and CAS facts. The
|
|
1373
|
+
resolved terminal, concrete control, adapter, legacy marker, Store directory,
|
|
1374
|
+
Turn paths, and terminal transport methods remain captured in CLI adapter
|
|
1375
|
+
closures. Runtime `Object.keys` witnesses fix the request, terminal-facts, and
|
|
1376
|
+
boundary shapes and reject `adapter` or `terminalControl` leakage. A stable
|
|
1377
|
+
data-only projection carries the source-reserved and target-prepared revisions
|
|
1378
|
+
and binding tokens through verification, dispatch, commit, and resolution;
|
|
1379
|
+
the associated broad terminal remains only in the CLI adapter.
|
|
1380
|
+
|
|
1381
|
+
The capability binder authenticates one active terminal -> Store writer ->
|
|
1382
|
+
optional Turn state transaction before repository use. Terminal incarnation
|
|
1383
|
+
and resource key, absolute canonical Store key/value, `state.json` membership
|
|
1384
|
+
under that Store, matching `events.ndjson`, and state resource key/value are
|
|
1385
|
+
checked before I/O. Null, object, relative, cross-Store, wrong-key,
|
|
1386
|
+
wrong-process, wrong-log, and released-scope cases fail with ordinary errors
|
|
1387
|
+
before repository access. The concrete scope is not exported, and every scope
|
|
1388
|
+
method repeats the active-scope gate; retained scopes therefore expire when the
|
|
1389
|
+
transaction callback returns. Recovery asserts the transfer, projected
|
|
1390
|
+
terminal, and Turn route immediately after candidate selection and carries the
|
|
1391
|
+
same scope through every transfer/Session/state/ledger adapter operation. The
|
|
1392
|
+
PR172 lifecycle-recovery service retains ownership of its state machine and
|
|
1393
|
+
invokes this deferred service through its existing `recoverDeferred` port with
|
|
1394
|
+
the same active terminal and writer scopes/resources.
|
|
1395
|
+
|
|
1396
|
+
### Application, CAS, and recovery order
|
|
1397
|
+
|
|
1398
|
+
The extraction preserves these Store, Turn, ledger, and terminal-evidence
|
|
1399
|
+
orders:
|
|
1400
|
+
|
|
1401
|
+
| Path | Exact effect and CAS order retained |
|
|
1402
|
+
| --- | --- |
|
|
1403
|
+
| Fresh preparation | process incarnation -> fresh rollout/dispatch observation -> fresh binding token -> target/transfer IDs -> canonical boundary revalidation -> exclusive ownership -> unresolved-transfer list (source identity or terminal id + endpoint; PID is not collision authority) -> request hash -> dispatcher pid -> clock -> transfer create with expected revision `null` |
|
|
1404
|
+
| Stale list token | process incarnation -> fresh observation -> freshly derived token -> reject; no ID generation, ownership check, list, hash, clock, or write |
|
|
1405
|
+
| Reservation | transfer load/authority -> fresh source verification -> source Session `bound -> transitioning` CAS -> crash point -> transfer `prepared -> source_reserved` CAS -> crash point -> transfer `source_reserved -> target_prepared` CAS with canonical Turn path -> crash point -> target Session create with expected revision `null` |
|
|
1406
|
+
| Dispatch evidence | target/source receipt checks -> transfer `target_prepared -> dispatch_started` CAS -> transfer `dispatch_started -> text_injected` CAS -> transfer `text_injected -> enter_dispatched` CAS; each write consumes the immediately loaded transfer revision |
|
|
1407
|
+
| Zero-input abort | possible-input guard first -> aborted transfer CAS -> target detach Session CAS -> source restore Session CAS -> `abort_resolved` transfer CAS. Before current-terminal recovery, every Store-authoritative aborted intent is finalized under the existing writer scope without pane/PID/cwd checks or a Turn-state lock, then transfers are listed again and filtered to the current terminal. Recovery with a prepared Turn first persists the aborted Turn receipt, then the resolved safe-to-retry ledger receipt, then performs those transfer/Session CAS writes |
|
|
1408
|
+
| Accepted commit | transfer/source/target reads and exact authority -> ownership -> optional same-thread source scrub Session CAS -> target accepted Session CAS -> committed transfer CAS -> source detach Session CAS -> target bind Session CAS -> exclusive-owner revalidation -> resolved transfer CAS |
|
|
1409
|
+
| Uncertain | authority and dispatch-start fence -> clock(s) -> one transfer CAS carrying `do_not_retry: true`; no Session rollback and no terminal retry |
|
|
1410
|
+
| Committed recovery | transfer/Turn/target/ledger authority -> exact acceptance observation -> accepted Turn state write -> accepted ledger write -> crash point -> source/target/transfer resolution CAS -> accepted Turn identity assertion |
|
|
1411
|
+
| Possible-input recovery | exact Turn/ledger authority -> one acceptance observation. Durable zero-input proof may enter the abort path; otherwise no abort or rollback is callable. A v3 pending candidate returns without replay, while older pending or observation failure reloads durable transfer authority, records uncertainty at most once, and fails closed |
|
|
1412
|
+
|
|
1413
|
+
Turn acceptance remains stronger than later Session and ledger bookkeeping. In
|
|
1414
|
+
accepted recovery the accepted Turn state is written before Session/transfer
|
|
1415
|
+
commit and the accepted ledger is written only after the resolved Session
|
|
1416
|
+
authority and Turn identity checks. If later bookkeeping fails, the accepted
|
|
1417
|
+
Turn is retained and the failure path records stalled/uncertain durable
|
|
1418
|
+
evidence; terminal input is never replayed. All transfer writes use explicit
|
|
1419
|
+
revision CAS, Session writes use the immediately observed managed-Session
|
|
1420
|
+
revision, target creation uses `null`, and no list token is reused as mutation
|
|
1421
|
+
authority: mutation always re-observes the canonical post-lock terminal and
|
|
1422
|
+
binding authority.
|
|
1423
|
+
|
|
1424
|
+
Four fast direct files provide the fake-port order, route, capability, and
|
|
1425
|
+
transition tables. They cover stale-token revalidation, request/boundary
|
|
1426
|
+
runtime shape, revision/clock order, possible-input never-abort behavior,
|
|
1427
|
+
single-observation recovery, durable reload before uncertainty, status routing,
|
|
1428
|
+
multiple-candidate rejection before state scope, cross-terminal abort cleanup
|
|
1429
|
+
before fresh matching, stable reservation-boundary CAS facts, canonical resource failures,
|
|
1430
|
+
non-public scope construction, and every-method released-scope failure. The
|
|
1431
|
+
five retained targeted integration witnesses are Codex no-rollout binding,
|
|
1432
|
+
dispatch authority, dispatch recovery, Session acceptance, and terminal send
|
|
1433
|
+
gates.
|
|
1434
|
+
|
|
1435
|
+
## Terminal list and selector CLI facade
|
|
1436
|
+
|
|
1437
|
+
The terminal-list slice moves raw Store, managed-Session, managed-Turn,
|
|
1438
|
+
terminal/process, dispatch-ledger, and approval observations out of
|
|
1439
|
+
`cli-core.ts` into `terminal-list-cli-adapter.ts`. The adapter owns only CLI
|
|
1440
|
+
composition and infrastructure projection. Existing terminal action,
|
|
1441
|
+
authority, binding, dispatch, approval, and list-renderer modules remain the
|
|
1442
|
+
unique decision owners; the facade does not copy their reducers, tokens,
|
|
1443
|
+
identity classifiers, conflict precedence, or approval rules.
|
|
1444
|
+
|
|
1445
|
+
The exported facade has five cohesive, explicitly typed dependency groups:
|
|
1446
|
+
reconciliation, terminal discovery, Store observation, authority observation,
|
|
1447
|
+
and policy configuration. `cli-core.ts` constructs one local facade and routes
|
|
1448
|
+
list and selector work through it. Each facade call installs its own immutable
|
|
1449
|
+
dependency set in an async-local execution context. There is no mutable module
|
|
1450
|
+
configuration or catch-all `(...args: any[]) => any` runtime port, and the only
|
|
1451
|
+
runtime export from the adapter is `createTerminalListCliFacade`.
|
|
1452
|
+
|
|
1453
|
+
The direct concurrency witness runs facade A's reconciled `runList` and facade
|
|
1454
|
+
B's selector discovery concurrently, pauses both across independent awaits,
|
|
1455
|
+
then releases B before A. The observed post-await callbacks remain B's process
|
|
1456
|
+
source and A's idle reconciler respectively. After both Promises settle, a
|
|
1457
|
+
second selector call through each facade still observes its own marker. This
|
|
1458
|
+
locks the per-execution dependency isolation and factory-only entry boundary.
|
|
1459
|
+
|
|
1460
|
+
Selector candidate projection is the I/O-free
|
|
1461
|
+
`terminal-selector-projection-service.ts`; it accepts typed entry facts and one
|
|
1462
|
+
typed active-status policy. Process elapsed parsing has one I/O-free canonical
|
|
1463
|
+
owner in `terminal-process-facts.ts`; the process-source adapter compatibility
|
|
1464
|
+
re-exports it, while the selector service never imports the process-source
|
|
1465
|
+
module or its `node:child_process` edge. Managed-Session revision is read
|
|
1466
|
+
directly from `managed-session.ts`. Native Turn identity matching has one
|
|
1467
|
+
neutral implementation in `terminal-authority-policy.ts`, shared by list and
|
|
1468
|
+
dispatch; the dispatch module keeps only a compatibility re-export.
|
|
1469
|
+
|
|
1470
|
+
Measured against exact head `29219e4f98a6057924feb37ed05a9982e7310695`,
|
|
1471
|
+
the slice reduces `src/cli-core.ts` from 23,124 to 20,051 physical lines
|
|
1472
|
+
(-3,073) and changes production TypeScript from 84,241 to 84,907 (+666). The
|
|
1473
|
+
transparent typed-facade overhead is 21.67% of the core movement. The graph
|
|
1474
|
+
changes from 90 modules and 417 static import edges to 93 modules and 446
|
|
1475
|
+
edges, with zero cycles before and after. The terminal-list owner has two
|
|
1476
|
+
modules and four targeted integration witnesses. The preceding deferred
|
|
1477
|
+
foreground slice retains its eight-module ownership mapping unchanged.
|
|
1478
|
+
|
|
1479
|
+
The stacked composition preserves the deferred foreground authority,
|
|
1480
|
+
preparation, application, and recovery services as the only owners of their
|
|
1481
|
+
state machines. Its existing authority-adapter ports now call the terminal-list
|
|
1482
|
+
facade for managed-Turn attention, transition state, and terminal-incarnation
|
|
1483
|
+
blocking facts; no old inline deferred reducer was restored during the rebase.
|
|
1484
|
+
|
|
1485
|
+
The infrastructure adapter is a reviewed exception to the preferred
|
|
1486
|
+
100-line/complexity-20 function target because its staged observation
|
|
1487
|
+
functions preserve existing Store/terminal/error priority and getter
|
|
1488
|
+
short-circuits. Its maximum function span is the 298-line/c43 binding
|
|
1489
|
+
observation, and its highest conservative approximate complexity is c44 in the
|
|
1490
|
+
139-line handoff observation. Public rendering is 256/c42, terminal discovery
|
|
1491
|
+
entry composition is 227/c39, and scoped approval resolution is 221/c36. All
|
|
1492
|
+
remain below the hard 500-line/c50 boundary. The pure selector service peaks at
|
|
1493
|
+
42/c11 and the process fact parser at 24/c9.
|
|
1494
|
+
|
|
1495
|
+
Direct fast proofs preserve exact selector JSON bytes and key insertion order,
|
|
1496
|
+
mutation-disabled lazy `available_actions` reads, approval fallback getter
|
|
1497
|
+
order and action target, canonical native-identity getter order, and concurrent
|
|
1498
|
+
facade isolation. Focused list, delegate, Session-selector, action projection,
|
|
1499
|
+
and process-source witnesses retain Store/terminal/error priority, the second
|
|
1500
|
+
Session lookup on mismatch, stale-list versus fresh-mutation separation, and
|
|
1501
|
+
public token bytes.
|
|
1502
|
+
## Generic CLI file-lock infrastructure
|
|
1503
|
+
|
|
1504
|
+
The synchronous generic file-lock protocol now lives in
|
|
1505
|
+
`file-lock-cli-adapter.ts`. The adapter owns only exclusive private-file
|
|
1506
|
+
creation, stale-owner probing, reclaim-guard cleanup, token-matched release,
|
|
1507
|
+
and legacy owner decoding. Store leases, terminal routing, lifecycle ledgers,
|
|
1508
|
+
monitor ownership, callback policy, and deferred-transfer decisions remain in
|
|
1509
|
+
their existing owners.
|
|
1510
|
+
|
|
1511
|
+
The factory receives typed clock, PID, sleep, nonce, process-signal, and
|
|
1512
|
+
filesystem ports and retains no mutable global configuration. `cli-core.ts`
|
|
1513
|
+
binds its existing async-local clock/PID/sleep functions once; those functions
|
|
1514
|
+
still resolve the active command context at each lock call. All 28 acquisition
|
|
1515
|
+
call sites keep the same lock path, timeout/retry options, returned release
|
|
1516
|
+
closure, and surrounding `try`/`finally` order. The one stale probe and one
|
|
1517
|
+
owner read also retain their previous query inputs and results.
|
|
1518
|
+
|
|
1519
|
+
Against exact parent `59983e63c8e5569d27e6396dc0961433e3a6ec34`, the move
|
|
1520
|
+
reduces `cli-core.ts` from 20,051 to 19,901 physical lines (-150). The new
|
|
1521
|
+
infrastructure module is 192 lines, so production grows from 84,907 to 84,949
|
|
1522
|
+
(+42, below both the 50-line target and the 150-line core movement). Direct
|
|
1523
|
+
recording tests lock acquisition/write/close/release order, live-owner timeout
|
|
1524
|
+
cleanup, dead-owner reclaim-before-retry, and descriptor close-before-error
|
|
1525
|
+
propagation. No file-lock behavior or error precedence changes.
|
|
1526
|
+
|
|
1527
|
+
## Ordinary terminal command CLI facade
|
|
1528
|
+
|
|
1529
|
+
The ordinary-command slice moves send, respond, approve, exclusive replay,
|
|
1530
|
+
and dispatch composition out of `cli-core.ts` into
|
|
1531
|
+
`terminal-command-cli-adapter.ts`. Cancel, renew, close, monitor, lifecycle,
|
|
1532
|
+
callback, and deferred-foreground state machines remain with their existing
|
|
1533
|
+
owners. The adapter composes the existing terminal-dispatch execution,
|
|
1534
|
+
application, capability, receipt, deferred-foreground, terminal-list, and
|
|
1535
|
+
file-lock factories; it does not introduce a second reducer or authority
|
|
1536
|
+
decision.
|
|
1537
|
+
|
|
1538
|
+
The only runtime export is `createTerminalCommandCliFacade`. Each invocation
|
|
1539
|
+
runs with an immutable dependency set in async-local context, so concurrently
|
|
1540
|
+
awaiting facades cannot observe one another's ports. The emitted command-facade
|
|
1541
|
+
declaration contains neither `any`, `Record<..., any>`, nor
|
|
1542
|
+
`ResolvedTerminalConversation`. Every callback has explicit parameters and
|
|
1543
|
+
results. `TerminalDispatchTerminal` is only a structural, CLI-infrastructure
|
|
1544
|
+
carrier for `conversationId`, `agent`, `pid`, and `terminalControl`; it does
|
|
1545
|
+
not claim to remove extra properties from the runtime object.
|
|
1546
|
+
`TerminalControlSendRequest` now uses a six-field
|
|
1547
|
+
`TerminalControlSendOptions extends Record<string, unknown>` boundary covering
|
|
1548
|
+
only the timeout, polling, scrollback, and Claude-home values read by dispatch.
|
|
1549
|
+
The structural terminal carrier and concrete deferred adapters remain
|
|
1550
|
+
CLI-infrastructure values, not business-service requests.
|
|
1551
|
+
|
|
1552
|
+
Every actual deferred business-service request still crosses the explicit
|
|
1553
|
+
`projectDeferredForegroundTerminalFacts()` literal projection. The direct
|
|
1554
|
+
preparation-service witness fixes the request and boundary `Object.keys`, and
|
|
1555
|
+
proves that neither `adapter` nor `terminalControl` crosses that boundary.
|
|
1556
|
+
Terminal-dispatch execution receives typed facts and ports, while dispatch
|
|
1557
|
+
application and capability receive authenticated routes/repositories; none of
|
|
1558
|
+
the three receives the concrete terminal carrier.
|
|
1559
|
+
|
|
1560
|
+
Measured against exact parent
|
|
1561
|
+
`921636a4a86da8d565c659bdcbb64021ac112366`, the slice reduces
|
|
1562
|
+
`src/cli-core.ts` from 19,901 to 16,350 physical lines (-3,551) and changes
|
|
1563
|
+
production TypeScript from 84,949 to 86,473 lines (+1,524). Typed production
|
|
1564
|
+
overhead is 42.92 percent of core movement, leaving 2,027 lines of movement
|
|
1565
|
+
margin. The production graph has 46 domains, 95 modules, 482 static import
|
|
1566
|
+
edges, and zero cycles. `cli-core.ts` retains one production importer. The
|
|
1567
|
+
ordinary-command owner has one module and exactly five focused integration
|
|
1568
|
+
witnesses.
|
|
1569
|
+
|
|
1570
|
+
The extraction preserves three critical transaction shapes. Replay validates
|
|
1571
|
+
ledger receipt history before active-ledger authority, validates every stored
|
|
1572
|
+
match (including getters and conflicting safe-abort receipts) before filtering
|
|
1573
|
+
retryable zero-input receipts, validates the durable log body, and presents
|
|
1574
|
+
inside the canonical mutation callback. Transport failure may call the
|
|
1575
|
+
zero-input reducer only when no text timestamp exists and the error is
|
|
1576
|
+
`TerminalInputNotStartedError`; every possible-input failure instead records
|
|
1577
|
+
uncertainty, emits `do_not_retry`, and presents the uncertain receipt. Managed
|
|
1578
|
+
approval holds the terminal lock across observation, reservation, key
|
|
1579
|
+
dispatch, durable resolution, monitor handoff, and JSON presentation. Its
|
|
1580
|
+
state lock is released before monitor launch as before, while a failed
|
|
1581
|
+
`beforeKeyDispatch` leaves the reserved uncertain marker and sends no key.
|
|
1582
|
+
|
|
1583
|
+
The following infrastructure functions are reviewed exceptions to the
|
|
1584
|
+
preferred 100-line/c20 target. Counts use the same conservative physical-span
|
|
1585
|
+
and nested-function-excluding complexity method as this document; every entry
|
|
1586
|
+
remains below the hard 500-line/c50 gate.
|
|
1587
|
+
|
|
1588
|
+
| Function or nested stage | LOC / approximate complexity |
|
|
1589
|
+
| --- | ---: |
|
|
1590
|
+
| `runManagedApprovalDispatch` | 486 / c2 |
|
|
1591
|
+
| `runRawTerminalSend` | 443 / c2 |
|
|
1592
|
+
| raw-send canonical mutation callback | 419 / c45 |
|
|
1593
|
+
| `runApprovalWithStateLock` | 393 / c30 |
|
|
1594
|
+
| `replayExactActiveTerminalSubmission` | 276 / c41 |
|
|
1595
|
+
| `runManagedSessionSend` | 265 / c21 |
|
|
1596
|
+
| `resolveTerminalDispatchSubmissionOwner` | 261 / c43 |
|
|
1597
|
+
| `prepareTerminalControlSend` | 255 / c42 |
|
|
1598
|
+
| `runTurnResponse` | 223 / c11 |
|
|
1599
|
+
| `replayExactStoredTerminalSubmission` | 188 / c22 |
|
|
1600
|
+
| managed-send mutation callback | 186 / c21 |
|
|
1601
|
+
| `runApprove` | 177 / c32 |
|
|
1602
|
+
| respond outer mutation callback | 164 / c1 |
|
|
1603
|
+
| `runTerminalConversationApprove` | 162 / c10 |
|
|
1604
|
+
| respond state callback | 153 / c22 |
|
|
1605
|
+
| `validateStoredTerminalSubmissionMatch` | 150 / c28 |
|
|
1606
|
+
| `createTerminalDispatchRuntime` | 148 / c4 |
|
|
1607
|
+
| approval `beforeKeyDispatch` callback | 132 / c31 |
|
|
1608
|
+
| `runTerminalControlSend` | 105 / c9 |
|
|
1609
|
+
| `runTerminalDispatchTransport` | 106 / c7 |
|
|
1610
|
+
| raw-send state callback | 103 / c4 |
|
|
1611
|
+
|
|
1612
|
+
The evidence map deliberately reuses the direct tests of the unique dispatch
|
|
1613
|
+
owners instead of copying their state machines into facade tests:
|
|
1614
|
+
|
|
1615
|
+
| Contract | Direct proof | Focused real-CLI proof |
|
|
1616
|
+
| --- | --- | --- |
|
|
1617
|
+
| Factory-only typed ports and await isolation | `terminal-command-cli-adapter.test.ts` fake-port trace | all five owner files exercise the bound production factory |
|
|
1618
|
+
| Replay receipt/log bytes, getter validation, error priority, and locked presentation | facade compiled-wiring proof; `terminal-dispatch-receipt.test.ts` exact bytes | `agent-cli-composer-replay.test.ts` exact output/log body and no second Enter |
|
|
1619
|
+
| Possible input never becomes zero-input retry | facade failure-wiring proof; `terminal-dispatch-application.test.ts` text-progress table; `terminal-dispatch-execution.test.ts` one-Enter table | `agent-cli-dispatch-authority.test.ts` retryable pre-input versus uncertain post-input receipts |
|
|
1620
|
+
| Approval uncertain reservation and terminal-lock lifetime | facade lock-wiring proof; `terminal-agent-bridge.test.ts` reservation/callback/no-key order | `agent-cli-claude-callback.test.ts` and `agent-cli-control-locks.test.ts` |
|
|
1621
|
+
| Native acceptance and dispatch-owner authority | execution/application fake-port tables | `agent-cli-session-acceptance.test.ts` |
|
|
1622
|
+
| Runtime stripping at the service boundary | `deferred-foreground-preparation-service.test.ts` exact request/boundary keys | the Session-acceptance witness traverses the same production projection |
|
|
1623
|
+
|
|
1624
|
+
The five selected focused files are composer replay, dispatch authority,
|
|
1625
|
+
control locks, Claude callback, and Session acceptance. They cover replay,
|
|
1626
|
+
send/possible-input, approval, lock order, and native acceptance without adding
|
|
1627
|
+
lifecycle, close, monitor, or callback ownership to this facade.
|
|
1628
|
+
|
|
1629
|
+
## Terminal dispatch repository and recovery
|
|
1630
|
+
|
|
1631
|
+
The terminal dispatch recovery slice moves the raw ordinary-ledger repository,
|
|
1632
|
+
prepared and lagging crash reconciliation, verified-dead reconciliation, and
|
|
1633
|
+
callbackless local-completion settlement out of `cli-core.ts`. Ordinary
|
|
1634
|
+
send/respond/approve dispatch, deferred foreground transfer state machines,
|
|
1635
|
+
native lifecycle policy, monitor polling and callback transport remain in their
|
|
1636
|
+
existing owners. The composition root keeps the narrow callback-outbox
|
|
1637
|
+
preparation closure and routes the old helper names through one invocation-safe
|
|
1638
|
+
facade.
|
|
1639
|
+
|
|
1640
|
+
Measured against exact parent `9156a7d45c28b8d9a428fbd048c46cf2226d56aa`,
|
|
1641
|
+
the slice reduces `src/cli-core.ts` from 16,350 to 14,390 physical lines
|
|
1642
|
+
(-1,960) and changes total production TypeScript from 86,473 to 87,562 lines
|
|
1643
|
+
(+1,089, 55.56% of the core movement). The three-module ownership domain has five
|
|
1644
|
+
targeted integration witnesses. Architecture validation reports 98 production
|
|
1645
|
+
modules, 515 static import edges, and zero cycles.
|
|
1646
|
+
|
|
1647
|
+
The 410-line repository adapter is the sole owner of dispatch-ledger filesystem
|
|
1648
|
+
paths, raw bytes, legacy/canonical filenames, the dual lock set, file modes,
|
|
1649
|
+
directory fsync, and atomic replace. Its 321-line/c1 factory is a reviewed
|
|
1650
|
+
exception to the preferred 100-line function target; its largest inner
|
|
1651
|
+
operation is the 73-line/c18 save. The 791-line recovery service exposes exactly
|
|
1652
|
+
five typed port groups (`transaction`, `authority`, `evidence`, `state`, and
|
|
1653
|
+
`completion`), has a 47-line maximum function and c12 maximum complexity, and
|
|
1654
|
+
imports no Node filesystem/path API, CLI core, Store/session persistence, raw
|
|
1655
|
+
lock or JSON helper, `Record<..., any>`, full resolved terminal, or terminal
|
|
1656
|
+
adapter capability. The 1,848-line CLI transaction adapter owns path projection,
|
|
1657
|
+
Session/event reads, Store-writer and state locking, callback preparation, and
|
|
1658
|
+
legacy record validation. Its largest function is 77/c17. The reviewed
|
|
1659
|
+
complexity exception is the 37-line/c30 exact ledger-receipt predicate; every
|
|
1660
|
+
function remains below the hard 500 LOC/c50 gates, and the facade factory is
|
|
1661
|
+
24/c1.
|
|
1662
|
+
|
|
1663
|
+
Repository compatibility remains fail closed. A canonical terminal acquires
|
|
1664
|
+
the canonical and legacy send locks in lexical order and releases them in
|
|
1665
|
+
reverse order through an idempotent closure. Reads reject symlinks and non-files
|
|
1666
|
+
without following the final path and reject simultaneous canonical/legacy
|
|
1667
|
+
owners. A validated legacy ledger is renamed to its canonical owner and the
|
|
1668
|
+
directory is synced before the next version-2 replace. Every replace creates a
|
|
1669
|
+
0600 exclusive temporary file, writes the exact pretty-JSON-plus-newline bytes,
|
|
1670
|
+
fsyncs the file, renames, reapplies 0600, fsyncs the directory, and removes any
|
|
1671
|
+
temporary artifact. Receipt history remains append-preserving across migration
|
|
1672
|
+
and settlement; a failed conversation/message CAS leaves the original bytes
|
|
1673
|
+
unchanged. Restoring a prior durable generation replaces the top-level document
|
|
1674
|
+
while retaining its append-only receipt history, so the abandoned generation
|
|
1675
|
+
cannot leak a self-referential `previous_generation_id`.
|
|
1676
|
+
|
|
1677
|
+
Recovery retains `terminal dispatch lock -> Store writer lease -> Turn state
|
|
1678
|
+
lock`. Prepared keep decisions do not sample the clock, and owner mismatch
|
|
1679
|
+
returns before Store/binding projection. Prepared recovery resolves only when
|
|
1680
|
+
durable evidence proves zero input was possible; text-injected,
|
|
1681
|
+
Enter-dispatched, submitted, accepted, and uncertain proof is reconciled
|
|
1682
|
+
without terminal replay. Fresh verified-dead recovery applies the basic ledger
|
|
1683
|
+
fence first, then short-circuits state, Store, full ledger, receipt, and
|
|
1684
|
+
acceptance observations in order. It reuses or observes one process-death proof
|
|
1685
|
+
and lets a newly observed durable completion win before writing stall evidence.
|
|
1686
|
+
Stall persistence remains `death event -> stalled event -> crash fence -> state
|
|
1687
|
+
-> runtime log`. Completion preparation releases the state lock while retaining
|
|
1688
|
+
terminal and writer ownership; a failed release is retried by the enclosing
|
|
1689
|
+
transaction cleanup before writer and terminal release. Local completion
|
|
1690
|
+
verifies the exact claim, detected event,
|
|
1691
|
+
message event, accepted submission, and ledger before `resolve ledger -> settled
|
|
1692
|
+
event`. Reload, projection, and callback errors still unwind state, writer, then
|
|
1693
|
+
terminal ownership.
|
|
1694
|
+
|
|
1695
|
+
Direct fast evidence fixes legacy promotion, canonical bytes and 0600 mode,
|
|
1696
|
+
receipt preservation, canonical/legacy conflict rejection, dangling-symlink
|
|
1697
|
+
rejection, dual-lock cleanup, failed-CAS byte identity, verified-dead completion
|
|
1698
|
+
and stall write order, callbackless settlement idempotence, zero-input-only
|
|
1699
|
+
prepared resolution, no replay surface, five-port boundary hygiene, and all-lock
|
|
1700
|
+
cleanup after a locked reload failure. It also fixes replacement-document
|
|
1701
|
+
Object keys and bytes, lazy-observation call counts and reason strings, and a
|
|
1702
|
+
release-error retry. Existing dispatch recovery, receipt
|
|
1703
|
+
fence, control-lock, monitor recovery, and human-handoff suites remain the
|
|
1704
|
+
black-box boundary set.
|
|
1705
|
+
|
|
1706
|
+
## Terminal runtime and provider CLI composition
|
|
1707
|
+
|
|
1708
|
+
The runtime/provider slice moves command-scoped terminal-control provider
|
|
1709
|
+
selection, process-source selection, Codex/Claude adapter registry composition,
|
|
1710
|
+
bridge construction, Claude `agents --json --all` observation, running-agent
|
|
1711
|
+
version observation, and provider-owned takeover decoding into
|
|
1712
|
+
`terminal-runtime-cli-adapter.ts`. Exact-bound Codex completion policy, native
|
|
1713
|
+
identity resolution and assertion, Store-backed runtime identity, durable
|
|
1714
|
+
request construction, endpoint refinement, legacy migration, acceptance,
|
|
1715
|
+
dispatch, monitor, lifecycle, callback, and deferred foreground work remain in
|
|
1716
|
+
their existing owners and enter this adapter only through typed callbacks.
|
|
1717
|
+
|
|
1718
|
+
The factory receives five invocation-local groups: options, async-local command
|
|
1719
|
+
dependencies, completion callbacks, opaque identity callbacks, and workspace
|
|
1720
|
+
validation. It retains no mutable global provider or dependency state. Bridge
|
|
1721
|
+
defaults are still evaluated lazily in provider -> agent registry -> process
|
|
1722
|
+
source order. Injected providers and sources still win before static fixtures;
|
|
1723
|
+
the original option truthiness rules are unchanged. Concrete raw JSON parsing
|
|
1724
|
+
and `spawnSync` calls stay in this CLI infrastructure adapter rather than
|
|
1725
|
+
crossing a service boundary. Claude keeps the exact
|
|
1726
|
+
`agents --json --all` argv, status/error handling, invalid-JSON diagnostics,
|
|
1727
|
+
required-observation refusal, and row normalization order. Running-version
|
|
1728
|
+
observation keeps injected -> per-PID fixture -> per-agent fixture -> exact
|
|
1729
|
+
`lsof` executable-path evidence priority.
|
|
1730
|
+
|
|
1731
|
+
Against exact parent `779e2e5d15ff18c5b8d0c5bbb7493e601f06cfb3`, the
|
|
1732
|
+
required top runtime movement plus the independent agent-version adapter reduce
|
|
1733
|
+
`src/cli-core.ts` from 14,390 to 13,935 physical lines (-455). Production
|
|
1734
|
+
TypeScript changes from 87,562 to 87,718 lines (+156, 34.29 percent of the core
|
|
1735
|
+
reduction), meeting the preferred overhead target and remaining below the 518
|
|
1736
|
+
lines of gross responsibility movement. The graph has 48 domains, 99 modules,
|
|
1737
|
+
526 edges, and zero cycles. The generated adapter declaration has no `any`,
|
|
1738
|
+
`Record<..., any>`, or `ResolvedTerminalConversation`; the module imports no
|
|
1739
|
+
Store, identity-authority, acceptance, dispatch, monitor, lifecycle, callback,
|
|
1740
|
+
or deferred module. Every adapter function is below 100 physical lines and
|
|
1741
|
+
approximate complexity 20; the maxima are 47 lines and c15.
|
|
1742
|
+
|
|
1743
|
+
Direct fast proofs lock factory laziness and instance isolation, exact provider
|
|
1744
|
+
-> registry -> process-source getter order, injection/static truthiness,
|
|
1745
|
+
exact-bound completion short-circuiting, Claude subprocess argv and fail-closed
|
|
1746
|
+
errors, agent-version precedence, and tmux/Herdr takeover decoding. Its targeted
|
|
1747
|
+
owner selects five retained CLI witnesses spanning Claude native inspection,
|
|
1748
|
+
facade import laziness, lifecycle versioning, send gating, and native Session
|
|
1749
|
+
acceptance. The 8,997-line Codex no-rollout fixture is deliberately excluded:
|
|
1750
|
+
these narrower witnesses cover this composition boundary without selecting the
|
|
1751
|
+
integration tier's dominant runtime for every adapter edit.
|
|
1752
|
+
|
|
1753
|
+
## Native acceptance and managed Turn application
|
|
1754
|
+
|
|
1755
|
+
The acceptance slice moves native acceptance composition, virgin Codex
|
|
1756
|
+
post-submission binding recovery, monitor acceptance reconciliation, uncertain
|
|
1757
|
+
settlement, managed Session identity refinement, managed Turn queries, and
|
|
1758
|
+
managed Turn construction out of `cli-core.ts`. The new CLI adapter composes the
|
|
1759
|
+
existing `TerminalDispatchExecutionService`, terminal-submission detectors,
|
|
1760
|
+
receipt merger, deferred-foreground recovery owner, and terminal-dispatch
|
|
1761
|
+
repository/recovery facades. Ordinary ledger locking, reads, and writes are
|
|
1762
|
+
projected directly from `terminalDispatchRepository`; prepared reconciliation
|
|
1763
|
+
and binding proof are projected directly from `terminalDispatchRecovery`. It
|
|
1764
|
+
obtains the command-local terminal runtime lazily and uses its existing Claude
|
|
1765
|
+
row and bridge ports instead of rebuilding provider composition. It does not
|
|
1766
|
+
copy acceptance scanning, receipt ranking,
|
|
1767
|
+
ledger repair, authority tokens, or deferred-transfer reducers.
|
|
1768
|
+
|
|
1769
|
+
`TerminalAcceptanceApplicationService` owns the ordered
|
|
1770
|
+
recover -> detect -> optional second recovery -> second detect -> exact draft
|
|
1771
|
+
proof -> commit decision. `ManagedTurnRecoveryService` owns the monotonic virgin
|
|
1772
|
+
binding sequence: validate literal facts, resolve the exact identity, require
|
|
1773
|
+
the canonical acceptance detector when neither side was committed, prove
|
|
1774
|
+
exclusive ownership, commit Session identity, commit Turn identity, then
|
|
1775
|
+
revalidate the Turn. Both services receive at most five typed port groups and
|
|
1776
|
+
import no filesystem, path, Store/session repository, raw lock, raw JSON,
|
|
1777
|
+
`Record<..., any>`, `ResolvedTerminalConversation`, or terminal adapter
|
|
1778
|
+
instances.
|
|
1779
|
+
|
|
1780
|
+
The CLI adapter retains the concrete resource discipline. Virgin recovery is
|
|
1781
|
+
terminal lock -> Store writer -> Turn state lock; monitor acceptance already
|
|
1782
|
+
holds the same terminal lock and therefore enters only writer -> state. Final
|
|
1783
|
+
acceptance writes Turn state before best-effort ledger and event bookkeeping,
|
|
1784
|
+
while uncertainty retains the legacy ledger -> Turn state -> event durable
|
|
1785
|
+
order. An `enter_dispatched` Turn with possible input never enters a replay or
|
|
1786
|
+
zero-input abort path: absent acceptance stays pending unless the exact draft
|
|
1787
|
+
is still present, in which case it becomes durable `not_accepted` with
|
|
1788
|
+
`do_not_retry` authority.
|
|
1789
|
+
|
|
1790
|
+
Managed Turn construction retains the original insertion order and exact
|
|
1791
|
+
storage-path suffix, binding id/generation, native identity, endpoint evidence,
|
|
1792
|
+
message metadata, and optional deferred transfer id. The public adapter
|
|
1793
|
+
declaration contains neither `any`, `Record<..., any>`, nor
|
|
1794
|
+
`ResolvedTerminalConversation`; deferred operations cross only the structural
|
|
1795
|
+
`TerminalDispatchTerminal` carrier.
|
|
1796
|
+
|
|
1797
|
+
Measured against exact parent
|
|
1798
|
+
`6318a3bbff2ec0aa10baa3ada8313d1eed038bd2`, this slice reduces
|
|
1799
|
+
`src/cli-core.ts` from 13,935 to 12,721 physical lines (-1,214) and changes
|
|
1800
|
+
production TypeScript from 87,718 to 88,732 lines (+1,014). The typed overhead
|
|
1801
|
+
is 83.53 percent of core movement and remains 200 lines below the hard
|
|
1802
|
+
movement ceiling; it does not meet the preferred 450-line overhead target, so
|
|
1803
|
+
that tradeoff is explicit. The production graph has 49 domains, 102 modules,
|
|
1804
|
+
559 static import edges, and zero cycles. `cli-core.ts` retains one production
|
|
1805
|
+
importer, and the acceptance owner retains exactly five integration witnesses.
|
|
1806
|
+
|
|
1807
|
+
All extracted functions remain below the hard 500-line/c50 gates. The two
|
|
1808
|
+
reviewed preferred-target exceptions use the documented nested-function-
|
|
1809
|
+
excluding complexity method: `#recoverVirginLocked` is 104 physical lines/c2,
|
|
1810
|
+
and `attachManagedTurn` is 75 lines/c23. Every business-service function stays
|
|
1811
|
+
below 100 lines and c20.
|
|
1812
|
+
|
|
1813
|
+
The direct evidence fixes the critical boundaries:
|
|
1814
|
+
|
|
1815
|
+
| Contract | Direct proof | Focused real-CLI proof |
|
|
1816
|
+
| --- | --- | --- |
|
|
1817
|
+
| Virgin acceptance order and split CAS recovery | recording ports prove detector -> ownership -> Session -> Turn -> revalidation and both one-sided crash continuations | no-rollout binding and Session-acceptance shards |
|
|
1818
|
+
| Possible input never replays | application table proves pending without exact draft and `not_accepted` only with exact draft | Session acceptance and terminal-send gates |
|
|
1819
|
+
| Terminal -> writer -> state and durable write order | compiled facade wiring checks both lock stacks plus accepted and uncertain writes | monitor-recovery and no-rollout binding |
|
|
1820
|
+
| Managed Turn JSON shape | direct exact key/order/binding/message projection | handoff and Session-acceptance shards |
|
|
1821
|
+
| Data-only service boundary | declaration/source prohibition test and at-most-five-group typed ports | all five owner witnesses traverse the production facade |
|
|
1822
|
+
|
|
1823
|
+
The five focused witnesses are Codex no-rollout binding, human handoff,
|
|
1824
|
+
monitor recovery, Session acceptance, and terminal send gates. Together they
|
|
1825
|
+
cover virgin and deferred acceptance, process drift/quarantine, crash recovery,
|
|
1826
|
+
uncertainty, Turn construction, and no-replay behavior without assigning
|
|
1827
|
+
lifecycle, callback, or generic ledger-recovery ownership to this slice.
|
|
1828
|
+
|
|
1829
|
+
## Terminal identity authority CLI composition
|
|
1830
|
+
|
|
1831
|
+
The identity-authority slice moves the exact 37-function inventory for terminal
|
|
1832
|
+
routing, process-incarnation and verified-dead observation, managed Session
|
|
1833
|
+
logical/native identity, Codex companion and pre-materialization fences,
|
|
1834
|
+
binding selection/conflict/materialization/reattach, and verified-empty deferred
|
|
1835
|
+
authority observation out of `cli-core.ts`. It deliberately leaves submission
|
|
1836
|
+
acceptance refinement/persistence/quarantine, current-native-identity polling,
|
|
1837
|
+
managed Turn creation, deferred detach/adoption state machines, repository,
|
|
1838
|
+
monitor, callback, and lifecycle mutation in their existing owners.
|
|
1839
|
+
|
|
1840
|
+
Against exact parent `918812c5b541d5586595c4ea793df370f538d3e4`,
|
|
1841
|
+
`src/cli-core.ts` falls from 12,721 to 11,468 physical lines (-1,253). Total
|
|
1842
|
+
production TypeScript changes from 88,732 to 89,156 (+424, 33.84 percent of the
|
|
1843
|
+
core movement), below the preferred 450-line overhead target. Architecture
|
|
1844
|
+
validation reports 50 domains, 104 production modules, 589 static import edges,
|
|
1845
|
+
and zero cycles. The factory has four explicit invocation-scoped groups
|
|
1846
|
+
(`runtime`, `store`, `authority`, and `environment`) and exports no singleton or
|
|
1847
|
+
mutable process-global runtime. The composition root projects provider ports
|
|
1848
|
+
directly from `terminalRuntime(options)` and acceptance-owned identity/Session
|
|
1849
|
+
ports directly from `terminalAcceptanceCliFacade`; it adds no interim owner.
|
|
1850
|
+
|
|
1851
|
+
The 78-line data-only service receives only projected native identity, process
|
|
1852
|
+
incarnation, companion, revision, status, and binding-token facts. It imports no
|
|
1853
|
+
filesystem/path/process-source, Store, managed Session, resolved terminal, raw
|
|
1854
|
+
JSON, lock, or `Record<..., any>` API. It owns only the moved exact-lifecycle
|
|
1855
|
+
fallback, deterministic companion uniqueness, and verified-empty snapshot
|
|
1856
|
+
comparison. The 1,599-line CLI adapter retains provider/process observation,
|
|
1857
|
+
Store reads, one managed-Session CAS reattach write, and explicit terminal
|
|
1858
|
+
projection. It reuses `terminal-binding-authority`,
|
|
1859
|
+
`terminal-authority-policy`, `terminal-dispatch-execution`, action projection,
|
|
1860
|
+
lifecycle verification, submission acceptance, verified-dead policy, and the
|
|
1861
|
+
runtime provider rather than copying rollout, fence, token, companion,
|
|
1862
|
+
status-card, or transition reducers.
|
|
1863
|
+
|
|
1864
|
+
Observation and mutation order remain fail closed. Exact bound-process proof
|
|
1865
|
+
short-circuits envelope, binding, then accepted-submission evidence before
|
|
1866
|
+
consulting the complete process inventory. Stored status-card identity remains
|
|
1867
|
+
preferred only under the committed companion/predecessor fence. Codex process
|
|
1868
|
+
birth lookup stays lazy, and Claude still rejects a missing process UUID before
|
|
1869
|
+
any fallback. Raw reattach performs exclusive-ownership observation, reloads
|
|
1870
|
+
the exact Session, revalidates revision plus binding token, then writes one
|
|
1871
|
+
generation-incremented Session CAS. Verified-empty handoff checks the initial
|
|
1872
|
+
snapshot, process incarnation, absent native identity, terminal status and
|
|
1873
|
+
dispatch readiness, then reloads and revalidates the Session before transition
|
|
1874
|
+
and composer gates. No new lock or durable-file order is introduced.
|
|
1875
|
+
|
|
1876
|
+
Every new function meets the preferred limits: the maximum adapter span is 95
|
|
1877
|
+
lines and the conservative maximum approximate complexity is c17; the service
|
|
1878
|
+
is smaller. Direct fast proofs cover malformed/fail-closed facts, deterministic
|
|
1879
|
+
companion selection, lazy process-birth lookup, parallel async-execution
|
|
1880
|
+
isolation, the four-group factory boundary, and service infrastructure hygiene.
|
|
1881
|
+
Five retained focused witnesses cover no-rollout/status-card binding, observed
|
|
1882
|
+
handoff/verified-empty authority, native lifecycle identity, Session acceptance,
|
|
1883
|
+
and terminal-send gates. The remaining exact-bound completion detector and
|
|
1884
|
+
requirement predicate stay with completion/recovery composition; endpoint
|
|
1885
|
+
refinement, Store-backed runtime identity, durable request construction, and
|
|
1886
|
+
legacy identity migration remain a later minimal identity-facade prerequisite
|
|
1887
|
+
rather than being duplicated here.
|
|
1888
|
+
|
|
1889
|
+
## Terminal runtime prerequisites and exact completion authority
|
|
1890
|
+
|
|
1891
|
+
The follow-up prerequisite slice closes that deliberately deferred inventory.
|
|
1892
|
+
The single exact-bound Codex completion detector and requirement predicate now
|
|
1893
|
+
live in `terminal-dispatch-completion-cli-adapter.ts`; neither the raw dispatch
|
|
1894
|
+
repository nor recovery adapter imports it. The detector retains
|
|
1895
|
+
accepted-submission -> exact-required -> Codex-source -> exact-anchor -> bound
|
|
1896
|
+
rollout detection order, while its synthetic-acceptance switch is read lazily
|
|
1897
|
+
from the invocation-local CLI environment. Exact completion still uses the one
|
|
1898
|
+
`detectCodexBoundRolloutCompletion` implementation and preserves request-hash
|
|
1899
|
+
fallback, byte identity, diagnostics, pending behavior, and completion metadata.
|
|
1900
|
+
|
|
1901
|
+
Endpoint refinement, Store-backed runtime identity, durable request projection,
|
|
1902
|
+
and legacy terminal-agent identity migration are now methods of the existing
|
|
1903
|
+
identity facade. The earlier temporary `runtimeIdentity` and `durableRequest`
|
|
1904
|
+
callback ports are gone. A fifth typed completion group supplies only the exact
|
|
1905
|
+
requirement predicate. Runtime identity still checks binding id, generation,
|
|
1906
|
+
native thread, PID, terminal incarnation, and committed Codex companion fences
|
|
1907
|
+
before expanding its authority. Durable requests continue to prefer takeover
|
|
1908
|
+
request text and metadata. Endpoint refinement associates and saves only
|
|
1909
|
+
canonical evidence for the same terminal incarnation.
|
|
1910
|
+
|
|
1911
|
+
Legacy migration is split into observation, locked persistence, and reporting
|
|
1912
|
+
functions. Only provider/process observation is downgraded to a warning. The
|
|
1913
|
+
state lock still encloses reload, revalidation, and save; every path releases it
|
|
1914
|
+
in `finally`. A successful save is followed, outside that lock, by durable event
|
|
1915
|
+
append and then runtime logging. Save and event failures propagate. The runtime
|
|
1916
|
+
facade also owns Codex Session-provider selection and active-Session terminal
|
|
1917
|
+
attachment, preserving injected-provider and injected-adapter precedence,
|
|
1918
|
+
fixture truthiness and JSON parsing, production Store fallback, and the original
|
|
1919
|
+
provider/process-source/bridge construction counts.
|
|
1920
|
+
|
|
1921
|
+
Against exact parent `6c83f9efe5b3201c584db3ad2b50cd9e120310ad`,
|
|
1922
|
+
`src/cli-core.ts` falls from 11,468 to 11,066 physical lines (-402). Production
|
|
1923
|
+
TypeScript changes from 89,156 to 89,264 lines (+108, 26.87 percent of the core
|
|
1924
|
+
reduction), below the preferred 160-line overhead target and the 240-line hard
|
|
1925
|
+
cap. Architecture validation reports 51 domains, 105 production modules, 596
|
|
1926
|
+
static import edges, and zero cycles. The three changed facade declarations
|
|
1927
|
+
contain no `any`, `Record<..., any>`, or `ResolvedTerminalConversation`. New
|
|
1928
|
+
functions are below 55 physical lines and approximate c20; the expanded identity
|
|
1929
|
+
facade retains its pre-existing 95-line/c17 maxima, below both hard limits.
|
|
1930
|
+
|
|
1931
|
+
Direct fast proofs cover dynamic synthetic environment lookup; accepted, source,
|
|
1932
|
+
anchor, and real byte-detector order; exact binding/generation/thread/PID/
|
|
1933
|
+
incarnation and companion fences; takeover-first durable requests; canonical
|
|
1934
|
+
endpoint save; observation-only warning behavior; lock/reload/save/unlock/event/
|
|
1935
|
+
log order; save and event error propagation; provider injection, fixture
|
|
1936
|
+
truthiness, JSON validation, and active provider/source/bridge call counts. Four
|
|
1937
|
+
targeted integration witnesses retain exact monitor recovery, Session acceptance,
|
|
1938
|
+
terminal send gates, and import-time facade wiring.
|
|
1939
|
+
|
|
1940
|
+
## Native lifecycle context, listing, and inspection CLI composition
|
|
1941
|
+
|
|
1942
|
+
The native-lifecycle Vertical A slice moves the exact 21-function inventory for
|
|
1943
|
+
binding tokens, lifecycle terminal resolution, query-port composition,
|
|
1944
|
+
workspace and exclusive-ownership observation, current lifecycle snapshots,
|
|
1945
|
+
resumable-thread listing, and the closed native status inspection out of
|
|
1946
|
+
`cli-core.ts`. It also moves terminal Store-authority and orphan projections
|
|
1947
|
+
behind the typed dispatch-recovery facade and keeps Codex latent-clear parsing,
|
|
1948
|
+
composer checks, and candidate-provider precedence in one command-scoped CLI
|
|
1949
|
+
adapter. Native new/resume/reconcile transition, recovery, verification,
|
|
1950
|
+
settlement, deferred handoff, acceptance, callback, and monitor state machines
|
|
1951
|
+
remain in their existing owners.
|
|
1952
|
+
|
|
1953
|
+
Against exact parent `81feac294d5a62ea8309c6e96a66c042ebf239b8`,
|
|
1954
|
+
`src/cli-core.ts` falls from 11,066 to 9,868 physical lines (-1,198). Total
|
|
1955
|
+
production TypeScript changes from 89,264 to 89,498 (+234, 19.53 percent of the
|
|
1956
|
+
core movement), below the preferred 350-line and hard 550-line overhead limits.
|
|
1957
|
+
Architecture validation reports 51 domains, 106 production modules, 615 static
|
|
1958
|
+
import edges, and zero cycles. The factory has exactly five explicit,
|
|
1959
|
+
invocation-scoped groups (`runtime`, `identity`, `state`, `terminalList`, and
|
|
1960
|
+
`output`) and exports no mutable singleton. Codex lifecycle-candidate selection
|
|
1961
|
+
delegates directly to the runtime facade's dedicated provider factory, retaining
|
|
1962
|
+
the invocation-local override before production Store fallback.
|
|
1963
|
+
|
|
1964
|
+
`currentSnapshot` is the only lifecycle snapshot sequencer. It resolves the
|
|
1965
|
+
claimed Codex companion context through `terminalIdentityAuthority`, observes
|
|
1966
|
+
the current native identity through `terminalAcceptanceCliFacade`, selects or
|
|
1967
|
+
materializes the managed Session, refines it through the acceptance owner when
|
|
1968
|
+
requested, derives the logical identity and companion set through the identity
|
|
1969
|
+
facade, performs exclusive ownership before returning a frozen data-only
|
|
1970
|
+
snapshot, and never returns a terminal adapter. Vertical B requests adapter
|
|
1971
|
+
behavior separately through the facade, so no full terminal or executable
|
|
1972
|
+
capability leaks into snapshot facts.
|
|
1973
|
+
|
|
1974
|
+
Native inspection retains the exact safety boundary: the terminal lock remains
|
|
1975
|
+
held through output presentation; `/status` is the only accepted plan; Enter is
|
|
1976
|
+
dispatched exactly once; a fresh terminal, binding token, agent version,
|
|
1977
|
+
identity, ownership, readiness, and composer are revalidated immediately before
|
|
1978
|
+
Enter; two consecutive fresh observations with the same evidence fingerprint
|
|
1979
|
+
are required; modal dismissal revalidates the same facts immediately before its
|
|
1980
|
+
single key sequence; and final status plus empty-composer proof precedes output.
|
|
1981
|
+
Only a pre-input `NativeInspectionSubmissionError` remains safely retryable;
|
|
1982
|
+
possible input and every post-Enter uncertainty retain the do-not-retry result.
|
|
1983
|
+
|
|
1984
|
+
The TypeScript compiler AST inventory contains 68 functions in the new adapter;
|
|
1985
|
+
every one stays below the preferred limits (maximum 64 physical lines and
|
|
1986
|
+
approximate complexity c14). Direct evidence
|
|
1987
|
+
fixes canonical and legacy binding-token bytes plus double getter order,
|
|
1988
|
+
snapshot sequencing and exact data-only keys, one-Enter/two-observation/final-
|
|
1989
|
+
revalidation ordering with lock-held presentation, parallel async provider
|
|
1990
|
+
isolation, the five-group factory boundary, and declaration/core forbidden
|
|
1991
|
+
patterns. The four focused witnesses are Claude native inspection,
|
|
1992
|
+
native-thread lifecycle, native ownership, and the Codex no-rollout native-
|
|
1993
|
+
inspection cases.
|
|
1994
|
+
|
|
1995
|
+
## Deferred foreground and observed handoff CLI facade
|
|
1996
|
+
|
|
1997
|
+
This slice moves the exact 23-function deferred/verified-empty/observed-handoff
|
|
1998
|
+
inventory (1,733 physical function-span lines) out of `cli-core.ts`. It owns
|
|
1999
|
+
safe-aborted deferred retry validation, verified-empty detach and transport
|
|
2000
|
+
boundaries, deferred preparation/application/recovery composition, observed
|
|
2001
|
+
handoff token/selector/target/adoption/transport boundaries, and nonterminal
|
|
2002
|
+
transfer guards. Ordinary replay, deferred reducers and repositories,
|
|
2003
|
+
submission acceptance, identity authority, lifecycle commands, callbacks,
|
|
2004
|
+
monitoring, and `runObservedHandoffClose` remain with their existing owners.
|
|
2005
|
+
|
|
2006
|
+
Against exact parent `d4cb4f108ce240a006c7eebb56e2ce5cc9d70c3f`,
|
|
2007
|
+
`src/cli-core.ts` falls from 9,868 to 8,119 physical lines (-1,749). Total
|
|
2008
|
+
production TypeScript changes from 89,498 to 89,873 (+375), meeting the
|
|
2009
|
+
preferred 450-line overhead target and the 1,650–1,850 core-reduction target.
|
|
2010
|
+
Architecture validation reports 52 domains, 109 production modules, 643 static
|
|
2011
|
+
import edges, zero cycles, and one retained `cli-core.ts` importer. The new
|
|
2012
|
+
owner has three modules and exactly five focused integration witnesses.
|
|
2013
|
+
|
|
2014
|
+
`terminal-handoff-facts.ts` and `TerminalHandoffApplicationService` own only
|
|
2015
|
+
neutral zero-input chronology and ordered authority-thunk evaluation. They
|
|
2016
|
+
import no filesystem/path API, Store or Session repository, locks, raw JSON,
|
|
2017
|
+
full terminal object, or `Record<..., any>`. The CLI adapter retains concrete
|
|
2018
|
+
terminal, Session, ledger, and path translation. Its invocation-local factory
|
|
2019
|
+
has exactly five groups (`runtime`, `identity`, `acceptance`, `authority`, and
|
|
2020
|
+
`repository`); repository includes the already-authenticated transaction-shell
|
|
2021
|
+
operations. `identity` is the actual `terminalIdentityAuthority` facade type,
|
|
2022
|
+
not a copied identity port list. Acceptance observation and Turn checks remain
|
|
2023
|
+
direct projections of `terminalAcceptanceCliFacade`.
|
|
2024
|
+
|
|
2025
|
+
The recovery seam is explicit for downstream lifecycle composition.
|
|
2026
|
+
`recoverDeferredCodexForegroundTransferBeforeMutation` is entered while the
|
|
2027
|
+
caller owns the exact terminal lock; it creates the canonical transaction scope
|
|
2028
|
+
with a no-op terminal acquisition, then acquires the Store writer lease.
|
|
2029
|
+
`recoverDeferredCodexForegroundTransferWhileWriterLease` accepts the resulting
|
|
2030
|
+
typed canonical scopes/resources, and only `withDeferredForegroundRecoveryScope`
|
|
2031
|
+
may add the conversation state capability. Transfers without a state path use
|
|
2032
|
+
the writer capability directly. Thus the retained order is terminal -> writer
|
|
2033
|
+
-> state, and no service reconstructs a raw lock or held-lock flag. Fresh
|
|
2034
|
+
handoff identity/status observation is exposed as the invocation-scoped
|
|
2035
|
+
`observedExternalHandoffIdentity`; known roots and companions remain the
|
|
2036
|
+
invocation-scoped `terminalIdentityAuthority` operation rather than being
|
|
2037
|
+
reconstructed here.
|
|
2038
|
+
|
|
2039
|
+
Safe retry remains fail closed. Only an exact `aborted` receipt with
|
|
2040
|
+
`safe_to_retry=true`, zero-input chronology, canonical state/log paths, exact
|
|
2041
|
+
terminal route and process incarnation, one byte-identical canonical receipt,
|
|
2042
|
+
matching request hash, resolved zero-input ledger, and exact restored Session
|
|
2043
|
+
CAS authority may retry. A possible-input stage never takes this route.
|
|
2044
|
+
Verified-empty detach revalidates the source snapshot and identity boundary
|
|
2045
|
+
before its Session CAS. Observed adoption retains the durable order `prepared
|
|
2046
|
+
transition -> prepared ledger -> source transitioning -> fresh observation ->
|
|
2047
|
+
verified transition -> verified ledger -> Session commit -> committed
|
|
2048
|
+
transition -> resolved ledger`. Once the durable transition is verified or
|
|
2049
|
+
committed, catch handling rethrows and never downgrades it to uncertain.
|
|
2050
|
+
|
|
2051
|
+
The two previously over-complex boundaries are now below the hard gate:
|
|
2052
|
+
safe-aborted retry is 148 lines/c9 and observed-handoff transport is 166/c28.
|
|
2053
|
+
The reviewed preferred-target exceptions are:
|
|
2054
|
+
|
|
2055
|
+
| Function | LOC / approximate complexity |
|
|
2056
|
+
| --- | ---: |
|
|
2057
|
+
| `maybeAdoptObservedExternalThread` | 322 / c35 |
|
|
2058
|
+
| `assertObservedHandoffTransportBoundary` | 166 / c28 |
|
|
2059
|
+
| `prepareDeferredCodexForegroundBinding` | 152 / c2 |
|
|
2060
|
+
| `safeAbortedDeferredRetrySourceSession` | 148 / c9 |
|
|
2061
|
+
| `recoverDeferredCodexForegroundTransferWhileWriterLease` | 123 / c1 |
|
|
2062
|
+
| `maybeDetachVerifiedEmptyCodexSource` | 104 / c9 |
|
|
2063
|
+
|
|
2064
|
+
Direct fast evidence records parallel factory/capability isolation, selector
|
|
2065
|
+
WeakMap isolation, getter and original-error priority, zero-input chronology,
|
|
2066
|
+
canonical receipt/hash/route byte ordering, monotonic handoff writes,
|
|
2067
|
+
verified-state non-downgrade, terminal/writer/state capability order, neutral
|
|
2068
|
+
service imports, and direct identity-facade composition. The five retained
|
|
2069
|
+
focused witnesses are Codex no-rollout binding, human handoff adoption,
|
|
2070
|
+
dispatch recovery, Session acceptance, and terminal-send gates. They cover the
|
|
2071
|
+
real verified-empty, deferred crash/retry, observed adoption, acceptance, and
|
|
2072
|
+
pre-input transport paths without assigning lifecycle, callback, monitor, or
|
|
2073
|
+
ordinary replay ownership to this facade.
|
|
2074
|
+
|
|
2075
|
+
## Callback CLI and outbox composition facade
|
|
2076
|
+
|
|
2077
|
+
The callback CLI slice moves the exact nine-function command, transaction,
|
|
2078
|
+
outbox-composition, prepared-result presentation, process-delivery recording,
|
|
2079
|
+
and OpenClaw transport inventory out of `cli-core.ts`. The new
|
|
2080
|
+
`callback-cli-adapter.ts` remains raw CLI infrastructure: it delegates every
|
|
2081
|
+
callback transition to the existing callback outbox service, settlement,
|
|
2082
|
+
policy, and OpenClaw transport owners and introduces no callback state machine.
|
|
2083
|
+
The outbox service boundary changes only mechanically from six port groups to
|
|
2084
|
+
five by placing `resolveCompletionDispatch` beside the other authority ports.
|
|
2085
|
+
|
|
2086
|
+
Against exact parent `0c2d4258094f47302bc8265eb98d4a05f5b44305`,
|
|
2087
|
+
`src/cli-core.ts` falls from 8,119 to 7,941 physical lines (-178). Total
|
|
2088
|
+
production TypeScript changes from 89,873 to 89,933 lines (+60, 33.71 percent
|
|
2089
|
+
of the core movement), meeting the preferred 60-line overhead target and the
|
|
2090
|
+
120-line hard cap. Architecture validation reports 52 domains, 110 production
|
|
2091
|
+
modules, 651 static import edges, and zero cycles. The 240-line adapter has four
|
|
2092
|
+
invocation-scoped groups (`state`, `authority`, `retry`, and `runtime`), exports
|
|
2093
|
+
only its factory at runtime, and uses async-local binding rather than mutable
|
|
2094
|
+
process-global configuration. Its declaration contains no `any`,
|
|
2095
|
+
`Record<..., any>`, or resolved-terminal capability.
|
|
2096
|
+
|
|
2097
|
+
The transaction chronology is unchanged. A normal callback holds writer then
|
|
2098
|
+
state authority through required-message validation and outbox preparation,
|
|
2099
|
+
releases state then writer, and only then performs delivery and presentation.
|
|
2100
|
+
A manual retry loads its selected Turn, takes writer authority, reloads the
|
|
2101
|
+
fresh Turn, applies the canonical handoff facade's nonterminal-transfer fence,
|
|
2102
|
+
releases the writer, and only then enters accepted recovery or retry delivery.
|
|
2103
|
+
Settlement keeps its existing state transaction. Delivery never holds either
|
|
2104
|
+
outer lock. Fresh preparation retains message-before-path/Store validation and
|
|
2105
|
+
the existing message/event/monitor/state/runtime-log sequence; progress,
|
|
2106
|
+
accepted transport, success, failure, and bounded retry remain owned by the
|
|
2107
|
+
unchanged outbox service and settlement. Accepted transport followed by an
|
|
2108
|
+
observation error still settles as delivered. Process delivery still appends
|
|
2109
|
+
the redacted durable event before its redacted runtime log.
|
|
2110
|
+
|
|
2111
|
+
All adapter functions stay within the preferred limits (maximum 34 physical
|
|
2112
|
+
lines and approximate c2, excluding nested function bodies). Direct recording
|
|
2113
|
+
tests prove writer/state release before presentation, fresh deferred fencing
|
|
2114
|
+
before retry, accepted-transport recovery, nested facade isolation, compiled
|
|
2115
|
+
lock and redaction order, the four-group boundary, factory-only exports, and
|
|
2116
|
+
declaration prohibitions. The focused real-CLI witnesses remain callback CLI,
|
|
2117
|
+
Claude callback, monitor approval context, and monitor recovery; they exercise
|
|
2118
|
+
ordinary and recovered single emission, retry, completion/approval preparation,
|
|
2119
|
+
transport acceptance, and monitor consumption without duplicating callback
|
|
2120
|
+
authority.
|
|
2121
|
+
|
|
2122
|
+
## Native lifecycle transition application
|
|
2123
|
+
|
|
2124
|
+
This slice moves the exact 13-function native lifecycle transition inventory
|
|
2125
|
+
(1,344 physical function-span lines) out of `cli-core.ts`. The new
|
|
2126
|
+
`native-thread-transition-application.ts` owns new-thread, exact resume,
|
|
2127
|
+
binding reconciliation, pre-mutation lifecycle recovery, transition
|
|
2128
|
+
settlement composition, and terminal-ready verification. The separate
|
|
2129
|
+
`native-thread-lifecycle-ledger-cli-adapter.ts` owns exact lifecycle ledger CAS
|
|
2130
|
+
against the existing terminal-dispatch repository. Candidate query,
|
|
2131
|
+
verification, settlement, recovery, ledger codec, identity, acceptance, and
|
|
2132
|
+
Session repositories remain with their existing owners; no reducer or
|
|
2133
|
+
repository is copied.
|
|
2134
|
+
|
|
2135
|
+
Against exact parent `98e3566f0e15e4a6ff0ffff6efa85cdde532ee77`,
|
|
2136
|
+
`src/cli-core.ts` falls from 7,941 to 6,483 physical lines (-1,458). Total
|
|
2137
|
+
production TypeScript changes from 89,933 to 90,578 (+645), inside the hard
|
|
2138
|
+
650-line overhead gate. Architecture validation reports 52 domains, 112
|
|
2139
|
+
production modules, 669 static import edges, zero cycles, and one retained
|
|
2140
|
+
`cli-core.ts` importer.
|
|
2141
|
+
|
|
2142
|
+
The invocation-local CLI bounded I/O shell composes exactly five port groups
|
|
2143
|
+
(`runtime`, `lifecycle`, `state`, `authority`, and `mutation`). It extends the
|
|
2144
|
+
existing lifecycle query facade at the CLI composition root. Observed handoff
|
|
2145
|
+
identity and writer-scope deferred recovery call the merged terminal-handoff
|
|
2146
|
+
facade directly; verified-empty detach and transport continue through that
|
|
2147
|
+
same facade. Recovery services receive only projected terminal facts plus scoped
|
|
2148
|
+
capabilities. Binding reconciliation likewise receives data-only terminal and
|
|
2149
|
+
status facts, while the CLI adapter retains the exact runtime terminal needed
|
|
2150
|
+
for subsequent infrastructure calls.
|
|
2151
|
+
|
|
2152
|
+
The mutation sequence remains terminal lock -> Store writer lease. A fresh
|
|
2153
|
+
terminal route is re-resolved after both capabilities are authenticated.
|
|
2154
|
+
Resume snapshot expiry, action fingerprint, and the complete candidate set are
|
|
2155
|
+
revalidated before persistence and again at their mutation-adjacent fences.
|
|
2156
|
+
The durable order remains prepared transition -> prepared ledger -> source
|
|
2157
|
+
transitioning -> dispatching transition/ledger -> input -> submitted
|
|
2158
|
+
transition/ledger -> verification -> verified transition -> target ownership
|
|
2159
|
+
-> Session commit -> committed transition -> resolved ledger -> presentation.
|
|
2160
|
+
Presentation therefore remains inside both locks. Only a
|
|
2161
|
+
`TerminalInputNotStartedError` with no text-injection observation can take the
|
|
2162
|
+
zero-input abort path; possible input remains uncertain, quarantined, and
|
|
2163
|
+
do-not-retry.
|
|
2164
|
+
|
|
2165
|
+
Compiler-AST evidence covers every function-like declaration in the new
|
|
2166
|
+
application. The maximum span is 445 physical lines and maximum approximate
|
|
2167
|
+
complexity is c44, below the hard 500/c50 gates. Direct tests record exact
|
|
2168
|
+
ledger load/authority/save precedence, scoped recovery resources, verified
|
|
2169
|
+
commit and uncertain failure order, resolved-ledger-before-presentation, and
|
|
2170
|
+
presentation before writer/terminal lock release. Fast and focused lifecycle,
|
|
2171
|
+
recovery, ownership, Codex sticky-rollout, and stale-resume witnesses retain
|
|
2172
|
+
the real CLI behavior.
|
|
2173
|
+
|
|
2174
|
+
## Terminal monitor state and collateral CLI facade
|
|
2175
|
+
|
|
2176
|
+
This slice moves the exact 14-function monitor state inventory plus its
|
|
2177
|
+
adjacent durable state/fact preparation out of `cli-core.ts`: uncertain-dispatch
|
|
2178
|
+
collateral fencing and repair evidence, approval notification persistence and
|
|
2179
|
+
clear, activity and detector diagnostics, stalled-state notification,
|
|
2180
|
+
callback/local-completion recovery, startup eligibility, and monitor service
|
|
2181
|
+
port composition. The state facade deliberately does not absorb process-owner
|
|
2182
|
+
inspection, legacy-owner decisions, watchdog supervision, monitor launch, or
|
|
2183
|
+
launch-event presentation. Those responsibilities now belong to the subsequent
|
|
2184
|
+
terminal monitor supervision facade documented below, rather than
|
|
2185
|
+
`cli-core.ts`.
|
|
2186
|
+
|
|
2187
|
+
Against exact parent `240732e4d0a654abb4f88a01020bd93734f0d020`,
|
|
2188
|
+
`src/cli-core.ts` falls from 6,212 to 4,547 physical lines (-1,665). Total
|
|
2189
|
+
production TypeScript changes from 90,711 to 91,535 lines (+824, 49.49 percent
|
|
2190
|
+
of the core movement), so production overhead remains below the moved core.
|
|
2191
|
+
Architecture validation reports 54 domains, 115 production modules, 712 static
|
|
2192
|
+
import edges, zero cycles, and one retained `cli-core.ts` importer.
|
|
2193
|
+
|
|
2194
|
+
`terminal-monitor-state-reconciliation-service.ts` is data-only and has four
|
|
2195
|
+
port groups (`state`, `completion`, `callbacks`, and `authority`). It imports no
|
|
2196
|
+
filesystem/path API, raw lock, Store, Session, resolved terminal, raw JSON, or
|
|
2197
|
+
`Record<..., any>`. Its reconciliation order remains local completion ->
|
|
2198
|
+
callback recovery -> terminal-bridge filter -> legacy identity migration ->
|
|
2199
|
+
verified-dead settlement -> deferred recovery -> virgin acceptance recovery ->
|
|
2200
|
+
binding assertion -> eligibility. Handled local, callback, dead-process, and
|
|
2201
|
+
ineligible results stop every later observation.
|
|
2202
|
+
|
|
2203
|
+
The CLI adapter has exactly five dependency groups (`dispatch`, `acceptance`,
|
|
2204
|
+
`authority`, `callbacks`, and `runtime`). It calls the merged
|
|
2205
|
+
`callbackCliFacade`, terminal-dispatch repository/recovery,
|
|
2206
|
+
`terminalAcceptanceCliFacade`, `terminalHandoffCliFacade`, and identity
|
|
2207
|
+
authority directly; it contains no copied callback, deferred, acceptance, or
|
|
2208
|
+
dispatch reducer. Command-selected Store authority is retained for terminal
|
|
2209
|
+
send locks, while state-path-derived Store authority is retained for writer
|
|
2210
|
+
leases, collateral repair, and verified-dead settlement.
|
|
2211
|
+
|
|
2212
|
+
The existing monitor application still samples one poll snapshot for status
|
|
2213
|
+
and screen facts. Prepared recovery preserves terminal -> writer -> state lock
|
|
2214
|
+
order; presentation stays inside the required lock scope. Approval state is
|
|
2215
|
+
saved before its event and outbox preparation, duplicate/recovery reads retain
|
|
2216
|
+
their original order, and approval/stalled callback delivery begins only after
|
|
2217
|
+
the state and writer locks release. Verified-dead completion calls the canonical
|
|
2218
|
+
prepared callback exactly once. Superseded binding remains a non-error skip,
|
|
2219
|
+
the subsequent supervision facade directly classifies raw `LOCK_TIMEOUT` for
|
|
2220
|
+
only its handoff and singleton process locks, and state/application deferral
|
|
2221
|
+
retains typed `StoreLockTimeoutError` plus the existing raw
|
|
2222
|
+
terminal/conversation timeout path.
|
|
2223
|
+
|
|
2224
|
+
All new functions remain below the hard 500-line/c50 gates. The transparent
|
|
2225
|
+
preferred-limit exceptions are the 209-line/c1 service-port composition table,
|
|
2226
|
+
the 122-line/c47 fail-closed collateral evidence predicate, and its
|
|
2227
|
+
64-line/c22 exact owner predicate; splitting either evidence predicate would
|
|
2228
|
+
obscure its ordered short-circuit proof. The data-only service maximum is
|
|
2229
|
+
63 lines/c8. Direct fast tests record resource identity and post-scope data,
|
|
2230
|
+
exact port/getter/error order, optional zero/null fields, prepared completion
|
|
2231
|
+
byte facts, canonical facade wiring, four/five-group declarations, and
|
|
2232
|
+
forbidden imports. The five focused CLI witnesses are Claude callback, monitor
|
|
2233
|
+
approval context, monitor lifecycle, monitor recovery, and Session acceptance.
|
|
2234
|
+
|
|
2235
|
+
## Maintenance command facade
|
|
2236
|
+
|
|
2237
|
+
The renew, raw/managed cancel, observed-handoff close, generic managed close,
|
|
2238
|
+
and orphan/lifecycle dispatch-close slice now lives in
|
|
2239
|
+
`terminal-maintenance-cli-adapter.ts`. The adapter is a bounded CLI I/O shell;
|
|
2240
|
+
it composes the existing terminal identity, acceptance, handoff, list, native
|
|
2241
|
+
lifecycle, dispatch repository, and verified-dead recovery authorities rather
|
|
2242
|
+
than copying a reducer, receipt, repository, or CAS transition. The subsequent
|
|
2243
|
+
terminal monitor supervision facade owns monitor process supervision, monitor
|
|
2244
|
+
reconciliation, and startup reconciliation. Maintenance routes its monitor
|
|
2245
|
+
start and lock-version facts through that typed facade; ordinary delegate/send
|
|
2246
|
+
presentation remains with its existing owner.
|
|
2247
|
+
|
|
2248
|
+
Against exact parent `8683b42c248b2310c59165ba712ecc943da3d775`,
|
|
2249
|
+
`src/cli-core.ts` falls from 4,547 to 3,419 physical lines (-1,128). Total
|
|
2250
|
+
production TypeScript changes from 91,535 to 91,961 lines (+426, 37.77 percent
|
|
2251
|
+
of the core movement), meeting the preferred 450-line and hard 650-line
|
|
2252
|
+
overhead gates. Architecture validation reports 54 domains, 116 production
|
|
2253
|
+
modules, 742 static import edges, zero cycles, and one retained `cli-core.ts`
|
|
2254
|
+
importer. The now 1,555-line adapter exposes only its factory at runtime and binds
|
|
2255
|
+
four invocation-scoped port groups (`runtime`, `identity`, `authority`, and
|
|
2256
|
+
`repository`) through async-local context. Its public option surface is
|
|
2257
|
+
`Readonly<Record<string, unknown>>`; its source and declaration contain no
|
|
2258
|
+
`any`, raw JSON codec, or resolved-terminal capability API.
|
|
2259
|
+
|
|
2260
|
+
Renew preserves selector/migration, status, verified-dead and uncertain-submit
|
|
2261
|
+
fences before terminal availability, then reloads under its state lock,
|
|
2262
|
+
revalidates binding and hard lifetime, persists state before the renewal event,
|
|
2263
|
+
and launches/presents only after releasing state. Raw cancel takes terminal
|
|
2264
|
+
then writer authority. Managed cancel preserves its distinct authorities:
|
|
2265
|
+
the command-selected Store keys only the terminal lock, the state-file lock is
|
|
2266
|
+
second, and the state-path-derived Store keys the writer lease third. It
|
|
2267
|
+
releases writer -> state -> terminal. Its fresh Turn, terminal incarnation,
|
|
2268
|
+
exact dispatch owner, bridge cancellation, event, state, and presentation order
|
|
2269
|
+
is unchanged, and presentation stays inside the authenticated transaction.
|
|
2270
|
+
|
|
2271
|
+
Observed-handoff close retains terminal -> writer -> state, fresh Turn and
|
|
2272
|
+
Session loads, native identity observation, exclusive target ownership, exact
|
|
2273
|
+
handoff token and dispatch-generation validation, then Turn save -> ledger
|
|
2274
|
+
resolve -> close event -> presentation. Generic close keeps its observed
|
|
2275
|
+
handoff fence and verified-dead completion-first recovery, persists the closed
|
|
2276
|
+
Turn before dispatch resolution and the append-only close event, and presents
|
|
2277
|
+
only after those effects. Orphan/lifecycle dispatch close continues to
|
|
2278
|
+
reconcile incarnation and deferred-transfer authority before lifecycle
|
|
2279
|
+
recovery or exact message-id resolution. Possible terminal input is never
|
|
2280
|
+
retried or downgraded.
|
|
2281
|
+
|
|
2282
|
+
Every extracted function remains below the hard 500/c50 gates. The cohesive
|
|
2283
|
+
CLI-shell exceptions to the preferred 100/c20 target are:
|
|
2284
|
+
|
|
2285
|
+
| Function or nested transaction | LOC / approximate complexity |
|
|
2286
|
+
| --- | ---: |
|
|
2287
|
+
| `runClose` | 264 / c8 |
|
|
2288
|
+
| generic close fresh-state transaction | 205 / c24 |
|
|
2289
|
+
| `runRenew` | 192 / c32 |
|
|
2290
|
+
| dispatch-close transaction | 184 / c22 |
|
|
2291
|
+
| observed-handoff close transaction | 176 / c29 |
|
|
2292
|
+
| `assertGenericCloseDoesNotBypassObservedHandoff` | 138 / c19 |
|
|
2293
|
+
|
|
2294
|
+
Direct recording tests prove concurrent factory isolation, factory-only
|
|
2295
|
+
exports, typed declarations, raw-cancel reverse release, managed-cancel
|
|
2296
|
+
terminal/state/writer order with distinct command/state Store keys, every
|
|
2297
|
+
acquire/release error priority, and the getter/error/persistence tables for all
|
|
2298
|
+
three commands. The five focused files are the maintenance facade, control
|
|
2299
|
+
locks, monitor lifecycle, human-handoff adoption, and native lifecycle
|
|
2300
|
+
recovery witnesses; together they retain real CLI cancel/close races, renew,
|
|
2301
|
+
verified-dead completion, observed handoff, and exact lifecycle ledger
|
|
2302
|
+
recovery.
|
|
2303
|
+
|
|
2304
|
+
## Terminal monitor supervision CLI facade
|
|
2305
|
+
|
|
2306
|
+
This slice moves 16 named monitor process-supervision functions spanning 706
|
|
2307
|
+
physical function-span lines, plus the
|
|
2308
|
+
`DEFAULT_MONITOR_POLL_INTERVAL_MS` constant, out of `cli-core.ts` into
|
|
2309
|
+
`terminal-monitor-supervision-cli-adapter.ts`:
|
|
2310
|
+
`spawnDetachedTerminalMonitor`,
|
|
2311
|
+
`startTerminalBridgeMonitorForConversation`,
|
|
2312
|
+
`ensureTerminalBridgeMonitorAfterApproval`, `runReconcileMonitors`,
|
|
2313
|
+
`reconcileMonitors`, `latestTerminalBridgeMonitorLaunchPid`,
|
|
2314
|
+
`prepareTerminalBridgeMonitorReconciliation`, `runMonitor`,
|
|
2315
|
+
`startCallbackRetryMonitor`, `runCallbackRetryMonitor`,
|
|
2316
|
+
`runTerminalBridgeMonitorHandoff`, `runTerminalBridgeMonitor`,
|
|
2317
|
+
`runTerminalBridgeMonitorWithLock`, `activeTerminalBridgeMonitorOwner`,
|
|
2318
|
+
`terminalBridgeMonitorLockOwner`, and
|
|
2319
|
+
`tryAcquireTerminalBridgeMonitorLock`. The adapter owns only the detached
|
|
2320
|
+
process shell, current/legacy process-owner supervision, watchdog retries,
|
|
2321
|
+
singleton monitor locks, launch presentation, and CLI command routing. Monitor
|
|
2322
|
+
state, acceptance, callback, deferred handoff, terminal-dispatch repository,
|
|
2323
|
+
and terminal runtime behavior continue through their canonical facades and
|
|
2324
|
+
services; no reducer or persistence protocol is copied.
|
|
2325
|
+
|
|
2326
|
+
Against exact parent `cc69f520207e276a4f3a55b0a32dfeb179ea8095`,
|
|
2327
|
+
`src/cli-core.ts` falls from 3,419 to 2,735 physical lines (-684). Total
|
|
2328
|
+
production TypeScript changes from 91,961 to 92,432 lines (+471), below the
|
|
2329
|
+
hard 500-line overhead gate and below the moved core. Architecture validation
|
|
2330
|
+
reports 54 domains, 117 production modules, 750 static import edges, zero
|
|
2331
|
+
cycles, and one retained `cli-core.ts` importer. The adapter exposes only its
|
|
2332
|
+
factory at runtime. Every function remains within the preferred limits; the
|
|
2333
|
+
compiler-AST maximum is 59 physical lines and approximate c8.
|
|
2334
|
+
|
|
2335
|
+
The invocation-local boundary has exactly five port groups: `state`,
|
|
2336
|
+
`callbacks`, `authority`, `io`, and `runtime`. `state` directly reuses
|
|
2337
|
+
`terminalMonitorStateCliFacade` for service execution, deferral, collateral
|
|
2338
|
+
repair, startup reconciliation, eligibility, and fresh launch preparation.
|
|
2339
|
+
The callback-retry command branch delegates directly to `callbackCliFacade`
|
|
2340
|
+
without acquiring a supervision lock. A normal callback reached through an
|
|
2341
|
+
owned monitor retains its message-generation singleton owner, but the existing
|
|
2342
|
+
callback/state adapters release state and writer locks before actual delivery.
|
|
2343
|
+
`authority` performs legacy identity migration and constructs the terminal
|
|
2344
|
+
bridge lazily.
|
|
2345
|
+
`io` binds detached spawn, the existing file-lock adapter, Store reads/events,
|
|
2346
|
+
and transcript reads. `runtime` supplies only invocation-scoped clock,
|
|
2347
|
+
environment, workspace, process-liveness, logging, and presentation facts.
|
|
2348
|
+
`loadTerminalDispatchLedgerOwner` and `assertManagedTerminalDispatchOwner`
|
|
2349
|
+
remain with dispatch/maintenance composition and were not moved into monitor
|
|
2350
|
+
supervision.
|
|
2351
|
+
|
|
2352
|
+
Startup reconciliation retains the durable observation order: collateral and
|
|
2353
|
+
state-facade reconciliation first (local completion -> callback recovery ->
|
|
2354
|
+
migration -> verified-dead -> deferred -> virgin -> binding -> eligibility),
|
|
2355
|
+
then current owner before legacy owner, fresh launch preparation, detached
|
|
2356
|
+
spawn, and only after successful spawn the exit/launch events, runtime log, and
|
|
2357
|
+
counters. A failed or disabled spawn records no launch event. The approval path
|
|
2358
|
+
also observes the exact generation owner, prepares the process plan, spawns,
|
|
2359
|
+
and only then records reuse, watchdog, or launch presentation.
|
|
2360
|
+
|
|
2361
|
+
The watchdog acquires its generation-specific handoff lock and performs a
|
|
2362
|
+
fresh Turn load on every retry; it never caches status, generation, owner, or
|
|
2363
|
+
launch preparation across sleeps. The owned monitor acquires its
|
|
2364
|
+
message-generation singleton lock before invoking
|
|
2365
|
+
`runTerminalMonitorWithStoreDeferral` and releases it in `finally`. Supervision
|
|
2366
|
+
directly classifies raw `LOCK_TIMEOUT` only while acquiring the handoff and
|
|
2367
|
+
message-generation singleton process locks. State/application deferral
|
|
2368
|
+
continues to classify typed Store timeouts and retains the existing raw
|
|
2369
|
+
terminal/conversation timeout path. The monitor configuration and terminal
|
|
2370
|
+
bridge remain lazy, so a replaced generation exits before timeout validation
|
|
2371
|
+
or effect initialization. Live owners stop duplicate launch, and dead owners
|
|
2372
|
+
are reclaimed by the canonical file-lock adapter. The monitor application
|
|
2373
|
+
service is the sole emitter of the `terminal_bridge_monitor_started` event and
|
|
2374
|
+
runtime log; command, receipt, and maintenance owners may still persist the
|
|
2375
|
+
separate `terminal_bridge_monitor_started_at` state field.
|
|
2376
|
+
|
|
2377
|
+
Maintenance remains the owner of renew/cancel/close durable transitions. Renew
|
|
2378
|
+
persists state and its renewal event under the state lock, releases that lock,
|
|
2379
|
+
then calls the supervision facade's typed `startMonitor`; its persisted
|
|
2380
|
+
`terminal_bridge_monitor_lock_version` now comes from the same facade. This
|
|
2381
|
+
keeps the cross-module durable order state -> renewal event -> state-lock
|
|
2382
|
+
release -> spawn -> launch event. Cancel and close lock stacks and their
|
|
2383
|
+
dispatch authority are unchanged.
|
|
2384
|
+
|
|
2385
|
+
The old black-box paths now have direct invariant witnesses:
|
|
2386
|
+
|
|
2387
|
+
| Old behavior path | New direct invariant | Direct witness |
|
|
2388
|
+
| --- | --- | --- |
|
|
2389
|
+
| monitor plan, approval launch, and process isolation | entry/environment/cwd/spawn/unref order, secret stripping, current-owner reuse, spawn failure without an event, and parallel factory isolation | `terminal-monitor-supervision-cli-adapter.test.ts` |
|
|
2390
|
+
| renew starts monitoring after its durable state transition | maintenance uses typed `startMonitor` and the supervision-owned lock version without changing renewal/cancel lock order | `terminal-maintenance-cli-adapter.test.ts` |
|
|
2391
|
+
| startup state and collateral recovery precede process ownership | the existing state facade returns a data-only handled/candidate result before owner or launch observations | `terminal-monitor-state-reconciliation-service.test.ts` |
|
|
2392
|
+
| monitor generation and Store contention | generation replacement precedes lazy configuration/bridge construction, while Store timeout deferral does not duplicate monitor start | `terminal-monitor-application-service.test.ts` |
|
|
2393
|
+
| live/dead singleton ownership and startup restart | current and legacy owners stop duplicate launch, while the canonical lock shell reclaims an exact dead owner | `terminal-monitor-supervision-cli-adapter.test.ts` and `file-lock-cli-adapter.test.ts` |
|
|
2394
|
+
|
|
2395
|
+
The configured focused integration witnesses remain exactly five shards:
|
|
2396
|
+
`test/shards/agent-cli-claude-callback.test.ts`,
|
|
2397
|
+
`test/shards/agent-cli-monitor-approval-context.test.ts`,
|
|
2398
|
+
`test/shards/agent-cli-monitor-lifecycle.test.ts`,
|
|
2399
|
+
`test/shards/agent-cli-monitor-recovery.test.ts`, and
|
|
2400
|
+
`test/shards/agent-cli-session-acceptance.test.ts`. They retain callback
|
|
2401
|
+
delivery, approval, monitor lifecycle, singleton/restart recovery, and
|
|
2402
|
+
Session-acceptance behavior through the real CLI boundary.
|
|
2403
|
+
|
|
2404
|
+
## Status CLI facade and data-only facts
|
|
2405
|
+
|
|
2406
|
+
The standalone status read, explicit status reconciliation, terminal context,
|
|
2407
|
+
Codex history projection, managed Turn summary, discoverability fact, and idle
|
|
2408
|
+
timeout reconciliation now live in `terminal-status-cli-adapter.ts` and
|
|
2409
|
+
`terminal-status-facts.ts`. The CLI adapter is the bounded Store/runtime I/O
|
|
2410
|
+
shell. The facts module is data-only and imports no filesystem/path API, Store,
|
|
2411
|
+
Session repository, lock, raw JSON codec, or `Record<..., any>`. List,
|
|
2412
|
+
terminal-command, identity, and runtime-completion composition use the same
|
|
2413
|
+
exported fact or typed facade operation; no selector, terminal action, monitor,
|
|
2414
|
+
or callback authority is copied.
|
|
2415
|
+
|
|
2416
|
+
Against exact parent `afa09955b0c5bd528aaaa69cf4d4f92ed1f44079`,
|
|
2417
|
+
`src/cli-core.ts` falls from 2,735 to 2,122 physical lines (-613). This is the
|
|
2418
|
+
bounded fallback slice: the remaining shared state/path selection and runtime
|
|
2419
|
+
completion context stay at the composition root rather than absorbing
|
|
2420
|
+
maintenance, transcript, or monitor supervision merely to increase movement.
|
|
2421
|
+
Total production TypeScript changes from 92,432 to 92,904 lines (+472, 77.00
|
|
2422
|
+
percent of the core movement), below the hard 500-line overhead cap though not
|
|
2423
|
+
the preferred 300-line target. Architecture validation reports 55 domains, 119
|
|
2424
|
+
production modules, 772 static import edges, zero cycles, and one retained
|
|
2425
|
+
`cli-core.ts` importer.
|
|
2426
|
+
|
|
2427
|
+
The adapter exposes only its factory at runtime and has four invocation-scoped
|
|
2428
|
+
port groups (`selection`, `observation`, `reconciliation`, and `projection`).
|
|
2429
|
+
It directly reuses the invocation-local CLI clock/output/log and the existing
|
|
2430
|
+
Store and trace infrastructure appropriate to a bounded CLI adapter. Default
|
|
2431
|
+
`status` performs no writable-Store assertion, state lock, save, event append,
|
|
2432
|
+
idle close, or monitor reconciliation. Only exact `--reconcile` first asserts
|
|
2433
|
+
the Store writable, then calls the narrow monitor-reconciliation port, then
|
|
2434
|
+
runs idle reconciliation and aggregates the two results.
|
|
2435
|
+
|
|
2436
|
+
Terminal-control status retains selector-token fencing before bridge status,
|
|
2437
|
+
then historical context, JSON presentation, and the redacted runtime log.
|
|
2438
|
+
Managed status retains events -> summary/about/recent evidence -> optional
|
|
2439
|
+
trace -> terminal status ordering and its exact insertion order. Codex history
|
|
2440
|
+
prefers the active process session id, otherwise sorts matching-cwd sessions by
|
|
2441
|
+
descending update time, and finally reports screen-only evidence. Claude keeps
|
|
2442
|
+
the adapter display name and explicit historical-context limitation. Public
|
|
2443
|
+
options remain unknown-valued and the emitted declaration contains no `any` or
|
|
2444
|
+
resolved capability object.
|
|
2445
|
+
|
|
2446
|
+
Idle reconciliation still observes the listed snapshot before acquiring the
|
|
2447
|
+
state lock, skips nonterminal candidate-rollout source Turns, treats raw
|
|
2448
|
+
`LOCK_TIMEOUT` as a skip, reloads the fresh Turn under lock, and rechecks fresh
|
|
2449
|
+
idle age. A close remains save -> append-only event -> runtime log, with the
|
|
2450
|
+
state lock released in `finally`. All 51 extracted function-like declarations
|
|
2451
|
+
meet the preferred 100/c20 target: adapter maxima are 60 lines and c12; facts
|
|
2452
|
+
maxima are 48 lines and c8. Direct tests cover concurrent factory isolation,
|
|
2453
|
+
factory-only exports and declarations, zero-write default status, parent-exact
|
|
2454
|
+
managed continuation and screen getter timing, non-Codex getter/error priority,
|
|
2455
|
+
terminal and managed JSON order, newest-cwd Codex fallback and default bounds,
|
|
2456
|
+
exact monitor aggregation, fresh idle locking/log getter order, and lock-timeout
|
|
2457
|
+
skip. The five
|
|
2458
|
+
focused CLI witnesses are CLI UX, management, control locks, monitor recovery,
|
|
2459
|
+
and terminal-send gates.
|
|
2460
|
+
|
|
2461
|
+
## OpenClaw plugin boundary split
|
|
2462
|
+
|
|
2463
|
+
Against exact parent `96b5dbdf775ed55ef0efb9391ab2618167a08966`, the
|
|
2464
|
+
2,830-line `openclaw-plugin.ts` monolith becomes a 67-line composition entry
|
|
2465
|
+
(-2,763). The complete plugin family, including the unchanged 1,068-line
|
|
2466
|
+
helper, moves from 3,898 to 3,974 lines (+76). Total production TypeScript
|
|
2467
|
+
moves from 92,904 to 92,980 lines, so adapter overhead is 2.75 percent of the
|
|
2468
|
+
entry movement and remains below both the preferred 250-line and hard 500-line
|
|
2469
|
+
budgets. The graph moves from 119 to 123 production modules and from 772 to 783
|
|
2470
|
+
static import edges, with zero cycles and the same sole `cli-core.ts` importer.
|
|
2471
|
+
The affected ownership groups contain four OpenClaw plugin modules, two
|
|
2472
|
+
callback-transport modules, and four monitor-supervision modules.
|
|
2473
|
+
|
|
2474
|
+
The split assigns one explicit role to every authority path:
|
|
2475
|
+
|
|
2476
|
+
- `openclaw-plugin-schemas.ts` owns the 14 tool JSON schemas and their exact
|
|
2477
|
+
property, `required`, `not`, `anyOf`, and `allOf` insertion order.
|
|
2478
|
+
- `openclaw-plugin-command-adapter.ts` owns `/akk` parsing/formatting,
|
|
2479
|
+
registration and tool mapping, argv construction, synchronous/asynchronous
|
|
2480
|
+
CLI result/error priority, message identity, and the per-API relay-path
|
|
2481
|
+
`WeakMap`.
|
|
2482
|
+
- `openclaw-plugin-callback-adapter.ts` owns callback identity and target
|
|
2483
|
+
agreement, automatic approval, injection, delivery planning, and shortcut
|
|
2484
|
+
text.
|
|
2485
|
+
- `openclaw-plugin-supervisor.ts` owns startup reconciliation and the
|
|
2486
|
+
non-overlapping immediate/timer/start/stop monitor-supervision loop.
|
|
2487
|
+
- `openclaw-plugin.ts` owns only `definePluginEntry` composition, stable plugin
|
|
2488
|
+
metadata, ordered registration wiring, the default export, and
|
|
2489
|
+
`createOpenClawPluginForTest`.
|
|
2490
|
+
- `openclaw-plugin-helpers.ts` remains the canonical parser/formatter/store-dir
|
|
2491
|
+
helper owner; no helper was copied into a new module.
|
|
2492
|
+
|
|
2493
|
+
The static dependency graph is deliberately one-way:
|
|
2494
|
+
|
|
2495
|
+
```text
|
|
2496
|
+
openclaw-plugin entry
|
|
2497
|
+
|-> callback adapter -> command adapter -> schemas -> executors
|
|
2498
|
+
| \-> helpers -> value guards
|
|
2499
|
+
|-> supervisor -------> command adapter
|
|
2500
|
+
| \-> helpers
|
|
2501
|
+
\-> command adapter ---> helpers
|
|
2502
|
+
```
|
|
2503
|
+
|
|
2504
|
+
Neither callback nor supervisor is imported by command, schemas, or helpers,
|
|
2505
|
+
and no split module imports the entry. The entry still binds the relay path
|
|
2506
|
+
before registering the callback, then registers callback -> supervisor ->
|
|
2507
|
+
slash command/tools in the original observable order. The merged status and
|
|
2508
|
+
terminal-monitor-supervision facades remain unchanged and retain their newer
|
|
2509
|
+
configuration, process ownership, and documentation authorities.
|
|
2510
|
+
|
|
2511
|
+
| Old monolith boundary | Preserved invariant | New authority and proof boundary |
|
|
2512
|
+
| --- | --- | --- |
|
|
2513
|
+
| 14 inline schema objects | byte-identical JSON, tool order, descriptions, required/exclusion semantics | schemas module; 12,657-byte schema SHA-256 contract and exact 14-tool registration witness |
|
|
2514
|
+
| `/akk` plus tool registration/CLI execution | argv/env/cwd/stdout/stderr/exit/JSON/error and getter priority | command adapter; OpenClaw contract argv/result/error and Resume snapshot witnesses |
|
|
2515
|
+
| callback gateway block | modern/legacy Session/Turn identity agreement, auto-approval, injection/delivery/shortcut order | callback adapter; callback injection, mismatch, approval, and per-API isolation witnesses |
|
|
2516
|
+
| monitor reconciliation service | immediate startup, non-overlap, timer reschedule, stop/drain, catch-and-warn routing | supervisor module; recording supervisor timer witness |
|
|
2517
|
+
| plugin factory and metadata | id/name/description, Gateway scope/error code, registration order, instance-local snapshots | 67-line entry; runtime and declaration expose only `default` and `createOpenClawPluginForTest` |
|
|
2518
|
+
|
|
2519
|
+
This is a source-ownership change only. It adds or removes no lock, Store or
|
|
2520
|
+
durable JSON/event write, subprocess boundary, timer, Gateway method, or
|
|
2521
|
+
Gateway restart. The existing `spawnSync`/`spawn` calls and their exact argv,
|
|
2522
|
+
environment, working-directory, output, timeout, and error rules only moved to
|
|
2523
|
+
the command adapter. At this exact plugin-split slice, static subprocess
|
|
2524
|
+
startup evidence remained 38 included sites; that is a historical slice metric,
|
|
2525
|
+
not the final result. The later static closeout establishes 19 of 48 baseline
|
|
2526
|
+
sites. The single supervisor `setTimeout` loop only moved files, and no install
|
|
2527
|
+
or restart path is called by plugin registration. Multiple plugin definitions
|
|
2528
|
+
retain separate resume caches, while the existing per-API `WeakMap` keeps
|
|
2529
|
+
relay path and plugin config isolated.
|
|
2530
|
+
|
|
2531
|
+
All newly extracted or moved slice functions remain below the hard
|
|
2532
|
+
500-line/c50 gates. The unchanged canonical `openclaw-plugin-helpers.ts` is not
|
|
2533
|
+
counted in this slice gate: its existing `parseAkkCommand` remains 188 lines/c58
|
|
2534
|
+
and is retained for the final global complexity closure. The cohesive preferred
|
|
2535
|
+
100-line/c20 exceptions in this slice are transparent and recorded below;
|
|
2536
|
+
splitting the registration table or the ordered decision/format paths further
|
|
2537
|
+
would obscure schema/action order or fail-closed precedence without reducing
|
|
2538
|
+
authority.
|
|
2539
|
+
|
|
2540
|
+
| Function or table | LOC / approximate complexity |
|
|
2541
|
+
| --- | ---: |
|
|
2542
|
+
| `registerOpenClawCommands` | 398 / c1 |
|
|
2543
|
+
| `runDelegate` | 178 / c45 |
|
|
2544
|
+
| `handleAkkLifecycleCommand` | 165 / c30 |
|
|
2545
|
+
| `runCliAsync` | 100 / c1 |
|
|
2546
|
+
| callback `handleCallback` | 105 / c15 |
|
|
2547
|
+
| `handleAkkCommand` | 90 / c22 |
|
|
2548
|
+
| `formatSendCommandResult` | 84 / c28 |
|
|
2549
|
+
| `formatStatusCommandResult` | 59 / c27 |
|
|
2550
|
+
| `runSendRequest` | 93 / c21 |
|
|
2551
|
+
|
|
2552
|
+
The entry maximum is 37 lines/c3 and the supervisor maximum is 97 lines/c12.
|
|
2553
|
+
Machine-readable public-contract evidence freezes the exact manifest plus six
|
|
2554
|
+
source authority paths, checks a role-specific responsibility signature and
|
|
2555
|
+
each required direct import, and rejects missing command/schema roles or an
|
|
2556
|
+
existing but incorrect substitute path.
|
|
2557
|
+
|
|
2558
|
+
## #195 production function hard-gate closeout
|
|
2559
|
+
|
|
2560
|
+
PR #195 compares exact parent
|
|
2561
|
+
`68e0e399152f5569ef0572b914da308acea36423` with exact candidate
|
|
2562
|
+
`256614ede43188c7cf29594b5afe14331ff9b909`. The compiler-AST measurement
|
|
2563
|
+
counts every production function, method, accessor, constructor, function
|
|
2564
|
+
expression, and arrow function with a body, excluding nested function bodies
|
|
2565
|
+
from the enclosing function's complexity.
|
|
2566
|
+
|
|
2567
|
+
| Metric | Parent | Candidate | Delta |
|
|
2568
|
+
| --- | ---: | ---: | ---: |
|
|
2569
|
+
| Production physical LOC | 92,980 | 93,303 | +323 |
|
|
2570
|
+
| Production functions | 4,019 | 4,044 | +25 |
|
|
2571
|
+
| Largest function / maximum complexity | 834 / c190 | 484 / c49 | strictly below 500 / c50 |
|
|
2572
|
+
| Hard-limit violations under the final rule | 6 | 0 | -6 |
|
|
2573
|
+
| Production modules / import edges / cycles | 123 / 783 / 0 | 123 / 783 / 0 | unchanged |
|
|
2574
|
+
| Static subprocess sites / affected full fallback | 19 of 48 / 2 of 10 | 19 of 48 / 2 of 10 | unchanged |
|
|
2575
|
+
|
|
2576
|
+
The six mechanical splits preserve evaluation, short-circuit, getter, and
|
|
2577
|
+
first-error order:
|
|
2578
|
+
|
|
2579
|
+
| Parent hard violation | Parent LOC / complexity | Candidate private stages | Candidate stage maxima |
|
|
2580
|
+
| --- | ---: | --- | ---: |
|
|
2581
|
+
| `pendingApprovalFromRecords` | 237 / c50 | turn selection, tool-use agreement, evidence projection | 91 / c22 |
|
|
2582
|
+
| `assertDeferredForegroundTransfer` | 834 / c190 | header, source history/binding, target, preparation, dispatch, commit, resolution, abort, failure | 142 / c37 |
|
|
2583
|
+
| `deriveRelationshipAssertions` | 121 / c60 | Session relationships and stable relationships | 90 / c36 |
|
|
2584
|
+
| `selectTerminalSnapshot` | 279 / c64 | row, process, management, and action selection | 128 / c28 |
|
|
2585
|
+
| `assertNativeThreadTransition` | 327 / c71 | header, identity, receipt, and binding consistency | 146 / c29 |
|
|
2586
|
+
| `parseAkkCommand` | 188 / c58 | lifecycle, Turn, and close parsing | 80 / c24 |
|
|
2587
|
+
|
|
2588
|
+
The gate is strict `<500` LOC and `<50` approximate complexity: a function
|
|
2589
|
+
that reaches 500 or c50 fails. There is no exception field or allowlist. The
|
|
2590
|
+
default `<100`/`<20` inventory remains visible for review but is not silently
|
|
2591
|
+
treated as a hard failure. This closeout changes no module ownership or import
|
|
2592
|
+
direction, lock scope or order, durable write or recovery phase, subprocess
|
|
2593
|
+
boundary, public command/tool/schema/JSON contract, Store protocol, or runtime
|
|
2594
|
+
export.
|
|
2595
|
+
|
|
2596
|
+
Exact-candidate validation covered typecheck, build, architecture, refactor
|
|
2597
|
+
evidence, and diff checks; 186 relevant direct tests, 1,001 fast tests, and
|
|
2598
|
+
five targeted integration files passed. Two independent exact-head reviews
|
|
2599
|
+
returned GO. No full suite, install, package, publish, or GitHub Actions run was
|
|
2600
|
+
part of PR #195.
|
|
2601
|
+
|
|
2602
|
+
## Final CLI-core facade and ownership closeout
|
|
2603
|
+
|
|
2604
|
+
The final closeout moves the remaining reusable authority and I/O helpers out
|
|
2605
|
+
of `cli-core.ts` without moving another command state machine. CLI option
|
|
2606
|
+
coercion and canonical workspace checks now live in `cli-command-runtime.ts`;
|
|
2607
|
+
conversation activity/waiting policy lives in `protocol.ts`; callback process
|
|
2608
|
+
failure classification lives in `callback-outbox-policy.ts`; and terminal
|
|
2609
|
+
process liveness lives at the existing `ps` boundary in
|
|
2610
|
+
`terminal-process-source.ts`. Terminal send safety is owned by
|
|
2611
|
+
`terminal-authority-policy.ts`, OpenClaw yield presentation by
|
|
2612
|
+
`terminal-dispatch-presenter.ts`, and Codex completion-context reads by the
|
|
2613
|
+
status facade. List and monitor consumers reuse those canonical policies rather
|
|
2614
|
+
than retaining private copies.
|
|
2615
|
+
|
|
2616
|
+
The Store-backed current-Turn fence is exposed through
|
|
2617
|
+
`terminal-turn-binding-authority-cli-adapter.ts` under the existing terminal
|
|
2618
|
+
identity-authority domain. It preserves Store selection, terminal-control
|
|
2619
|
+
validation, writable-Store upgrade, protocol check, authoritative Session read,
|
|
2620
|
+
and exact-or-migrated binding comparison order. Dispatch recovery now exposes
|
|
2621
|
+
its existing ledger-owner read and managed-owner fence directly. Managed
|
|
2622
|
+
approval/cancellation still checks deferred transfer, current binding, and the
|
|
2623
|
+
ledger generation in that order; no lock, Store, error, or asynchronous
|
|
2624
|
+
boundary is reordered.
|
|
2625
|
+
|
|
2626
|
+
Against exact parent `1274306e8e2f1e294910c8719b23de0d74878a31`,
|
|
2627
|
+
`src/cli-core.ts` falls from 2,122 to 1,556 physical lines (-566). Total
|
|
2628
|
+
production TypeScript changes from 93,303 to 93,313 lines (+10), the typed
|
|
2629
|
+
owner/facade overhead for the final extraction. Architecture validation reports
|
|
2630
|
+
57 domains, 125 production modules, 809 static import edges, zero cycles, and
|
|
2631
|
+
one retained `cli-core.ts` importer. Its public surface remains the stable
|
|
2632
|
+
`parseCliCommand` / `executeCliCommand` facade, and `CliCommandOptions` is now
|
|
2633
|
+
`Record<string, unknown>` in both source and emitted declarations.
|
|
2634
|
+
|
|
2635
|
+
The final typed-boundary cleanup adds nine interface-only production lines to
|
|
2636
|
+
remove the last `TerminalControlSendRequest` `Record<string, any>` bridge. The
|
|
2637
|
+
closeout production ratchet is therefore 93,322 physical lines;
|
|
2638
|
+
`cli-core.ts` remains 1,556 lines and the graph remains 125 modules, 809 edges,
|
|
2639
|
+
and zero cycles. Direct source and emitted-declaration guards freeze the six
|
|
2640
|
+
option properties and reject any reintroduction of raw `any` in the composition
|
|
2641
|
+
boundary.
|
|
2642
|
+
|
|
2643
|
+
The ownership validator also fixes an independent Issue-level ceiling of 8,000
|
|
2644
|
+
physical `cli-core.ts` lines. Manifest validation rejects a configured value
|
|
2645
|
+
above 8,000, while architecture validation rejects an actual source above
|
|
2646
|
+
8,000 even when a coordinated manifest edit makes the two values equal. The
|
|
2647
|
+
exact ratchet remains 1,556; a direct tamper witness raises both source and
|
|
2648
|
+
ratchet to 8,001, synchronizes the production total, and still fails on the
|
|
2649
|
+
hard ceiling. The combined compiler-AST architecture gate reports zero
|
|
2650
|
+
production function hard-limit violations. It also fixes one owner for each of
|
|
2651
|
+
the six shared status predicates: conversation release, session-send blocking,
|
|
2652
|
+
and callback supersede belong to `protocol.ts`; deferred-transfer finality
|
|
2653
|
+
belongs to `deferred-foreground-transfer-policy.ts`; ordinary dispatch activity
|
|
2654
|
+
and recovery belong to `terminal-dispatch-policy.ts`. The same compiler-AST
|
|
2655
|
+
gate rejects duplicate predicate definitions, duplicate exact inline tables,
|
|
2656
|
+
and full active/recoverable tables that bypass their derived policy.
|
|
2657
|
+
|
|
2658
|
+
An exact compiler-AST inventory ratchets the 27 remaining top-level functions
|
|
2659
|
+
and rejects top-level classes or function-valued variables. A forbidden-owner
|
|
2660
|
+
guard prevents terminal-send policy, Turn-binding authority, Codex context
|
|
2661
|
+
loading, callback failure classification, process liveness, and status policy
|
|
2662
|
+
definitions from returning to the composition root. Direct tests record the
|
|
2663
|
+
Turn-generation and migrated compatibility boundary, superseded-error
|
|
2664
|
+
projection, delegated/malformed short-circuits, deferred -> binding -> ledger
|
|
2665
|
+
ordering and early failure, Codex provider/process/history read order, callback
|
|
2666
|
+
classification priority, terminal-send getter/error priority, canonical
|
|
2667
|
+
workspace behavior, and process/status policy reuse. Therefore `cli-core.ts`
|
|
2668
|
+
contains no send, lifecycle, monitor, or callback state-machine definition; it
|
|
2669
|
+
retains only stable parsing/execution, command routing, composition wiring,
|
|
2670
|
+
shared lock scopes, and CLI parser/presentation compatibility.
|
|
2671
|
+
|
|
2672
|
+
## Integration virtual-clock profile remediation
|
|
2673
|
+
|
|
2674
|
+
The final profile remediation changes test timing only. Production timeout,
|
|
2675
|
+
polling, retry, lock, and composer windows are unchanged. The ordinary
|
|
2676
|
+
`runAgentCliInProcess` fixture also remains real-time by default. Selected
|
|
2677
|
+
sequential scenarios opt in to `runAgentCliInProcessVirtual`, whose wall and
|
|
2678
|
+
monotonic clocks are scoped by an explicit Store, state path, or
|
|
2679
|
+
`AKK_RUNTIME_DIR`. Async sleeps advance that clock and yield one `setImmediate`
|
|
2680
|
+
turn; sync sleeps only advance it. The fixture records both kinds of request,
|
|
2681
|
+
reuses one monotonic clock across calls in the same fixture, and fails fast if
|
|
2682
|
+
two commands try to share that clock concurrently.
|
|
2683
|
+
|
|
2684
|
+
The highest-volume sequential Codex cases may opt in one step further through
|
|
2685
|
+
`runAgentCliInProcessDirect`. That helper still runs the production CLI parser,
|
|
2686
|
+
composition, terminal adapters, identity fences, dispatch ledger, and receipt
|
|
2687
|
+
state machines. It replaces only the executable fake `tmux`/`ps`/`lsof` ports
|
|
2688
|
+
with the existing `MutableRecordingTerminalProvider` and
|
|
2689
|
+
`StaticTerminalProcessSource`. `writeFakeTmux` and `writeFakeProcessTools`
|
|
2690
|
+
register fixture-scoped panes, screens, and process snapshots; screen capture
|
|
2691
|
+
remains live across calls, and direct text/key operations are projected into
|
|
2692
|
+
the existing exact input ledger with a `direct_terminal_provider` marker.
|
|
2693
|
+
Explicit JSON terminal fixtures retain their own static adapters. The direct
|
|
2694
|
+
helper fails before command execution when it sees a capture/send/list gate,
|
|
2695
|
+
delay, transport failure, uncertain SIGKILL outcome, or overlapping command.
|
|
2696
|
+
It is additionally restricted to a non-empty Codex process fixture. Monitor,
|
|
2697
|
+
Claude, empty-process, process-death, and executable-observation scenarios may
|
|
2698
|
+
use virtual time where listed below, but never the direct provider seam.
|
|
2699
|
+
|
|
2700
|
+
The timing boundary is intentionally narrower than the test boundary:
|
|
2701
|
+
|
|
2702
|
+
| Virtual-time scenarios | Real-time boundary retained |
|
|
2703
|
+
| --- | --- |
|
|
2704
|
+
| Session follow-current/response generations and synthetic acceptance outcomes | v0.8.1 compatibility, Claude observation failure, the real native-binding window, and late-ACK child processes |
|
|
2705
|
+
| Sequential dispatch recovery and receipt-fence state machines, using direct terminal/process ports where the executable shim is not the contract | the public active-managed dispatch witness, uncertain transport/SIGKILL recovery, and both concurrent-send witnesses |
|
|
2706
|
+
| Wrapped-composer, prepared/orphan receipt, stable replay, and delegate replay semantics | the multilingual composer adapter witness and both gated raw-send process witnesses |
|
|
2707
|
+
| Same-cwd/low-confidence monitor decisions, working hard-timeout policy, and sequential renew semantics | one complete Gateway callback path and the gated renew-versus-close race |
|
|
2708
|
+
| Fake-process Claude death/transcript reconciliation | monitor singleton, live/dead PID and SIGKILL recovery, supervised/crash recovery, and transcript-monitor restart processes |
|
|
2709
|
+
| Idle-gate matrix except injected capture failure, and managed background-conversation projection | capture failure, stale-PID, partial-`lsof`, raw approval, and direct cancel adapter witnesses |
|
|
2710
|
+
|
|
2711
|
+
No test name or pre-existing assertion is removed. Receipt bytes, whitespace,
|
|
2712
|
+
error priority, no-second-Enter, no-terminal-input, and Store-authority
|
|
2713
|
+
assertions remain in their original integration tests. The existing
|
|
2714
|
+
`terminal-dispatch-ledger` public-contract mapping continues to pair those
|
|
2715
|
+
retained receipt/recovery boundaries with the direct dispatch application,
|
|
2716
|
+
ledger codec, receipt, and terminal-acceptance witnesses; no manifest path or
|
|
2717
|
+
tier changes merely to claim a timing improvement.
|
|
2718
|
+
|
|
2719
|
+
Measure the focused worker cost from a clean exact commit with the repository
|
|
2720
|
+
profile reporter. Run the identical command for the parent and candidate, on
|
|
2721
|
+
the same host, Node version, compile-cache state, and concurrency:
|
|
2722
|
+
|
|
2723
|
+
```sh
|
|
2724
|
+
test -z "$(git status --porcelain)"
|
|
2725
|
+
npm run build
|
|
2726
|
+
test -z "$(git status --porcelain)"
|
|
2727
|
+
AKK_PROFILE_CACHE="$(mktemp -d /tmp/akk-126-integration-cache.XXXXXX)"
|
|
2728
|
+
AKK_PROFILE_OUTPUT="/tmp/akk-126-integration-$(git rev-parse HEAD).json"
|
|
2729
|
+
AKK_TEST_CONCURRENCY=4 \
|
|
2730
|
+
NODE_COMPILE_CACHE="$AKK_PROFILE_CACHE" \
|
|
2731
|
+
AKK_TEST_REPORTER="$PWD/scripts/test-profile-reporter.js" \
|
|
2732
|
+
AKK_TEST_PROFILE_TIER=integration \
|
|
2733
|
+
AKK_TEST_PROFILE_COMMIT="$(git rev-parse HEAD)" \
|
|
2734
|
+
AKK_TEST_PROFILE_DIRTY=0 \
|
|
2735
|
+
AKK_TEST_PROFILE_OUTPUT="$AKK_PROFILE_OUTPUT" \
|
|
2736
|
+
node scripts/run-test-tier.js integration \
|
|
2737
|
+
test/shards/agent-cli-session-acceptance.test.ts \
|
|
2738
|
+
test/shards/agent-cli-dispatch-recovery.test.ts \
|
|
2739
|
+
test/shards/agent-cli-dispatch-authority.test.ts \
|
|
2740
|
+
test/shards/agent-cli-composer-replay.test.ts \
|
|
2741
|
+
test/shards/agent-cli-monitor-recovery.test.ts \
|
|
2742
|
+
test/shards/agent-cli-monitor-lifecycle.test.ts \
|
|
2743
|
+
test/shards/agent-cli-terminal-send-gates.test.ts \
|
|
2744
|
+
test/shards/agent-cli-receipt-fences.test.ts
|
|
2745
|
+
```
|
|
2746
|
+
|
|
2747
|
+
Compare the sum of `files[].duration_ms`, not nested test durations, and reject
|
|
2748
|
+
dirty, failed, wrong-SHA, wrong-Node, or wrong-concurrency reports. This section
|
|
2749
|
+
does not claim the final performance gate: exact merged-head before/after
|
|
2750
|
+
worker time and the repeated fast/full reports belong in the separate final
|
|
2751
|
+
evidence update after all remediation branches are stacked.
|
|
2752
|
+
|
|
2753
|
+
## Soft freeze while #126 is active
|
|
2754
|
+
|
|
2755
|
+
Until the orchestration milestones finish:
|
|
2756
|
+
|
|
2757
|
+
1. Do not add product features directly to a hotspot in `cli-core.ts`. Route new
|
|
2758
|
+
work through the next typed seam when reasonably possible.
|
|
2759
|
+
2. Security, data-loss, liveness, and release-blocking regressions may patch the
|
|
2760
|
+
current path, but the PR must identify the temporary ownership and update the
|
|
2761
|
+
extraction inventory.
|
|
2762
|
+
3. Do not introduce new `Record<string, any>` service inputs, new `*LockHeld`
|
|
2763
|
+
booleans, new direct persistence calls in `cli-core.ts`, or a new lock-order
|
|
2764
|
+
exception.
|
|
2765
|
+
4. Keep refactor PRs free of unrelated user-facing behavior changes. A behavior
|
|
2766
|
+
change needs its own issue, acceptance tests, and explicit review.
|
|
2767
|
+
5. Retain real-process contract tests for argv/exit, terminal input, Store crash
|
|
2768
|
+
recovery, and OpenClaw callback boundaries. First add deterministic reducer
|
|
2769
|
+
tests; consolidate duplicate black-box cases only after equivalent contract
|
|
2770
|
+
coverage is demonstrated.
|
|
2771
|
+
6. Do not weaken identity, token, composer, approval, ownership, CAS, uncertain
|
|
2772
|
+
outcome, or callback isolation fences to make extraction easier.
|
|
2773
|
+
|
|
2774
|
+
## Measurement method
|
|
2775
|
+
|
|
2776
|
+
Physical LOC is `wc -l` over checked-in `src/*.ts`. Function and approximate
|
|
2777
|
+
complexity measurements use the TypeScript compiler AST and count functions,
|
|
2778
|
+
methods, accessors, constructors, function expressions, and arrow functions with
|
|
2779
|
+
bodies. Approximate complexity is `1 + if/loop/case/catch/?:/&&/||/??`, excluding
|
|
2780
|
+
nested function bodies from the enclosing function. It is a prioritization
|
|
2781
|
+
signal, not a semantic correctness score.
|
|
2782
|
+
|
|
2783
|
+
The JSON baseline is immutable for this snapshot. Future PRs append their own
|
|
2784
|
+
before/after measurements or replace the documented current baseline while
|
|
2785
|
+
retaining this commit as the historical comparison point.
|
|
2786
|
+
|
|
2787
|
+
## Issue #206 addendum — durable observation of human-started work
|
|
2788
|
+
|
|
2789
|
+
Issue #206 adds Terminal Watch as a new aggregate beside, not inside, the
|
|
2790
|
+
managed Session/Turn architecture. The v16 action-contract and 14-tool sections
|
|
2791
|
+
above remain immutable historical snapshots; at the time of the #206 delta,
|
|
2792
|
+
the public surface was list action-contract v23 with 16 registered OpenClaw
|
|
2793
|
+
tools. v23 keeps every structured
|
|
2794
|
+
Send semantic-ID-only while making Codex `terminal_user_explicit` independent
|
|
2795
|
+
of Composer visibility, stability, and exactness. Its physical fallback clears
|
|
2796
|
+
the current Composer once, injects the new request, waits through the paste
|
|
2797
|
+
window, and dispatches Enter exactly once without a post-text Composer veto.
|
|
2798
|
+
Claude Code user-explicit Send, native inspection, and lifecycle input remain
|
|
2799
|
+
exact-empty-only; the managed path may require exact empty before input, but a
|
|
2800
|
+
user-explicit Codex request cannot be vetoed by Composer observation after text
|
|
2801
|
+
injection. When managed delivery fails before input, the physical fallback
|
|
2802
|
+
captures a pre-Send provider boundary and best-effort attaches an exact
|
|
2803
|
+
request-bound Terminal Watch after Enter. The Watch supplies completion callback
|
|
2804
|
+
behavior without claiming a managed Turn, and its failure never revokes Send.
|
|
2805
|
+
No draft text or Composer digest crosses the model boundary.
|
|
2806
|
+
|
|
2807
|
+
The later interactive-response release advances the current public surface to
|
|
2808
|
+
action-contract v24 and 17 OpenClaw tools. It adds a status-bound semantic
|
|
2809
|
+
questionnaire response action while keeping prompt fingerprints, terminal-key
|
|
2810
|
+
plans, and one-shot mutation authority private.
|
|
2811
|
+
|
|
2812
|
+
Issue #298 P2 subsequently advances the current core surface to action-contract
|
|
2813
|
+
v25 and 19 OpenClaw tools. It adds explicit Codex `identify_foreground` and
|
|
2814
|
+
atomic `identify_and_send` operations plus independent screen, native-identity,
|
|
2815
|
+
and durable-activity status axes. The standalone 30-second `/status` proof is
|
|
2816
|
+
diagnostic only and is not persisted as reusable identity authority; normal
|
|
2817
|
+
Send, List, and Status do not run the probe.
|
|
2818
|
+
|
|
2819
|
+
### Aggregate and persistence boundary
|
|
2820
|
+
|
|
2821
|
+
`TerminalWatch` schema v2 represents either one task that a human started
|
|
2822
|
+
directly in a Codex or Claude Code TUI or one request AKK delivered through the
|
|
2823
|
+
user-explicit unmanaged fallback. It is not a Conversation, Session, Turn, dispatch
|
|
2824
|
+
receipt, monitor owner, or terminal-input authority. Creating or reconciling it
|
|
2825
|
+
does not send input, adopt or claim the work, reserve the terminal, block later
|
|
2826
|
+
human activity, or create callback authority for a managed Turn.
|
|
2827
|
+
|
|
2828
|
+
Each strict record contains `watch_id`, revision, agent, exact terminal endpoint,
|
|
2829
|
+
workspace and internally resolved binding token; one privacy-safe provider anchor
|
|
2830
|
+
owns the process incarnation, native thread/task and exact captured agent-version
|
|
2831
|
+
evidence. Regression-tested versions are diagnostics rather than a Watch
|
|
2832
|
+
allowlist; structurally compatible future versions remain observable with a
|
|
2833
|
+
warning. The record also retains the originating OpenClaw session/binary,
|
|
2834
|
+
creation/update/deadline timestamps, status, last activity, optional terminal
|
|
2835
|
+
settlement, and an append-only notification outbox whose approval entries carry
|
|
2836
|
+
their own evidence fingerprints.
|
|
2837
|
+
Status is one of `active`, `completed`,
|
|
2838
|
+
`failed`, `timed_out`, `invalidated`, or `cancelled`. The files live at
|
|
2839
|
+
`<store>/terminal-watches/<watch_id>.json`, with a `0700` directory, `0600`
|
|
2840
|
+
owner-private atomic JSON, strict path/symlink/shape validation, and revision
|
|
2841
|
+
CAS. The independent namespace is admitted by the Store root allowlist while
|
|
2842
|
+
retaining Store format 1 and advancing the writer fence to protocol 6.
|
|
2843
|
+
|
|
2844
|
+
Codex anchors retain the exact process identity, rollout device/inode/path, native
|
|
2845
|
+
task, request hash, version, task-start/user-message/observed-end byte offsets,
|
|
2846
|
+
capture time, and evidence fingerprint. Claude anchors retain the exact
|
|
2847
|
+
process/session identity, workspace, transcript relative path/device/inode/file
|
|
2848
|
+
identity, root prompt, request hash, version, current-turn/observed-end byte
|
|
2849
|
+
offsets, capture time, and fingerprint. The compact terminal record separately
|
|
2850
|
+
binds endpoint/incarnation, workspace, and the internal creation-time binding
|
|
2851
|
+
token. The Store validates the provider-owned anchor directly, without a mirrored
|
|
2852
|
+
Watch-specific shape or any raw prompt or command text. Legacy schema-v1 Watch
|
|
2853
|
+
records normalize to v2 on read; protocol 6 prevents an older writer from
|
|
2854
|
+
treating those v2 records as compatible.
|
|
2855
|
+
|
|
2856
|
+
### State, locking, and callback recovery
|
|
2857
|
+
|
|
2858
|
+
The user flow is human TUI start → fresh `/akk list` → copy only the advertised
|
|
2859
|
+
`terminals[].available_actions.watch` action's exact `terminal_id` → create Watch
|
|
2860
|
+
→ address it only by `watch_id` for status or unwatch. The creation path resolves
|
|
2861
|
+
the current binding token internally, acquires the terminal lock, rescans and
|
|
2862
|
+
revalidates the exact terminal incarnation and token, captures one unique
|
|
2863
|
+
active-task anchor, then creates with expected revision `null`. All mutations acquire the canonical
|
|
2864
|
+
Store writer lease before the per-Watch file lock. Observation occurs outside
|
|
2865
|
+
that write scope; settlement reloads under `writer -> watch`, checks the exact
|
|
2866
|
+
terminal and anchor fingerprints plus deadline, and commits one CAS transition.
|
|
2867
|
+
Concurrent cancellation, timeout, settlement, or another observer therefore
|
|
2868
|
+
cannot overwrite a newer revision.
|
|
2869
|
+
|
|
2870
|
+
The observation reducer yields `pending`, `approval`, `completed`, `failed`, or
|
|
2871
|
+
`invalidated`. Any endpoint, process, native-thread/task, provider file,
|
|
2872
|
+
offset/boundary, version/profile, request, or fingerprint drift—and any missing,
|
|
2873
|
+
truncated, replaced, successor, unsupported, or ambiguous evidence—fails closed
|
|
2874
|
+
as invalidated rather than following current terminal work. `unwatch` settles
|
|
2875
|
+
only the aggregate as cancelled and never touches the TUI.
|
|
2876
|
+
|
|
2877
|
+
Approval appends one notification per exact fingerprint while leaving the Watch
|
|
2878
|
+
active. It carries metadata only, never raw prompt/command text; Terminal Watch
|
|
2879
|
+
has no approval execution port and cannot participate in automatic approval.
|
|
2880
|
+
Completed/failed observations may retain only provider-redacted bounded
|
|
2881
|
+
completion text (maximum 4,000 characters) plus optional completion identity and
|
|
2882
|
+
timestamp. Every terminal outcome appends exactly one outcome notification.
|
|
2883
|
+
|
|
2884
|
+
Notification IDs derive deterministically from Watch, kind, and evidence
|
|
2885
|
+
fingerprint; the transport idempotency key derives from Watch plus notification.
|
|
2886
|
+
Delivery first persists a leased claim, performs transport outside the lock,
|
|
2887
|
+
then CAS-settles success or retry metadata. A process crash leaves an expiring
|
|
2888
|
+
claim that startup/periodic reconciliation can reclaim. This is crash-safe
|
|
2889
|
+
at-least-once transport with effective at-most-once logical delivery when the
|
|
2890
|
+
OpenClaw transport honors the idempotency key. One Watch's observation or
|
|
2891
|
+
delivery failure is recorded in its reconciliation item and does not stop the
|
|
2892
|
+
remaining Watches.
|
|
2893
|
+
|
|
2894
|
+
### Public wiring and supervision
|
|
2895
|
+
|
|
2896
|
+
The 16-tool OpenClaw surface adds `agent_knock_knock_watch` and
|
|
2897
|
+
`agent_knock_knock_unwatch`; the existing status tool accepts exactly one of a
|
|
2898
|
+
managed Turn target, semantic terminal target, or `watch_id`. List projects
|
|
2899
|
+
active Watches in `terminal_watches[]` and advertises `watch` only for an exact,
|
|
2900
|
+
supported terminal currently classified as working or awaiting approval. Slash
|
|
2901
|
+
routing is `/akk watch <exact-terminal-id>`, `/akk status <watch-id>`, and
|
|
2902
|
+
`/akk unwatch <watch-id>`. The internal CLI boundary has exactly four entries:
|
|
2903
|
+
|
|
2904
|
+
```text
|
|
2905
|
+
watch-terminal --terminal <exact-terminal-id> ...
|
|
2906
|
+
watch-status --watch <watch-id> ...
|
|
2907
|
+
unwatch-terminal --watch <watch-id> ...
|
|
2908
|
+
reconcile-watches ...
|
|
2909
|
+
```
|
|
2910
|
+
|
|
2911
|
+
Action-contract v18 establishes a zero-token model boundary. Structured actions
|
|
2912
|
+
carry semantic identities and user intent only:
|
|
2913
|
+
|
|
2914
|
+
- ordinary send is `{session_id, request}` for strict continuation or
|
|
2915
|
+
`{terminal_id, request}` for follow-current; the target fields are mutually
|
|
2916
|
+
exclusive and may both be absent only when AKK must prove one unique target;
|
|
2917
|
+
- Terminal Watch is `{terminal_id}` only;
|
|
2918
|
+
- native inspection is `{terminal_id, inspection}`, new is `{terminal_id}`, and
|
|
2919
|
+
resume is `{terminal_id, native_thread_id}`;
|
|
2920
|
+
- managed approval is `{turn_id}`, terminal-scoped approval is `{terminal_id}`,
|
|
2921
|
+
reconcile is `{terminal_id, conflicting_session_id}`, and handoff takeover is
|
|
2922
|
+
`{turn_id, reason:"superseded_by_human_context_switch"}`.
|
|
2923
|
+
|
|
2924
|
+
Approval, reconcile, and handoff still require explicit user confirmation. The
|
|
2925
|
+
trusted plugin/CLI retains that confirmation offer, derives fresh terminal,
|
|
2926
|
+
binding, candidate, approval, handoff, revision, and compare-and-swap fences,
|
|
2927
|
+
and revalidates them under the canonical locks immediately before mutation.
|
|
2928
|
+
None of those opaque values—including live native UUIDs used only as a handoff
|
|
2929
|
+
fence—crosses the model-facing boundary. Human slash selectors remain a CLI
|
|
2930
|
+
discovery layer. Orphan close keeps `expected_message_id` and
|
|
2931
|
+
`expected_transition_id` because they are durable entity identities rather than
|
|
2932
|
+
authority tokens. This projection change retains Store format 1 and the private
|
|
2933
|
+
persisted authority evidence while advancing the writer fence to protocol 6.
|
|
2934
|
+
|
|
2935
|
+
The existing non-overlapping OpenClaw supervisor now coordinates two independent
|
|
2936
|
+
steps at startup and every five seconds: managed-Turn monitor reconciliation and
|
|
2937
|
+
Terminal Watch reconciliation. Each has its own error boundary, so a failure in
|
|
2938
|
+
one cannot starve the other. Watch reconciliation observes active aggregates,
|
|
2939
|
+
settles deadlines/outcomes, and drains eligible durable notifications; it does
|
|
2940
|
+
not mutate Session/Turn state or replay terminal input.
|
|
2941
|
+
|
|
2942
|
+
The deterministic fast witnesses cover provider-anchor drift, Store privacy and
|
|
2943
|
+
CAS, service restart/dedupe/timeout/claim-crash/retry behavior, callback
|
|
2944
|
+
projection, list/action v18, slash/tool routing, and documentation. Per the
|
|
2945
|
+
repository test policy, integration/full/release tests remain reserved for the
|
|
2946
|
+
immediate pre-publication gate of an actual npm or ClawHub release.
|
|
2947
|
+
|
|
2948
|
+
## Issue #212 addendum — Host-owned lifecycle adapter
|
|
2949
|
+
|
|
2950
|
+
AKK does not run a standalone supervisor. Exactly one external Host owns the
|
|
2951
|
+
in-process AKK lifecycle and calls `start()` and `stop()` with its own plugin or
|
|
2952
|
+
adapter lifetime. The Host injects an ordered list of reconciliation phases;
|
|
2953
|
+
the host-neutral lifecycle service owns only startup execution, periodic
|
|
2954
|
+
single-flight scheduling, per-phase error isolation, and stop/drain behavior.
|
|
2955
|
+
It owns no Store, callback transport, process identity, Host configuration,
|
|
2956
|
+
daemon entrypoint, or cross-Host lease.
|
|
2957
|
+
|
|
2958
|
+
OpenClaw is the first adapter. Its compatibility module continues to own the
|
|
2959
|
+
existing reconciliation argv, Store-dir lookup, log messages, unref timer
|
|
2960
|
+
policy, registration service id, and managed-monitor-before-Watch ordering. The
|
|
2961
|
+
legacy module and service names remain unchanged to avoid an unnecessary
|
|
2962
|
+
OpenClaw compatibility change; they do not represent an independently running
|
|
2963
|
+
Supervisor product. Callback route and delivery ports were already
|
|
2964
|
+
host-neutral, so this extraction does not change the Store or callback protocol.
|
|
2965
|
+
|
|
2966
|
+
Future Hosts such as Hermes compose their own adapter around the same lifecycle
|
|
2967
|
+
and callback ports. AKK deliberately does not add multi-Host ownership,
|
|
2968
|
+
Host-switch recovery, PID/heartbeat fencing, or no-Host continuity because
|
|
2969
|
+
those are outside the supported product behavior.
|
|
2970
|
+
|
|
2971
|
+
## Issue #320 P2 addendum — Host connector capability handshake
|
|
2972
|
+
|
|
2973
|
+
The Host-neutral catalog now derives one immutable capability handshake for Pi
|
|
2974
|
+
and DeepSeek Harness. Version 1 contains only public catalog identity: the
|
|
2975
|
+
ordered tool names and derived count, a canonical metadata/schema SHA-256, and
|
|
2976
|
+
the canonical Skill name/SHA-256. It contains no controller route, environment,
|
|
2977
|
+
token, filesystem path, or other authority. Each connector validates the
|
|
2978
|
+
handshake before starting its Host lifecycle and validates the exact names it
|
|
2979
|
+
registered before reporting ready. Unknown versions, missing metadata, catalog
|
|
2980
|
+
drift, generated-Skill drift, and partial registration fail closed.
|
|
2981
|
+
|
|
2982
|
+
This replaces connector-local `EXPECTED_TOOL_COUNT` literals and removes the
|
|
2983
|
+
architecture dashboard's regex extraction of those constants. The checked-in
|
|
2984
|
+
public-contract witness still records the current 22-tool OpenClaw/Host Bridge
|
|
2985
|
+
surface; adding or removing a catalog entry intentionally changes that public
|
|
2986
|
+
witness, while connector counts and registration expectations derive from the
|
|
2987
|
+
same handshake without another manual edit.
|