@haaaiawd/second-nature 0.1.8 → 0.1.9
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 +73 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -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 +161 -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/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 +46 -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/index.js
CHANGED
|
@@ -70,6 +70,17 @@ function parseExplainSubject(subjectRaw) {
|
|
|
70
70
|
case "soul":
|
|
71
71
|
case "soul-change":
|
|
72
72
|
return { subjectType: "soul-change", subjectId: id };
|
|
73
|
+
case "fallback":
|
|
74
|
+
return { subjectType: "fallback", subjectId: id };
|
|
75
|
+
case "probe":
|
|
76
|
+
return { subjectType: "probe", subjectId: id };
|
|
77
|
+
case "report":
|
|
78
|
+
return { subjectType: "report", subjectId: id };
|
|
79
|
+
case "delivery":
|
|
80
|
+
return { subjectType: "delivery", subjectId: id };
|
|
81
|
+
case "source":
|
|
82
|
+
case "source_ref":
|
|
83
|
+
return { subjectType: "source_ref", subjectId: id };
|
|
73
84
|
default:
|
|
74
85
|
throw new Error("explain_subject_unsupported");
|
|
75
86
|
}
|
|
@@ -183,7 +194,7 @@ function buildExplainPayload(spine, subjectRaw) {
|
|
|
183
194
|
return createUnavailableActionError("EXPLAIN_SUBJECT_REQUIRES_ID", "subject must include identifier", ["subject"], "reinvoke_explain_with_supported_subject");
|
|
184
195
|
}
|
|
185
196
|
if (code === "explain_subject_unsupported") {
|
|
186
|
-
return createUnavailableActionError("EXPLAIN_SUBJECT_UNSUPPORTED", "supported subjects
|
|
197
|
+
return createUnavailableActionError("EXPLAIN_SUBJECT_UNSUPPORTED", "supported subjects include decision:, platform:, outreach:, soul:, fallback:, delivery:, probe:, report:, source:", ["subject"], "reinvoke_explain_with_supported_subject");
|
|
187
198
|
}
|
|
188
199
|
return createUnavailableActionError("EXPLAIN_SUBJECT_INVALID", "invalid explain subject", ["subject"], "reinvoke_explain_with_supported_subject");
|
|
189
200
|
}
|
|
@@ -207,6 +218,40 @@ function buildExplainPayload(spine, subjectRaw) {
|
|
|
207
218
|
},
|
|
208
219
|
};
|
|
209
220
|
}
|
|
221
|
+
async function buildStorageSmokePayload(input) {
|
|
222
|
+
try {
|
|
223
|
+
const mod = await import("./runtime/storage/bootstrap/storage-mode-smoke.js");
|
|
224
|
+
const runRepairFixture = Boolean(input?.runRepairFixture);
|
|
225
|
+
const workspaceRoot = typeof input?.workspaceRoot === "string" ? input.workspaceRoot : undefined;
|
|
226
|
+
const data = await mod.runStorageModeSmoke({ runRepairFixture, workspaceRoot });
|
|
227
|
+
return { ok: true, data };
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
return {
|
|
231
|
+
ok: false,
|
|
232
|
+
message: error instanceof Error ? error.message : String(error),
|
|
233
|
+
error: {
|
|
234
|
+
code: "STORAGE_SMOKE_LOAD_FAILED",
|
|
235
|
+
message: "Could not load packaged storage-mode smoke module",
|
|
236
|
+
nextStep: "rebuild_plugin_runtime_package",
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function buildFallbackHostSafePayload(ref) {
|
|
242
|
+
if (!ref?.trim()) {
|
|
243
|
+
return {
|
|
244
|
+
ok: false,
|
|
245
|
+
error: {
|
|
246
|
+
code: "MISSING_FALLBACK_REF",
|
|
247
|
+
message: "fallback requires ref (e.g. fallback:…)",
|
|
248
|
+
requiredUserInput: ["ref"],
|
|
249
|
+
nextStep: "reinvoke_with_ref",
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
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");
|
|
254
|
+
}
|
|
210
255
|
function buildHeartbeatCheckPayload(spine, input) {
|
|
211
256
|
const runtimeEvidence = latestRuntimeEvidence(spine);
|
|
212
257
|
const updatedAt = runtimeEvidence?.createdAt ?? new Date(spine.lifecycleState.lastChangedAt).toISOString();
|
|
@@ -316,6 +361,19 @@ function createHostSafeRouter(spine) {
|
|
|
316
361
|
description: "Acknowledge the shipping heartbeat bridge round",
|
|
317
362
|
execute: async (input) => buildHeartbeatCheckPayload(spine, input),
|
|
318
363
|
},
|
|
364
|
+
{
|
|
365
|
+
name: "fallback",
|
|
366
|
+
description: "Operator-visible delivery fallback view (full workspace runtime required)",
|
|
367
|
+
execute: async (input) => {
|
|
368
|
+
const ref = typeof input?.ref === "string" ? input.ref.trim() : undefined;
|
|
369
|
+
return buildFallbackHostSafePayload(ref);
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
name: "storage_smoke",
|
|
374
|
+
description: "T4.1.4 storage mode smoke report (sql.js vs native probe)",
|
|
375
|
+
execute: async (input) => buildStorageSmokePayload(input),
|
|
376
|
+
},
|
|
319
377
|
];
|
|
320
378
|
return {
|
|
321
379
|
commands,
|
|
@@ -442,6 +500,20 @@ function parseCommandInput(rawArgs) {
|
|
|
442
500
|
command,
|
|
443
501
|
input: rest.length > 0 ? { subject: rest.join(" ") } : undefined,
|
|
444
502
|
};
|
|
503
|
+
case "fallback":
|
|
504
|
+
return {
|
|
505
|
+
ok: true,
|
|
506
|
+
command,
|
|
507
|
+
input: rest.length > 0 ? { ref: rest.join(" ") } : undefined,
|
|
508
|
+
};
|
|
509
|
+
case "storage_smoke": {
|
|
510
|
+
const wantRepair = rest[0] === "repair" || rest.includes("--repair");
|
|
511
|
+
return {
|
|
512
|
+
ok: true,
|
|
513
|
+
command,
|
|
514
|
+
input: wantRepair ? { runRepairFixture: true } : undefined,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
445
517
|
default:
|
|
446
518
|
return {
|
|
447
519
|
ok: true,
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -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>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { resolveExplainSubject } from "./resolve-subject.js";
|
|
2
|
+
export async function explainSurfaceSubject(subjectRaw, readModels) {
|
|
3
|
+
const trimmed = subjectRaw.trim();
|
|
4
|
+
if (!trimmed) {
|
|
5
|
+
throw new Error("explain_subject_requires_id");
|
|
6
|
+
}
|
|
7
|
+
const subject = resolveExplainSubject(trimmed);
|
|
8
|
+
return readModels.explain(subject);
|
|
9
|
+
}
|
|
@@ -6,5 +6,7 @@ export interface FormattedExplanation {
|
|
|
6
6
|
evidenceRefs: string[];
|
|
7
7
|
requiredUserInput?: string[];
|
|
8
8
|
nextStep?: string;
|
|
9
|
+
warnings?: string[];
|
|
10
|
+
relatedAuditEventIds?: string[];
|
|
9
11
|
}
|
|
10
12
|
export declare function formatExplanation(model: ExplainReadModel): FormattedExplanation;
|
|
@@ -22,5 +22,20 @@ export function resolveExplainSubject(raw) {
|
|
|
22
22
|
if (prefix === "soul") {
|
|
23
23
|
return { kind: "soul-change", id };
|
|
24
24
|
}
|
|
25
|
+
if (prefix === "fallback") {
|
|
26
|
+
return { kind: "fallback", id };
|
|
27
|
+
}
|
|
28
|
+
if (prefix === "probe") {
|
|
29
|
+
return { kind: "probe", id };
|
|
30
|
+
}
|
|
31
|
+
if (prefix === "report") {
|
|
32
|
+
return { kind: "report", id };
|
|
33
|
+
}
|
|
34
|
+
if (prefix === "delivery") {
|
|
35
|
+
return { kind: "delivery", id };
|
|
36
|
+
}
|
|
37
|
+
if (prefix === "source" || prefix === "source_ref") {
|
|
38
|
+
return { kind: "source_ref", id };
|
|
39
|
+
}
|
|
25
40
|
throw new Error("explain_subject_unsupported");
|
|
26
41
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes host-reported delivery signals into DeliveryCapabilityStatus (cli-system).
|
|
3
|
+
*/
|
|
4
|
+
import type { DeliveryCapabilityStatus } from "./types.js";
|
|
5
|
+
export interface ClassifyDeliveryCapabilityInput {
|
|
6
|
+
/** Host-reported delivery channel / target hint */
|
|
7
|
+
rawTarget?: string | null;
|
|
8
|
+
channel?: string | null;
|
|
9
|
+
/** When false, host API for delivery is not reachable */
|
|
10
|
+
apiAvailable?: boolean;
|
|
11
|
+
/** When true, host explicitly reports unsupported delivery surface */
|
|
12
|
+
hostUnsupported?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function classifyDeliveryCapability(input: ClassifyDeliveryCapabilityInput): DeliveryCapabilityStatus;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function classifyDeliveryCapability(input) {
|
|
2
|
+
if (input.hostUnsupported) {
|
|
3
|
+
return "host_unsupported";
|
|
4
|
+
}
|
|
5
|
+
if (input.apiAvailable === false) {
|
|
6
|
+
return "host_api_unavailable";
|
|
7
|
+
}
|
|
8
|
+
const target = (input.rawTarget ?? "").trim().toLowerCase();
|
|
9
|
+
if (target === "none" || target === "") {
|
|
10
|
+
return "target_none";
|
|
11
|
+
}
|
|
12
|
+
const ch = (input.channel ?? "").trim();
|
|
13
|
+
if (!ch) {
|
|
14
|
+
return "channel_missing";
|
|
15
|
+
}
|
|
16
|
+
if (target === "unknown" || target === "unspecified") {
|
|
17
|
+
return "unknown";
|
|
18
|
+
}
|
|
19
|
+
return "target_available";
|
|
20
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw host capability probe — aggregates adapter checks into HostCapabilityReport.
|
|
3
|
+
*/
|
|
4
|
+
import * as crypto from "node:crypto";
|
|
5
|
+
function mergeEvidenceRefs(...groups) {
|
|
6
|
+
const seen = new Set();
|
|
7
|
+
const out = [];
|
|
8
|
+
for (const group of groups) {
|
|
9
|
+
for (const ref of group) {
|
|
10
|
+
const key = `${ref.kind}:${ref.id}`;
|
|
11
|
+
if (!seen.has(key)) {
|
|
12
|
+
seen.add(key);
|
|
13
|
+
out.push(ref);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return out;
|
|
18
|
+
}
|
|
19
|
+
export function probeHostCapability(options) {
|
|
20
|
+
const { adapter, docLinks, docCheckedAt, hostVersion, observedVersion } = options;
|
|
21
|
+
const generatedAt = new Date().toISOString();
|
|
22
|
+
const pluginLoad = adapter.checkPluginLoad();
|
|
23
|
+
const heartbeatBridge = adapter.checkHeartbeatBridge();
|
|
24
|
+
const heartbeatToolInvocation = adapter.checkHeartbeatToolInvocation();
|
|
25
|
+
const delivery = adapter.checkDeliveryTarget();
|
|
26
|
+
const deliveryTarget = delivery.status;
|
|
27
|
+
const ackDropBehavior = adapter.checkAckDropBehavior();
|
|
28
|
+
const hookSupport = adapter.checkHookSupport();
|
|
29
|
+
const conflictRecords = [];
|
|
30
|
+
if (delivery.reason === "docs_vs_observed_mismatch" && docLinks.length > 0) {
|
|
31
|
+
const doc = docLinks[0];
|
|
32
|
+
conflictRecords.push({
|
|
33
|
+
capability: "delivery_target",
|
|
34
|
+
documentedBehavior: doc.documentedBehavior,
|
|
35
|
+
observedBehavior: deliveryTarget,
|
|
36
|
+
hostVersion,
|
|
37
|
+
docUrl: doc.url,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const evidenceRefs = mergeEvidenceRefs(pluginLoad.evidenceRefs, heartbeatBridge.evidenceRefs, heartbeatToolInvocation.evidenceRefs, delivery.evidenceRefs, ackDropBehavior.evidenceRefs, ...hookSupport.map((h) => h.evidenceRefs));
|
|
41
|
+
return {
|
|
42
|
+
reportId: crypto.randomUUID(),
|
|
43
|
+
generatedAt,
|
|
44
|
+
hostVersion,
|
|
45
|
+
observedVersion,
|
|
46
|
+
docLinks,
|
|
47
|
+
docCheckedAt,
|
|
48
|
+
pluginLoad,
|
|
49
|
+
heartbeatBridge,
|
|
50
|
+
heartbeatToolInvocation,
|
|
51
|
+
deliveryTarget,
|
|
52
|
+
ackDropBehavior,
|
|
53
|
+
hookSupport,
|
|
54
|
+
evidenceRefs,
|
|
55
|
+
conflictRecords,
|
|
56
|
+
recommendedNextStep: conflictRecords.length > 0 ? "reconcile_docs_vs_observed" : undefined,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persist HostCapabilityReport into observability SQLite (T1.1.2).
|
|
3
|
+
*/
|
|
4
|
+
import type { ObservabilityDatabase } from "../../observability/db/index.js";
|
|
5
|
+
import type { HostCapabilityReport } from "./types.js";
|
|
6
|
+
export declare function recordHostCapability(db: ObservabilityDatabase, report: HostCapabilityReport): Promise<void>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { hostCapabilityReports } from "../../observability/db/schema/host-capability-reports.js";
|
|
2
|
+
export async function recordHostCapability(db, report) {
|
|
3
|
+
await db.db.insert(hostCapabilityReports).values({
|
|
4
|
+
reportId: report.reportId,
|
|
5
|
+
generatedAt: report.generatedAt,
|
|
6
|
+
hostVersion: report.hostVersion ?? null,
|
|
7
|
+
observedVersion: report.observedVersion ?? null,
|
|
8
|
+
docCheckedAt: report.docCheckedAt,
|
|
9
|
+
docLinksJson: JSON.stringify(report.docLinks),
|
|
10
|
+
deliveryTarget: report.deliveryTarget,
|
|
11
|
+
conflictRecordsJson: JSON.stringify(report.conflictRecords),
|
|
12
|
+
fullReportJson: JSON.stringify(report),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host capability probe contracts (cli-system v5 / ADR-007).
|
|
3
|
+
*
|
|
4
|
+
* Test coverage: tests/unit/cli/host-capability.test.ts, tests/integration/cli/host-capability-probe.test.ts
|
|
5
|
+
*/
|
|
6
|
+
export type DeliveryCapabilityStatus = "target_available" | "target_none" | "channel_missing" | "host_api_unavailable" | "host_unsupported" | "unknown";
|
|
7
|
+
export type CapabilityVerdict = "pass" | "fail" | "unknown" | "not_applicable";
|
|
8
|
+
export interface SourceRef {
|
|
9
|
+
id: string;
|
|
10
|
+
kind: "platform_item" | "workspace_artifact" | "decision_record" | "user_anchor" | "connector_result" | "host_report" | "fallback_artifact";
|
|
11
|
+
uri: string;
|
|
12
|
+
excerptHash?: string;
|
|
13
|
+
observedAt?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface HostCapabilityDocReference {
|
|
16
|
+
title: string;
|
|
17
|
+
url: string;
|
|
18
|
+
checkedAt: string;
|
|
19
|
+
documentedBehavior: string;
|
|
20
|
+
}
|
|
21
|
+
export interface HostCapabilityConflictRecord {
|
|
22
|
+
capability: string;
|
|
23
|
+
documentedBehavior: string;
|
|
24
|
+
observedBehavior: string;
|
|
25
|
+
hostVersion?: string;
|
|
26
|
+
docUrl?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CapabilityCheckResult {
|
|
29
|
+
name: string;
|
|
30
|
+
verdict: CapabilityVerdict;
|
|
31
|
+
observedAt: string;
|
|
32
|
+
reason?: string;
|
|
33
|
+
evidenceRefs: SourceRef[];
|
|
34
|
+
}
|
|
35
|
+
export interface HostCapabilityReport {
|
|
36
|
+
reportId: string;
|
|
37
|
+
generatedAt: string;
|
|
38
|
+
hostVersion?: string;
|
|
39
|
+
observedVersion?: string;
|
|
40
|
+
docLinks: HostCapabilityDocReference[];
|
|
41
|
+
docCheckedAt: string;
|
|
42
|
+
pluginLoad: CapabilityCheckResult;
|
|
43
|
+
heartbeatBridge: CapabilityCheckResult;
|
|
44
|
+
heartbeatToolInvocation: CapabilityCheckResult;
|
|
45
|
+
deliveryTarget: DeliveryCapabilityStatus;
|
|
46
|
+
ackDropBehavior: CapabilityCheckResult;
|
|
47
|
+
hookSupport: CapabilityCheckResult[];
|
|
48
|
+
evidenceRefs: SourceRef[];
|
|
49
|
+
conflictRecords: HostCapabilityConflictRecord[];
|
|
50
|
+
recommendedNextStep?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface HostCapabilityProbeOptions {
|
|
53
|
+
adapter: HostCapabilityAdapter;
|
|
54
|
+
docLinks: HostCapabilityDocReference[];
|
|
55
|
+
docCheckedAt: string;
|
|
56
|
+
hostVersion?: string;
|
|
57
|
+
observedVersion?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface HostCapabilityAdapter {
|
|
60
|
+
checkPluginLoad(): CapabilityCheckResult;
|
|
61
|
+
checkHeartbeatBridge(): CapabilityCheckResult;
|
|
62
|
+
checkHeartbeatToolInvocation(): CapabilityCheckResult;
|
|
63
|
+
/** Return normalized delivery capability as observed on the host */
|
|
64
|
+
checkDeliveryTarget(): {
|
|
65
|
+
status: DeliveryCapabilityStatus;
|
|
66
|
+
evidenceRefs: SourceRef[];
|
|
67
|
+
reason?: string;
|
|
68
|
+
};
|
|
69
|
+
checkAckDropBehavior(): CapabilityCheckResult;
|
|
70
|
+
checkHookSupport(): CapabilityCheckResult[];
|
|
71
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reproducible host smoke runner (T1.3.1). Uses transcript fixtures — no live OpenClaw in unit/integration path.
|
|
3
|
+
*
|
|
4
|
+
* Core logic: evaluate `heartbeat_tool_invocation` by substring match for heartbeat_check / second_nature_ops heartbeat surface.
|
|
5
|
+
*/
|
|
6
|
+
import * as crypto from "node:crypto";
|
|
7
|
+
function evalHeartbeatToolInvocation(c) {
|
|
8
|
+
const hasHeartbeatCheck = c.toolInvocations.some((t) => /heartbeat_check|second_nature_ops\s*\(\s*\{[^}]*heartbeat_check|command\s*:\s*["']heartbeat_check["']/i.test(t));
|
|
9
|
+
if (hasHeartbeatCheck) {
|
|
10
|
+
return { caseType: c.type, status: "pass", reasons: [] };
|
|
11
|
+
}
|
|
12
|
+
return { caseType: c.type, status: "fail", reasons: ["heartbeat_tool_not_invoked"] };
|
|
13
|
+
}
|
|
14
|
+
function evalDocsConflict(c) {
|
|
15
|
+
if (c.observedBehavior.trim() === c.docExpectation.trim()) {
|
|
16
|
+
return { caseType: c.type, status: "pass", reasons: [] };
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
caseType: c.type,
|
|
20
|
+
status: "fail",
|
|
21
|
+
reasons: ["docs_vs_observed_conflict", `expected:${c.docExpectation}`, `observed:${c.observedBehavior}`],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function evalCase(c) {
|
|
25
|
+
if (c.type === "heartbeat_tool_invocation") {
|
|
26
|
+
return evalHeartbeatToolInvocation(c);
|
|
27
|
+
}
|
|
28
|
+
return evalDocsConflict(c);
|
|
29
|
+
}
|
|
30
|
+
export async function runHostSmoke(plan) {
|
|
31
|
+
const results = plan.cases.map((c) => evalCase(c));
|
|
32
|
+
return {
|
|
33
|
+
reportId: crypto.randomUUID(),
|
|
34
|
+
generatedAt: new Date().toISOString(),
|
|
35
|
+
results,
|
|
36
|
+
docLinks: plan.docLinks,
|
|
37
|
+
docCheckedAt: plan.docCheckedAt,
|
|
38
|
+
hostVersion: plan.hostVersion,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host smoke plan + report types (T1.3.1).
|
|
3
|
+
*
|
|
4
|
+
* `heartbeat_tool_invocation` verifies that a near-real transcript actually invoked heartbeat_check.
|
|
5
|
+
*/
|
|
6
|
+
export interface HeartbeatToolInvocationCase {
|
|
7
|
+
readonly type: "heartbeat_tool_invocation";
|
|
8
|
+
/** Tool names, ops strings, or host transcript fragments observed during the smoke turn */
|
|
9
|
+
toolInvocations: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface DocsVsObservedConflictCase {
|
|
12
|
+
readonly type: "docs_vs_observed_conflict";
|
|
13
|
+
docExpectation: string;
|
|
14
|
+
observedBehavior: string;
|
|
15
|
+
}
|
|
16
|
+
export type HostSmokeCase = HeartbeatToolInvocationCase | DocsVsObservedConflictCase;
|
|
17
|
+
export interface HostSmokePlan {
|
|
18
|
+
cases: HostSmokeCase[];
|
|
19
|
+
docLinks?: string[];
|
|
20
|
+
docCheckedAt?: string;
|
|
21
|
+
hostVersion?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface HostSmokeCaseResult {
|
|
24
|
+
caseType: HostSmokeCase["type"];
|
|
25
|
+
status: "pass" | "fail" | "unknown";
|
|
26
|
+
reasons: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface HostSmokeReport {
|
|
29
|
+
reportId: string;
|
|
30
|
+
generatedAt: string;
|
|
31
|
+
results: HostSmokeCaseResult[];
|
|
32
|
+
docLinks?: string[];
|
|
33
|
+
docCheckedAt?: string;
|
|
34
|
+
hostVersion?: string;
|
|
35
|
+
}
|
package/runtime/cli/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { createObservabilityDatabase } from "../observability/db/index.js";
|
|
2
2
|
import { createStateAPI, createStateDatabase } from "../storage/index.js";
|
|
3
|
+
import path from "node:path";
|
|
3
4
|
import { createActionBridge } from "./action-bridge.js";
|
|
4
5
|
import { createCliCommands } from "./commands/index.js";
|
|
6
|
+
import { createOpsRouter } from "./ops/ops-router.js";
|
|
5
7
|
import { createCliReadModels } from "./read-models/index.js";
|
|
8
|
+
import { resolvePackagedRuntime } from "./runtime/runtime-artifact-boundary.js";
|
|
6
9
|
export function createCliRuntimeDeps(overrides = {}) {
|
|
7
10
|
const stateDb = overrides.stateDb ?? createStateDatabase();
|
|
8
11
|
const observabilityDb = overrides.observabilityDb ?? createObservabilityDatabase();
|
|
@@ -19,9 +22,15 @@ export function createCliRuntimeDeps(overrides = {}) {
|
|
|
19
22
|
}
|
|
20
23
|
export function createCommandRouter(options = {}) {
|
|
21
24
|
const runtime = createCliRuntimeDeps(options.deps);
|
|
25
|
+
const pluginRoot = path.join(process.cwd(), "plugin");
|
|
26
|
+
const opsRouter = createOpsRouter({
|
|
27
|
+
runtimeAvailable: resolvePackagedRuntime(pluginRoot).ok,
|
|
28
|
+
readModels: runtime.readModels,
|
|
29
|
+
});
|
|
22
30
|
const commands = createCliCommands({
|
|
23
31
|
readModels: runtime.readModels,
|
|
24
32
|
actionBridge: runtime.actionBridge,
|
|
33
|
+
opsRouter,
|
|
25
34
|
});
|
|
26
35
|
return {
|
|
27
36
|
commands,
|
|
@@ -34,3 +43,12 @@ export function closeCliRuntimeDeps(deps) {
|
|
|
34
43
|
deps.stateDb.close();
|
|
35
44
|
deps.observabilityDb.close();
|
|
36
45
|
}
|
|
46
|
+
export { createOpsRouter } from "./ops/ops-router.js";
|
|
47
|
+
export { heartbeatCheck, } from "./ops/heartbeat-surface.js";
|
|
48
|
+
export * from "./host-capability/types.js";
|
|
49
|
+
export { classifyDeliveryCapability } from "./host-capability/classify-delivery.js";
|
|
50
|
+
export { probeHostCapability } from "./host-capability/probe-host-capability.js";
|
|
51
|
+
export { recordHostCapability } from "./host-capability/record-host-capability.js";
|
|
52
|
+
export { runHostSmoke } from "./host-smoke/run-host-smoke.js";
|
|
53
|
+
export { explainSurfaceSubject } from "./explain/explain-surface-subject.js";
|
|
54
|
+
export { showOperatorFallback, OperatorFallbackNotFoundError } from "./ops/show-operator-fallback.js";
|