@haaaiawd/second-nature 0.1.8 → 0.1.10
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/index.js +281 -69
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -1
- package/runtime/cli/commands/index.d.ts +2 -0
- package/runtime/cli/commands/index.js +61 -6
- package/runtime/cli/explain/explain-surface-subject.d.ts +8 -0
- package/runtime/cli/explain/explain-surface-subject.js +9 -0
- package/runtime/cli/explain/format-explanation.d.ts +2 -0
- package/runtime/cli/explain/format-explanation.js +2 -0
- package/runtime/cli/explain/resolve-subject.js +15 -0
- package/runtime/cli/host-capability/classify-delivery.d.ts +14 -0
- package/runtime/cli/host-capability/classify-delivery.js +20 -0
- package/runtime/cli/host-capability/probe-host-capability.d.ts +2 -0
- package/runtime/cli/host-capability/probe-host-capability.js +58 -0
- package/runtime/cli/host-capability/record-host-capability.d.ts +6 -0
- package/runtime/cli/host-capability/record-host-capability.js +14 -0
- package/runtime/cli/host-capability/types.d.ts +71 -0
- package/runtime/cli/host-capability/types.js +6 -0
- package/runtime/cli/host-smoke/run-host-smoke.d.ts +2 -0
- package/runtime/cli/host-smoke/run-host-smoke.js +40 -0
- package/runtime/cli/host-smoke/types.d.ts +35 -0
- package/runtime/cli/host-smoke/types.js +6 -0
- package/runtime/cli/index.js +18 -0
- package/runtime/cli/ops/heartbeat-surface.d.ts +35 -0
- package/runtime/cli/ops/heartbeat-surface.js +71 -0
- package/runtime/cli/ops/ops-router.d.ts +16 -0
- package/runtime/cli/ops/ops-router.js +83 -0
- package/runtime/cli/ops/show-operator-fallback.d.ts +13 -0
- package/runtime/cli/ops/show-operator-fallback.js +22 -0
- package/runtime/cli/ops/workspace-heartbeat-runner.d.ts +10 -0
- package/runtime/cli/ops/workspace-heartbeat-runner.js +26 -0
- package/runtime/cli/read-models/index.d.ts +11 -2
- package/runtime/cli/read-models/index.js +50 -0
- package/runtime/cli/read-models/operator-explain-map.d.ts +6 -0
- package/runtime/cli/read-models/operator-explain-map.js +10 -0
- package/runtime/cli/read-models/types.d.ts +5 -1
- package/runtime/cli/runtime/runtime-artifact-boundary.d.ts +28 -0
- package/runtime/cli/runtime/runtime-artifact-boundary.js +94 -0
- package/runtime/connectors/base/contract.d.ts +6 -0
- package/runtime/connectors/base/execution-policy.d.ts +47 -0
- package/runtime/connectors/base/execution-policy.js +82 -0
- package/runtime/connectors/base/index.d.ts +2 -0
- package/runtime/connectors/base/index.js +2 -0
- package/runtime/connectors/base/manifest.d.ts +55 -2
- package/runtime/connectors/base/manifest.js +50 -0
- package/runtime/connectors/base/map-life-evidence.d.ts +16 -0
- package/runtime/connectors/base/map-life-evidence.js +79 -0
- package/runtime/connectors/base/policy-layer.d.ts +2 -0
- package/runtime/connectors/base/policy-layer.js +16 -0
- package/runtime/connectors/base/route-planner.js +1 -0
- package/runtime/connectors/index.d.ts +1 -0
- package/runtime/connectors/index.js +1 -0
- package/runtime/connectors/near-real/near-real-connector-smoke.d.ts +19 -0
- package/runtime/connectors/near-real/near-real-connector-smoke.js +152 -0
- package/runtime/core/second-nature/heartbeat/heartbeat-executor.js +2 -0
- package/runtime/core/second-nature/heartbeat/heartbeat-loop.d.ts +37 -16
- package/runtime/core/second-nature/heartbeat/heartbeat-loop.js +95 -29
- package/runtime/core/second-nature/heartbeat/index.d.ts +4 -1
- package/runtime/core/second-nature/heartbeat/index.js +4 -1
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.d.ts +21 -0
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle.js +35 -0
- package/runtime/core/second-nature/heartbeat/runtime-snapshot.d.ts +28 -0
- package/runtime/core/second-nature/heartbeat/runtime-snapshot.js +35 -0
- package/runtime/core/second-nature/heartbeat/signal.d.ts +9 -2
- package/runtime/core/second-nature/heartbeat/snapshot-builder.d.ts +19 -1
- package/runtime/core/second-nature/index.d.ts +8 -0
- package/runtime/core/second-nature/index.js +8 -0
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +1 -1
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +9 -4
- package/runtime/core/second-nature/orchestrator/guard-layer.d.ts +6 -0
- package/runtime/core/second-nature/orchestrator/guard-layer.js +76 -20
- package/runtime/core/second-nature/orchestrator/intent-planner.d.ts +10 -0
- package/runtime/core/second-nature/orchestrator/intent-planner.js +135 -28
- package/runtime/core/second-nature/orchestrator/lease-manager.d.ts +1 -1
- package/runtime/core/second-nature/orchestrator/lease-manager.js +1 -1
- package/runtime/core/second-nature/outreach/build-outreach-draft-request.d.ts +6 -0
- package/runtime/core/second-nature/outreach/build-outreach-draft-request.js +63 -0
- package/runtime/core/second-nature/outreach/delivery-target.d.ts +26 -0
- package/runtime/core/second-nature/outreach/delivery-target.js +70 -0
- package/runtime/core/second-nature/outreach/dispatch-user-outreach.d.ts +38 -0
- package/runtime/core/second-nature/outreach/dispatch-user-outreach.js +119 -0
- package/runtime/core/second-nature/outreach/judge-input-from-snapshot.d.ts +7 -0
- package/runtime/core/second-nature/outreach/judge-input-from-snapshot.js +45 -0
- package/runtime/core/second-nature/outreach/judge-outreach.d.ts +40 -0
- package/runtime/core/second-nature/outreach/judge-outreach.js +121 -0
- package/runtime/core/second-nature/quiet/run-source-backed-quiet.d.ts +21 -0
- package/runtime/core/second-nature/quiet/run-source-backed-quiet.js +123 -0
- package/runtime/core/second-nature/rhythm/planner-rhythm-window.d.ts +15 -0
- package/runtime/core/second-nature/rhythm/planner-rhythm-window.js +52 -0
- package/runtime/core/second-nature/rhythm/policy-bridge.d.ts +19 -0
- package/runtime/core/second-nature/rhythm/policy-bridge.js +34 -0
- package/runtime/core/second-nature/types.d.ts +16 -2
- package/runtime/guidance/draft-outreach-message.d.ts +7 -0
- package/runtime/guidance/draft-outreach-message.js +42 -0
- package/runtime/guidance/evidence-guidance.d.ts +40 -0
- package/runtime/guidance/evidence-guidance.js +52 -0
- package/runtime/guidance/index.d.ts +3 -0
- package/runtime/guidance/index.js +3 -0
- package/runtime/guidance/outreach-draft-schema.d.ts +228 -0
- package/runtime/guidance/outreach-draft-schema.js +80 -0
- package/runtime/observability/audit/append-only-audit-store.d.ts +14 -0
- package/runtime/observability/audit/append-only-audit-store.js +21 -0
- package/runtime/observability/audit/audit-envelope.d.ts +51 -0
- package/runtime/observability/audit/audit-envelope.js +130 -0
- package/runtime/observability/audit/verify-audit-hash-chain.d.ts +23 -0
- package/runtime/observability/audit/verify-audit-hash-chain.js +83 -0
- package/runtime/observability/db/index.js +11 -0
- package/runtime/observability/db/schema/host-capability-reports.d.ts +180 -0
- package/runtime/observability/db/schema/host-capability-reports.js +12 -0
- package/runtime/observability/db/schema/index.d.ts +1 -0
- package/runtime/observability/db/schema/index.js +1 -0
- package/runtime/observability/index.d.ts +7 -0
- package/runtime/observability/index.js +7 -0
- package/runtime/observability/query/explain-query.d.ts +48 -0
- package/runtime/observability/query/explain-query.js +114 -0
- package/runtime/observability/query/export-audit-bundle.d.ts +22 -0
- package/runtime/observability/query/export-audit-bundle.js +27 -0
- package/runtime/observability/services/decision-ledger.d.ts +1 -1
- package/runtime/observability/services/decision-ledger.js +4 -0
- package/runtime/observability/services/governance-audit.d.ts +14 -0
- package/runtime/observability/services/governance-audit.js +25 -1
- package/runtime/observability/services/governance-plane-recorder.d.ts +47 -0
- package/runtime/observability/services/governance-plane-recorder.js +55 -0
- package/runtime/observability/services/lived-experience-audit.d.ts +97 -0
- package/runtime/observability/services/lived-experience-audit.js +162 -0
- package/runtime/storage/bootstrap/native-sqlite-probe.d.ts +7 -0
- package/runtime/storage/bootstrap/native-sqlite-probe.js +28 -0
- package/runtime/storage/bootstrap/repair-gate.d.ts +17 -0
- package/runtime/storage/bootstrap/repair-gate.js +71 -0
- package/runtime/storage/bootstrap/storage-mode-smoke.d.ts +38 -0
- package/runtime/storage/bootstrap/storage-mode-smoke.js +85 -0
- package/runtime/storage/db/index.js +49 -0
- package/runtime/storage/db/schema/delivery-attempts.d.ts +199 -0
- package/runtime/storage/db/schema/delivery-attempts.js +13 -0
- package/runtime/storage/db/schema/index.d.ts +3 -0
- package/runtime/storage/db/schema/index.js +3 -0
- package/runtime/storage/db/schema/life-evidence-index.d.ts +161 -0
- package/runtime/storage/db/schema/life-evidence-index.js +11 -0
- package/runtime/storage/db/schema/operator-fallback-artifacts.d.ts +161 -0
- package/runtime/storage/db/schema/operator-fallback-artifacts.js +11 -0
- package/runtime/storage/db/schema/policies.d.ts +17 -0
- package/runtime/storage/db/schema/policies.js +1 -0
- package/runtime/storage/delivery/query-delivery-attempts.d.ts +3 -0
- package/runtime/storage/delivery/query-delivery-attempts.js +32 -0
- package/runtime/storage/delivery/types.d.ts +27 -0
- package/runtime/storage/delivery/types.js +1 -0
- package/runtime/storage/delivery/write-delivery-attempt.d.ts +6 -0
- package/runtime/storage/delivery/write-delivery-attempt.js +36 -0
- package/runtime/storage/fallback/load-operator-fallback.d.ts +14 -0
- package/runtime/storage/fallback/load-operator-fallback.js +47 -0
- package/runtime/storage/fallback/operator-fallback-types.d.ts +9 -0
- package/runtime/storage/fallback/operator-fallback-types.js +1 -0
- package/runtime/storage/fallback/operator-fallback-view.d.ts +11 -0
- package/runtime/storage/fallback/operator-fallback-view.js +1 -0
- package/runtime/storage/fallback/write-operator-fallback.d.ts +6 -0
- package/runtime/storage/fallback/write-operator-fallback.js +21 -0
- package/runtime/storage/index.d.ts +21 -0
- package/runtime/storage/index.js +14 -0
- package/runtime/storage/life-evidence/append-life-evidence.d.ts +7 -0
- package/runtime/storage/life-evidence/append-life-evidence.js +64 -0
- package/runtime/storage/life-evidence/types.d.ts +45 -0
- package/runtime/storage/life-evidence/types.js +6 -0
- package/runtime/storage/quiet/persist-quiet-artifact.d.ts +7 -0
- package/runtime/storage/quiet/persist-quiet-artifact.js +22 -0
- package/runtime/storage/quiet/quiet-artifact-types.d.ts +18 -0
- package/runtime/storage/quiet/quiet-artifact-types.js +1 -0
- package/runtime/storage/quiet/quiet-artifact-writer.d.ts +15 -0
- package/runtime/storage/quiet/quiet-artifact-writer.js +56 -0
- package/runtime/storage/repositories/credential-repository.js +12 -1
- package/runtime/storage/rhythm/rhythm-policy-snapshot.d.ts +10 -0
- package/runtime/storage/rhythm/rhythm-policy-snapshot.js +34 -0
- package/runtime/storage/services/credential-vault.d.ts +5 -0
- package/runtime/storage/services/credential-vault.js +47 -9
- package/runtime/storage/snapshots/continuity-snapshot.d.ts +9 -0
- package/runtime/storage/snapshots/continuity-snapshot.js +41 -0
- package/runtime/storage/snapshots/life-evidence-snapshot.d.ts +6 -0
- package/runtime/storage/snapshots/life-evidence-snapshot.js +114 -0
- package/runtime/storage/snapshots/types.d.ts +58 -0
- package/runtime/storage/snapshots/types.js +1 -0
- package/runtime/storage/state-api.js +11 -4
- package/runtime/storage/user-interest/load-user-interest-snapshot.d.ts +2 -0
- package/runtime/storage/user-interest/load-user-interest-snapshot.js +150 -0
- package/runtime/storage/user-interest/types.d.ts +25 -0
- package/runtime/storage/user-interest/types.js +1 -0
- package/workspace-ops-bridge.js +78 -0
package/index.js
CHANGED
|
@@ -19,12 +19,102 @@
|
|
|
19
19
|
* Test coverage:
|
|
20
20
|
* - tests/integration/cli/plugin-runtime-registration.test.ts
|
|
21
21
|
* - tests/integration/cli/plugin-packaging-walkthrough.test.ts
|
|
22
|
+
* - tests/integration/cli/plugin-workspace-ops-bridge.test.ts (T1.1.4)
|
|
22
23
|
*/
|
|
23
24
|
import { startRuntimeService, } from "./runtime/core/second-nature/runtime/service-entry.js";
|
|
24
25
|
import { getLifecycleState, recordRegistration, } from "./runtime/core/second-nature/runtime/lifecycle-service.js";
|
|
26
|
+
import { openWorkspaceOpsBridge } from "./workspace-ops-bridge.js";
|
|
25
27
|
const INTERNAL_RUNTIME_TRACE_PREFIX = "sn-runtime-";
|
|
26
28
|
const HOST_SAFE_LIMITATION_MESSAGE = "Host-safe plugin package keeps synchronous register/load semantics, but mutating workspace runtime flows remain unavailable here.";
|
|
27
29
|
let activationSpine = null;
|
|
30
|
+
/** T1.1.4 — lazily opened full read bridge; closed when workspace root / resolution changes. */
|
|
31
|
+
let workspaceOpsBridge = null;
|
|
32
|
+
function disposeWorkspaceOpsBridge() {
|
|
33
|
+
if (workspaceOpsBridge) {
|
|
34
|
+
workspaceOpsBridge.close();
|
|
35
|
+
workspaceOpsBridge = null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const WORKSPACE_BRIDGE_COMMANDS = new Set([
|
|
39
|
+
"status",
|
|
40
|
+
"quiet",
|
|
41
|
+
"report",
|
|
42
|
+
"session",
|
|
43
|
+
"explain",
|
|
44
|
+
"heartbeat_check",
|
|
45
|
+
"fallback",
|
|
46
|
+
"storage_smoke",
|
|
47
|
+
]);
|
|
48
|
+
function isWorkspaceBridgeCommand(command, input) {
|
|
49
|
+
if (command === "credential") {
|
|
50
|
+
const action = typeof input?.action === "string" ? input.action : "show";
|
|
51
|
+
return action !== "verify";
|
|
52
|
+
}
|
|
53
|
+
return WORKSPACE_BRIDGE_COMMANDS.has(command);
|
|
54
|
+
}
|
|
55
|
+
async function ensureWorkspaceOpsBridge(spine) {
|
|
56
|
+
const root = spine.workspaceRootContext.runtimeRoot;
|
|
57
|
+
if (workspaceOpsBridge?.root === root) {
|
|
58
|
+
return { ok: true, dispatch: workspaceOpsBridge.dispatch };
|
|
59
|
+
}
|
|
60
|
+
disposeWorkspaceOpsBridge();
|
|
61
|
+
const opened = await openWorkspaceOpsBridge(root);
|
|
62
|
+
if (!opened.ok) {
|
|
63
|
+
return opened;
|
|
64
|
+
}
|
|
65
|
+
workspaceOpsBridge = { root, close: opened.close, dispatch: opened.dispatch };
|
|
66
|
+
return { ok: true, dispatch: opened.dispatch };
|
|
67
|
+
}
|
|
68
|
+
async function routeSecondNatureCommand(spine, command, input) {
|
|
69
|
+
const wr = spine.workspaceRootContext;
|
|
70
|
+
const useBridge = wr.resolution !== "unknown" && isWorkspaceBridgeCommand(command, input);
|
|
71
|
+
if (useBridge) {
|
|
72
|
+
const bridge = await ensureWorkspaceOpsBridge(spine);
|
|
73
|
+
if (!bridge.ok) {
|
|
74
|
+
return {
|
|
75
|
+
ok: false,
|
|
76
|
+
surfaceMode: "host_safe_carrier",
|
|
77
|
+
workspaceReadModelsEvaluated: false,
|
|
78
|
+
message: HOST_SAFE_LIMITATION_MESSAGE,
|
|
79
|
+
error: bridge.error,
|
|
80
|
+
data: {
|
|
81
|
+
workspaceRootResolution: wr.resolution,
|
|
82
|
+
bridgeAttempted: true,
|
|
83
|
+
declaredRoot: wr.declaredRoot,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return (await bridge.dispatch(command, input));
|
|
88
|
+
}
|
|
89
|
+
const def = spine.router.resolve(command);
|
|
90
|
+
if (!def) {
|
|
91
|
+
return { ok: false, message: `Unknown Second Nature command: ${command}` };
|
|
92
|
+
}
|
|
93
|
+
return def.execute(input);
|
|
94
|
+
}
|
|
95
|
+
function resolveWorkspaceRoot(toolWorkspaceRoot) {
|
|
96
|
+
const env = process.env.SECOND_NATURE_WORKSPACE_ROOT?.trim();
|
|
97
|
+
if (env) {
|
|
98
|
+
return { resolution: "env", declaredRoot: env, runtimeRoot: env };
|
|
99
|
+
}
|
|
100
|
+
const tool = toolWorkspaceRoot?.trim();
|
|
101
|
+
if (tool) {
|
|
102
|
+
return { resolution: "tool_args", declaredRoot: tool, runtimeRoot: tool };
|
|
103
|
+
}
|
|
104
|
+
return { resolution: "unknown", declaredRoot: undefined, runtimeRoot: process.cwd() };
|
|
105
|
+
}
|
|
106
|
+
function syncWorkspaceRootFromTool(spine, toolWorkspaceRoot) {
|
|
107
|
+
const next = resolveWorkspaceRoot(toolWorkspaceRoot);
|
|
108
|
+
const prev = spine.workspaceRootContext;
|
|
109
|
+
const changed = next.runtimeRoot !== prev.runtimeRoot || next.resolution !== prev.resolution;
|
|
110
|
+
if (changed) {
|
|
111
|
+
disposeWorkspaceOpsBridge();
|
|
112
|
+
}
|
|
113
|
+
spine.workspaceRootContext = next;
|
|
114
|
+
if (changed) {
|
|
115
|
+
spine.runtimeHandle = startRuntimeService({ workspaceRoot: next.runtimeRoot });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
28
118
|
function trimRuntimeEvidence(spine) {
|
|
29
119
|
if (spine.runtimeEvidence.length > 12) {
|
|
30
120
|
spine.runtimeEvidence.splice(0, spine.runtimeEvidence.length - 12);
|
|
@@ -70,6 +160,17 @@ function parseExplainSubject(subjectRaw) {
|
|
|
70
160
|
case "soul":
|
|
71
161
|
case "soul-change":
|
|
72
162
|
return { subjectType: "soul-change", subjectId: id };
|
|
163
|
+
case "fallback":
|
|
164
|
+
return { subjectType: "fallback", subjectId: id };
|
|
165
|
+
case "probe":
|
|
166
|
+
return { subjectType: "probe", subjectId: id };
|
|
167
|
+
case "report":
|
|
168
|
+
return { subjectType: "report", subjectId: id };
|
|
169
|
+
case "delivery":
|
|
170
|
+
return { subjectType: "delivery", subjectId: id };
|
|
171
|
+
case "source":
|
|
172
|
+
case "source_ref":
|
|
173
|
+
return { subjectType: "source_ref", subjectId: id };
|
|
73
174
|
default:
|
|
74
175
|
throw new Error("explain_subject_unsupported");
|
|
75
176
|
}
|
|
@@ -77,56 +178,73 @@ function parseExplainSubject(subjectRaw) {
|
|
|
77
178
|
function buildStatusPayload(spine) {
|
|
78
179
|
const runtimeEvidence = latestRuntimeEvidence(spine);
|
|
79
180
|
const updatedAt = runtimeEvidence?.createdAt ?? new Date(spine.lifecycleState.lastChangedAt).toISOString();
|
|
181
|
+
const wr = spine.workspaceRootContext;
|
|
182
|
+
const needsRootHint = wr.resolution === "unknown";
|
|
80
183
|
return {
|
|
81
|
-
ok:
|
|
184
|
+
ok: false,
|
|
185
|
+
surfaceMode: "host_safe_carrier",
|
|
186
|
+
workspaceReadModelsEvaluated: false,
|
|
187
|
+
message: HOST_SAFE_LIMITATION_MESSAGE,
|
|
188
|
+
error: {
|
|
189
|
+
code: "WORKSPACE_READ_SURFACE_UNAVAILABLE",
|
|
190
|
+
message: "Aggregated status requires workspace state; the host-safe plugin does not load persisted read models on this surface.",
|
|
191
|
+
requiredUserInput: needsRootHint ? ["SECOND_NATURE_WORKSPACE_ROOT or tool workspaceRoot"] : [],
|
|
192
|
+
nextStep: "run_workspace_second_nature_cli_or_full_runtime_package",
|
|
193
|
+
},
|
|
82
194
|
data: {
|
|
83
|
-
|
|
195
|
+
workspaceRootResolution: wr.resolution,
|
|
196
|
+
carrier: {
|
|
84
197
|
host: "openclaw-plugin",
|
|
85
198
|
serviceStatus: spine.runtimeHandle.ready ? "running" : "idle",
|
|
86
199
|
updatedAt,
|
|
87
|
-
|
|
88
|
-
rhythm: {
|
|
89
|
-
mode: "active",
|
|
90
|
-
windowId: undefined,
|
|
91
|
-
},
|
|
92
|
-
quiet: {
|
|
93
|
-
mode: "unknown",
|
|
94
|
-
lastEvent: runtimeEvidence?.traceId,
|
|
95
|
-
interrupted: undefined,
|
|
96
|
-
},
|
|
97
|
-
connectors: [],
|
|
98
|
-
credentials: [],
|
|
99
|
-
risk: {
|
|
100
|
-
level: "low",
|
|
101
|
-
flags: [],
|
|
200
|
+
lastRuntimeTraceId: runtimeEvidence?.traceId,
|
|
102
201
|
},
|
|
103
202
|
},
|
|
104
203
|
};
|
|
105
204
|
}
|
|
106
|
-
function buildQuietPayload(scope) {
|
|
205
|
+
function buildQuietPayload(spine, scope) {
|
|
206
|
+
const wr = spine.workspaceRootContext;
|
|
107
207
|
return {
|
|
108
|
-
ok:
|
|
208
|
+
ok: false,
|
|
209
|
+
surfaceMode: "host_safe_carrier",
|
|
210
|
+
workspaceReadModelsEvaluated: false,
|
|
211
|
+
message: HOST_SAFE_LIMITATION_MESSAGE,
|
|
212
|
+
error: {
|
|
213
|
+
code: "QUIET_READ_SURFACE_UNAVAILABLE",
|
|
214
|
+
message: "Quiet read surface requires workspace runtime; not evaluated in host-safe carrier mode.",
|
|
215
|
+
requiredUserInput: wr.resolution === "unknown" ? ["SECOND_NATURE_WORKSPACE_ROOT or tool workspaceRoot"] : [],
|
|
216
|
+
nextStep: "run_workspace_second_nature_cli_or_full_runtime_package",
|
|
217
|
+
},
|
|
109
218
|
data: {
|
|
110
219
|
scope,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
recentJournalCount: 0,
|
|
220
|
+
evaluated: false,
|
|
221
|
+
unavailableReason: "host_safe_carrier_no_workspace_db",
|
|
222
|
+
workspaceRootResolution: wr.resolution,
|
|
115
223
|
},
|
|
116
224
|
};
|
|
117
225
|
}
|
|
118
|
-
function buildReportPayload(day) {
|
|
226
|
+
function buildReportPayload(spine, day) {
|
|
227
|
+
const wr = spine.workspaceRootContext;
|
|
119
228
|
return {
|
|
120
|
-
ok:
|
|
229
|
+
ok: false,
|
|
230
|
+
surfaceMode: "host_safe_carrier",
|
|
231
|
+
workspaceReadModelsEvaluated: false,
|
|
232
|
+
message: HOST_SAFE_LIMITATION_MESSAGE,
|
|
233
|
+
error: {
|
|
234
|
+
code: "REPORT_READ_SURFACE_UNAVAILABLE",
|
|
235
|
+
message: "Daily report artifacts require workspace runtime.",
|
|
236
|
+
requiredUserInput: wr.resolution === "unknown" ? ["SECOND_NATURE_WORKSPACE_ROOT or tool workspaceRoot"] : [],
|
|
237
|
+
nextStep: "run_workspace_second_nature_cli_or_full_runtime_package",
|
|
238
|
+
},
|
|
121
239
|
data: {
|
|
240
|
+
evaluated: false,
|
|
241
|
+
unavailableReason: "host_safe_carrier_no_workspace_db",
|
|
122
242
|
day: day && day.trim() ? day : new Date().toISOString().slice(0, 10),
|
|
123
|
-
|
|
124
|
-
highlights: [],
|
|
125
|
-
sourceRefs: [],
|
|
243
|
+
workspaceRootResolution: wr.resolution,
|
|
126
244
|
},
|
|
127
245
|
};
|
|
128
246
|
}
|
|
129
|
-
function buildSessionPayload(sessionId) {
|
|
247
|
+
function buildSessionPayload(spine, sessionId) {
|
|
130
248
|
if (!sessionId) {
|
|
131
249
|
return {
|
|
132
250
|
ok: false,
|
|
@@ -138,26 +256,44 @@ function buildSessionPayload(sessionId) {
|
|
|
138
256
|
},
|
|
139
257
|
};
|
|
140
258
|
}
|
|
259
|
+
const wr = spine.workspaceRootContext;
|
|
141
260
|
return {
|
|
142
|
-
ok:
|
|
261
|
+
ok: false,
|
|
262
|
+
surfaceMode: "host_safe_carrier",
|
|
263
|
+
workspaceReadModelsEvaluated: false,
|
|
264
|
+
message: HOST_SAFE_LIMITATION_MESSAGE,
|
|
265
|
+
error: {
|
|
266
|
+
code: "SESSION_READ_SURFACE_UNAVAILABLE",
|
|
267
|
+
message: "Session analytics require workspace state database.",
|
|
268
|
+
requiredUserInput: wr.resolution === "unknown" ? ["SECOND_NATURE_WORKSPACE_ROOT or tool workspaceRoot"] : [],
|
|
269
|
+
nextStep: "run_workspace_second_nature_cli_or_full_runtime_package",
|
|
270
|
+
},
|
|
143
271
|
data: {
|
|
144
272
|
requestedSessionId: sessionId,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
governanceCount: 0,
|
|
149
|
-
keyFactors: [],
|
|
150
|
-
evidenceRefs: [],
|
|
273
|
+
evaluated: false,
|
|
274
|
+
unavailableReason: "host_safe_carrier_no_workspace_db",
|
|
275
|
+
workspaceRootResolution: wr.resolution,
|
|
151
276
|
},
|
|
152
277
|
};
|
|
153
278
|
}
|
|
154
|
-
function buildCredentialPayload(platformId) {
|
|
279
|
+
function buildCredentialPayload(spine, platformId) {
|
|
280
|
+
const wr = spine.workspaceRootContext;
|
|
155
281
|
return {
|
|
156
|
-
ok:
|
|
282
|
+
ok: false,
|
|
283
|
+
surfaceMode: "host_safe_carrier",
|
|
284
|
+
workspaceReadModelsEvaluated: false,
|
|
285
|
+
message: HOST_SAFE_LIMITATION_MESSAGE,
|
|
286
|
+
error: {
|
|
287
|
+
code: "CREDENTIAL_READ_SURFACE_UNAVAILABLE",
|
|
288
|
+
message: "Credential inspection requires workspace runtime on this surface.",
|
|
289
|
+
requiredUserInput: wr.resolution === "unknown" ? ["SECOND_NATURE_WORKSPACE_ROOT or tool workspaceRoot"] : [],
|
|
290
|
+
nextStep: "run_workspace_second_nature_cli_or_full_runtime_package",
|
|
291
|
+
},
|
|
157
292
|
data: {
|
|
158
|
-
platformId: platformId && platformId.trim() ? platformId :
|
|
159
|
-
|
|
160
|
-
|
|
293
|
+
platformId: platformId && platformId.trim() ? platformId : undefined,
|
|
294
|
+
evaluated: false,
|
|
295
|
+
unavailableReason: "host_safe_carrier_no_workspace_db",
|
|
296
|
+
workspaceRootResolution: wr.resolution,
|
|
161
297
|
},
|
|
162
298
|
};
|
|
163
299
|
}
|
|
@@ -183,44 +319,79 @@ function buildExplainPayload(spine, subjectRaw) {
|
|
|
183
319
|
return createUnavailableActionError("EXPLAIN_SUBJECT_REQUIRES_ID", "subject must include identifier", ["subject"], "reinvoke_explain_with_supported_subject");
|
|
184
320
|
}
|
|
185
321
|
if (code === "explain_subject_unsupported") {
|
|
186
|
-
return createUnavailableActionError("EXPLAIN_SUBJECT_UNSUPPORTED", "supported subjects
|
|
322
|
+
return createUnavailableActionError("EXPLAIN_SUBJECT_UNSUPPORTED", "supported subjects include decision:, platform:, outreach:, soul:, fallback:, delivery:, probe:, report:, source:", ["subject"], "reinvoke_explain_with_supported_subject");
|
|
187
323
|
}
|
|
188
324
|
return createUnavailableActionError("EXPLAIN_SUBJECT_INVALID", "invalid explain subject", ["subject"], "reinvoke_explain_with_supported_subject");
|
|
189
325
|
}
|
|
190
|
-
const
|
|
326
|
+
const wr = spine.workspaceRootContext;
|
|
191
327
|
return {
|
|
192
|
-
ok:
|
|
328
|
+
ok: false,
|
|
329
|
+
surfaceMode: "host_safe_carrier",
|
|
330
|
+
workspaceReadModelsEvaluated: false,
|
|
331
|
+
message: HOST_SAFE_LIMITATION_MESSAGE,
|
|
332
|
+
error: {
|
|
333
|
+
code: "EXPLAIN_READ_SURFACE_UNAVAILABLE",
|
|
334
|
+
message: "Evidence-backed explain requires persisted workspace read models; host-safe carrier did not evaluate operator explain (CH-11-02).",
|
|
335
|
+
requiredUserInput: wr.resolution === "unknown" ? ["SECOND_NATURE_WORKSPACE_ROOT or tool workspaceRoot"] : [],
|
|
336
|
+
nextStep: "run_workspace_second_nature_cli_or_full_runtime_package",
|
|
337
|
+
},
|
|
193
338
|
data: {
|
|
194
339
|
subjectType: subject.subjectType,
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
"synchronous_register",
|
|
198
|
-
`subject:${subject.subjectId}`,
|
|
199
|
-
runtimeEvidence?.capability ?? "runtime.activate",
|
|
200
|
-
],
|
|
201
|
-
evidenceRefs: [
|
|
202
|
-
runtimeEvidence?.traceId ?? `${INTERNAL_RUNTIME_TRACE_PREFIX}none`,
|
|
203
|
-
`subject:${subjectRaw.trim()}`,
|
|
204
|
-
"host_safe_mode",
|
|
205
|
-
],
|
|
206
|
-
nextStep: "use full workspace runtime for evidence-backed explain details",
|
|
340
|
+
evaluated: false,
|
|
341
|
+
workspaceRootResolution: wr.resolution,
|
|
207
342
|
},
|
|
208
343
|
};
|
|
209
344
|
}
|
|
345
|
+
async function buildStorageSmokePayload(input) {
|
|
346
|
+
try {
|
|
347
|
+
const mod = await import("./runtime/storage/bootstrap/storage-mode-smoke.js");
|
|
348
|
+
const runRepairFixture = Boolean(input?.runRepairFixture);
|
|
349
|
+
const workspaceRoot = typeof input?.workspaceRoot === "string" ? input.workspaceRoot : undefined;
|
|
350
|
+
const data = await mod.runStorageModeSmoke({ runRepairFixture, workspaceRoot });
|
|
351
|
+
return { ok: true, data };
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
return {
|
|
355
|
+
ok: false,
|
|
356
|
+
message: error instanceof Error ? error.message : String(error),
|
|
357
|
+
error: {
|
|
358
|
+
code: "STORAGE_SMOKE_LOAD_FAILED",
|
|
359
|
+
message: "Could not load packaged storage-mode smoke module",
|
|
360
|
+
nextStep: "rebuild_plugin_runtime_package",
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
function buildFallbackHostSafePayload(ref) {
|
|
366
|
+
if (!ref?.trim()) {
|
|
367
|
+
return {
|
|
368
|
+
ok: false,
|
|
369
|
+
error: {
|
|
370
|
+
code: "MISSING_FALLBACK_REF",
|
|
371
|
+
message: "fallback requires ref (e.g. fallback:…)",
|
|
372
|
+
requiredUserInput: ["ref"],
|
|
373
|
+
nextStep: "reinvoke_with_ref",
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
return createUnavailableActionError("HOST_SAFE_FALLBACK_VIEW_UNAVAILABLE", "Operator fallback view requires workspace state database; host-safe plugin cannot read persisted fallback artifacts.", ["ref"], "run_workspace_second_nature_cli_or_full_runtime_package");
|
|
378
|
+
}
|
|
210
379
|
function buildHeartbeatCheckPayload(spine, input) {
|
|
211
380
|
const runtimeEvidence = latestRuntimeEvidence(spine);
|
|
212
381
|
const updatedAt = runtimeEvidence?.createdAt ?? new Date(spine.lifecycleState.lastChangedAt).toISOString();
|
|
213
382
|
const timestamp = typeof input?.timestamp === "string" && input.timestamp.trim().length > 0 ? input.timestamp : updatedAt;
|
|
383
|
+
const wr = spine.workspaceRootContext;
|
|
214
384
|
return {
|
|
215
385
|
ok: true,
|
|
216
|
-
status: "
|
|
217
|
-
|
|
386
|
+
status: "runtime_carrier_only",
|
|
387
|
+
livedExperienceLoopClaimed: false,
|
|
218
388
|
scope: "rhythm",
|
|
219
389
|
trigger: "heartbeat_bridge",
|
|
220
|
-
reasons: ["
|
|
221
|
-
nextAction: "
|
|
222
|
-
message: "
|
|
390
|
+
reasons: ["runtime_carrier_only", "host_safe_bridge_ack"],
|
|
391
|
+
nextAction: "continue_carrier_surface_only",
|
|
392
|
+
message: "Packaged carrier acknowledged this heartbeat round. This is not a full lived-experience decision loop; use the workspace CLI when read models are required.",
|
|
223
393
|
data: {
|
|
394
|
+
workspaceRootResolution: wr.resolution,
|
|
224
395
|
runtime: {
|
|
225
396
|
host: "openclaw-plugin",
|
|
226
397
|
serviceStatus: spine.runtimeHandle.ready ? "running" : "idle",
|
|
@@ -271,7 +442,7 @@ function createHostSafeRouter(spine) {
|
|
|
271
442
|
return createUnavailableActionError("HOST_SAFE_CREDENTIAL_VERIFY_UNAVAILABLE", "credential verify is unavailable in the host-safe plugin package", ["verification_answer"], "run_workspace_runtime_or_reinstall_full_build");
|
|
272
443
|
}
|
|
273
444
|
const platformId = typeof input?.platformId === "string" ? input.platformId : undefined;
|
|
274
|
-
return buildCredentialPayload(platformId);
|
|
445
|
+
return buildCredentialPayload(spine, platformId);
|
|
275
446
|
},
|
|
276
447
|
},
|
|
277
448
|
{
|
|
@@ -279,7 +450,7 @@ function createHostSafeRouter(spine) {
|
|
|
279
450
|
description: "Inspect Quiet lifecycle state",
|
|
280
451
|
execute: async (input) => {
|
|
281
452
|
const scope = typeof input?.scope === "string" ? input.scope : undefined;
|
|
282
|
-
return buildQuietPayload(scope);
|
|
453
|
+
return buildQuietPayload(spine, scope);
|
|
283
454
|
},
|
|
284
455
|
},
|
|
285
456
|
{
|
|
@@ -287,7 +458,7 @@ function createHostSafeRouter(spine) {
|
|
|
287
458
|
description: "Show daily report artifacts",
|
|
288
459
|
execute: async (input) => {
|
|
289
460
|
const day = typeof input?.day === "string" ? input.day : undefined;
|
|
290
|
-
return buildReportPayload(day);
|
|
461
|
+
return buildReportPayload(spine, day);
|
|
291
462
|
},
|
|
292
463
|
},
|
|
293
464
|
{
|
|
@@ -295,7 +466,7 @@ function createHostSafeRouter(spine) {
|
|
|
295
466
|
description: "Inspect continuity session details",
|
|
296
467
|
execute: async (input) => {
|
|
297
468
|
const sessionId = typeof input?.sessionId === "string" ? input.sessionId : undefined;
|
|
298
|
-
return buildSessionPayload(sessionId);
|
|
469
|
+
return buildSessionPayload(spine, sessionId);
|
|
299
470
|
},
|
|
300
471
|
},
|
|
301
472
|
{
|
|
@@ -316,6 +487,19 @@ function createHostSafeRouter(spine) {
|
|
|
316
487
|
description: "Acknowledge the shipping heartbeat bridge round",
|
|
317
488
|
execute: async (input) => buildHeartbeatCheckPayload(spine, input),
|
|
318
489
|
},
|
|
490
|
+
{
|
|
491
|
+
name: "fallback",
|
|
492
|
+
description: "Operator-visible delivery fallback view (full workspace runtime required)",
|
|
493
|
+
execute: async (input) => {
|
|
494
|
+
const ref = typeof input?.ref === "string" ? input.ref.trim() : undefined;
|
|
495
|
+
return buildFallbackHostSafePayload(ref);
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
name: "storage_smoke",
|
|
500
|
+
description: "T4.1.4 storage mode smoke report (sql.js vs native probe)",
|
|
501
|
+
execute: async (input) => buildStorageSmokePayload(input),
|
|
502
|
+
},
|
|
319
503
|
];
|
|
320
504
|
return {
|
|
321
505
|
commands,
|
|
@@ -325,12 +509,14 @@ function createHostSafeRouter(spine) {
|
|
|
325
509
|
};
|
|
326
510
|
}
|
|
327
511
|
function createActivationSpine() {
|
|
512
|
+
const workspaceRootContext = resolveWorkspaceRoot(undefined);
|
|
328
513
|
const spine = {
|
|
329
514
|
router: undefined,
|
|
330
|
-
runtimeHandle: startRuntimeService({ workspaceRoot:
|
|
515
|
+
runtimeHandle: startRuntimeService({ workspaceRoot: workspaceRootContext.runtimeRoot }),
|
|
331
516
|
lifecycleState: getLifecycleState(),
|
|
332
517
|
serviceStartRecorded: false,
|
|
333
518
|
runtimeEvidence: [],
|
|
519
|
+
workspaceRootContext,
|
|
334
520
|
};
|
|
335
521
|
spine.router = createHostSafeRouter(spine);
|
|
336
522
|
return spine;
|
|
@@ -364,7 +550,14 @@ function recordRuntimeEvidence(spine, origin) {
|
|
|
364
550
|
}
|
|
365
551
|
function refreshRegistrationState() {
|
|
366
552
|
const spine = ensureActivationSpine();
|
|
367
|
-
|
|
553
|
+
const workspaceRootContext = resolveWorkspaceRoot(undefined);
|
|
554
|
+
const prev = spine.workspaceRootContext;
|
|
555
|
+
const changed = workspaceRootContext.runtimeRoot !== prev.runtimeRoot || workspaceRootContext.resolution !== prev.resolution;
|
|
556
|
+
if (changed) {
|
|
557
|
+
disposeWorkspaceOpsBridge();
|
|
558
|
+
}
|
|
559
|
+
spine.workspaceRootContext = workspaceRootContext;
|
|
560
|
+
spine.runtimeHandle = startRuntimeService({ workspaceRoot: workspaceRootContext.runtimeRoot });
|
|
368
561
|
spine.lifecycleState = recordRegistration();
|
|
369
562
|
spine.serviceStartRecorded = false;
|
|
370
563
|
recordRuntimeEvidence(spine, "register");
|
|
@@ -442,6 +635,20 @@ function parseCommandInput(rawArgs) {
|
|
|
442
635
|
command,
|
|
443
636
|
input: rest.length > 0 ? { subject: rest.join(" ") } : undefined,
|
|
444
637
|
};
|
|
638
|
+
case "fallback":
|
|
639
|
+
return {
|
|
640
|
+
ok: true,
|
|
641
|
+
command,
|
|
642
|
+
input: rest.length > 0 ? { ref: rest.join(" ") } : undefined,
|
|
643
|
+
};
|
|
644
|
+
case "storage_smoke": {
|
|
645
|
+
const wantRepair = rest[0] === "repair" || rest.includes("--repair");
|
|
646
|
+
return {
|
|
647
|
+
ok: true,
|
|
648
|
+
command,
|
|
649
|
+
input: wantRepair ? { runRepairFixture: true } : undefined,
|
|
650
|
+
};
|
|
651
|
+
}
|
|
445
652
|
default:
|
|
446
653
|
return {
|
|
447
654
|
ok: true,
|
|
@@ -503,7 +710,7 @@ export default {
|
|
|
503
710
|
text: JSON.stringify({ ok: false, command: parsed.command, message: "Unknown Second Nature command." }),
|
|
504
711
|
};
|
|
505
712
|
}
|
|
506
|
-
const result = await
|
|
713
|
+
const result = await routeSecondNatureCommand(spine, parsed.command, parsed.input);
|
|
507
714
|
return {
|
|
508
715
|
text: JSON.stringify(result),
|
|
509
716
|
};
|
|
@@ -518,11 +725,16 @@ export default {
|
|
|
518
725
|
properties: {
|
|
519
726
|
command: { type: "string" },
|
|
520
727
|
args: { type: "object", additionalProperties: true },
|
|
728
|
+
workspaceRoot: {
|
|
729
|
+
type: "string",
|
|
730
|
+
description: "Workspace root for packaged smoke/runtime alignment (optional; prefer SECOND_NATURE_WORKSPACE_ROOT).",
|
|
731
|
+
},
|
|
521
732
|
},
|
|
522
733
|
required: ["command"],
|
|
523
734
|
},
|
|
524
735
|
async execute(_id, params) {
|
|
525
736
|
const spine = ensureActivationSpine();
|
|
737
|
+
syncWorkspaceRootFromTool(spine, params.workspaceRoot);
|
|
526
738
|
const resolved = spine.router.resolve(params.command);
|
|
527
739
|
if (!resolved) {
|
|
528
740
|
return {
|
|
@@ -534,7 +746,7 @@ export default {
|
|
|
534
746
|
],
|
|
535
747
|
};
|
|
536
748
|
}
|
|
537
|
-
const result = await
|
|
749
|
+
const result = await routeSecondNatureCommand(spine, params.command, params.args);
|
|
538
750
|
return {
|
|
539
751
|
content: [
|
|
540
752
|
{
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haaaiawd/second-nature",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "OpenClaw native plugin with synchronous registration, a packaged runtime artifact, and operator-facing status/explain flows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openclaw",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"main": "./index.js",
|
|
18
18
|
"files": [
|
|
19
19
|
"index.js",
|
|
20
|
+
"workspace-ops-bridge.js",
|
|
20
21
|
"openclaw.plugin.json",
|
|
21
22
|
"runtime/"
|
|
22
23
|
],
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ActionBridge } from "../action-bridge.js";
|
|
2
|
+
import type { OpsRouter } from "../ops/ops-router.js";
|
|
2
3
|
import type { CliReadModels } from "../read-models/index.js";
|
|
3
4
|
export interface CliCommandDefinition {
|
|
4
5
|
name: string;
|
|
@@ -8,5 +9,6 @@ export interface CliCommandDefinition {
|
|
|
8
9
|
export interface CliCommandDeps {
|
|
9
10
|
readModels: CliReadModels;
|
|
10
11
|
actionBridge: ActionBridge;
|
|
12
|
+
opsRouter: OpsRouter;
|
|
11
13
|
}
|
|
12
14
|
export declare function createCliCommands(deps: CliCommandDeps): CliCommandDefinition[];
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { credentialVerify } from "./credential.js";
|
|
2
2
|
import { formatExplanation } from "../explain/format-explanation.js";
|
|
3
|
-
import {
|
|
3
|
+
import { explainSurfaceSubject } from "../explain/explain-surface-subject.js";
|
|
4
|
+
import { showOperatorFallback, OperatorFallbackNotFoundError } from "../ops/show-operator-fallback.js";
|
|
5
|
+
import { runStorageModeSmoke } from "../../storage/bootstrap/storage-mode-smoke.js";
|
|
4
6
|
import { policySet } from "./policy.js";
|
|
5
7
|
const notImplemented = async (command) => ({
|
|
6
8
|
ok: false,
|
|
@@ -19,7 +21,7 @@ function explainSubjectError(code, message) {
|
|
|
19
21
|
};
|
|
20
22
|
}
|
|
21
23
|
export function createCliCommands(deps) {
|
|
22
|
-
const { readModels, actionBridge } = deps;
|
|
24
|
+
const { readModels, actionBridge, opsRouter } = deps;
|
|
23
25
|
return [
|
|
24
26
|
{
|
|
25
27
|
name: "status",
|
|
@@ -113,9 +115,9 @@ export function createCliCommands(deps) {
|
|
|
113
115
|
},
|
|
114
116
|
};
|
|
115
117
|
}
|
|
116
|
-
let
|
|
118
|
+
let model;
|
|
117
119
|
try {
|
|
118
|
-
|
|
120
|
+
model = await explainSurfaceSubject(subjectRaw, readModels);
|
|
119
121
|
}
|
|
120
122
|
catch (error) {
|
|
121
123
|
const code = error.message;
|
|
@@ -123,16 +125,69 @@ export function createCliCommands(deps) {
|
|
|
123
125
|
return explainSubjectError("EXPLAIN_SUBJECT_REQUIRES_ID", "subject must include identifier");
|
|
124
126
|
}
|
|
125
127
|
if (code === "explain_subject_unsupported") {
|
|
126
|
-
return explainSubjectError("EXPLAIN_SUBJECT_UNSUPPORTED", "supported subjects
|
|
128
|
+
return explainSubjectError("EXPLAIN_SUBJECT_UNSUPPORTED", "supported subjects include decision:, platform:, outreach:, soul:, fallback:, delivery:, probe:, report:, source:");
|
|
127
129
|
}
|
|
128
130
|
return explainSubjectError("EXPLAIN_SUBJECT_INVALID", "invalid explain subject");
|
|
129
131
|
}
|
|
130
|
-
const model = await readModels.explain(subject);
|
|
131
132
|
return {
|
|
132
133
|
ok: true,
|
|
133
134
|
data: formatExplanation(model),
|
|
134
135
|
};
|
|
135
136
|
},
|
|
136
137
|
},
|
|
138
|
+
{
|
|
139
|
+
name: "heartbeat_check",
|
|
140
|
+
description: "Workspace heartbeat_check ops surface (v5 HeartbeatSurfaceResult)",
|
|
141
|
+
execute: async (input) => {
|
|
142
|
+
const surface = await Promise.resolve(opsRouter.dispatch("heartbeat_check", input));
|
|
143
|
+
return surface;
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "storage_smoke",
|
|
148
|
+
description: "T4.1.4 — report sql.js vs native SQLite probe and optional artifact→index repair fixture",
|
|
149
|
+
execute: async (input) => {
|
|
150
|
+
const runRepairFixture = Boolean(input?.runRepairFixture);
|
|
151
|
+
const workspaceRoot = typeof input?.workspaceRoot === "string" ? input.workspaceRoot : undefined;
|
|
152
|
+
const data = await runStorageModeSmoke({ runRepairFixture, workspaceRoot });
|
|
153
|
+
return { ok: true, data };
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "fallback",
|
|
158
|
+
description: "Operator-visible delivery fallback view (status always not_sent)",
|
|
159
|
+
execute: async (input) => {
|
|
160
|
+
const ref = typeof input?.ref === "string" ? input.ref.trim() : "";
|
|
161
|
+
if (!ref) {
|
|
162
|
+
return {
|
|
163
|
+
ok: false,
|
|
164
|
+
error: {
|
|
165
|
+
code: "MISSING_FALLBACK_REF",
|
|
166
|
+
message: "fallback requires ref (e.g. fallback:…)",
|
|
167
|
+
requiredUserInput: ["ref"],
|
|
168
|
+
nextStep: "reinvoke_with_ref",
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const data = await showOperatorFallback(ref, readModels);
|
|
174
|
+
return { ok: true, data };
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
if (error instanceof OperatorFallbackNotFoundError) {
|
|
178
|
+
return {
|
|
179
|
+
ok: false,
|
|
180
|
+
error: {
|
|
181
|
+
code: error.code,
|
|
182
|
+
message: error.message,
|
|
183
|
+
requiredUserInput: ["ref"],
|
|
184
|
+
nextStep: "verify_fallback_ref_from_delivery_audit",
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
},
|
|
137
192
|
];
|
|
138
193
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable operator explain entry matching cli-system.detail §3.8 (T1.2.1).
|
|
3
|
+
*
|
|
4
|
+
* Core logic: parse subject string via resolveExplainSubject, delegate to read models.
|
|
5
|
+
*/
|
|
6
|
+
import type { CliReadModels } from "../read-models/index.js";
|
|
7
|
+
import type { ExplainReadModel } from "../read-models/types.js";
|
|
8
|
+
export declare function explainSurfaceSubject(subjectRaw: string, readModels: CliReadModels): Promise<ExplainReadModel>;
|