@haaaiawd/second-nature 0.1.7 → 0.1.8

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 CHANGED
@@ -1,27 +1,322 @@
1
- // @ts-ignore packaged runtime declarations are generated under plugin/runtime
2
- import { createCliRuntimeDeps, createCommandRouter } from "./runtime/cli/index.js";
3
- import { DecisionLedger } from "./runtime/observability/services/decision-ledger.js";
4
- import { ExecutionTelemetry } from "./runtime/observability/services/execution-telemetry.js";
1
+ /**
2
+ * Host-safe Second Nature plugin surface.
3
+ *
4
+ * Core logic:
5
+ * - keep register(api) synchronous so OpenClaw captures services/command/tool before return
6
+ * - avoid importing CLI/runtime DB modules at module-evaluation time because the packaged
7
+ * runtime graph currently contains async sql.js bootstrap that breaks vm sandbox loading
8
+ * - expose a minimal in-memory activation spine so status/lifecycle stay truthful even when
9
+ * the full workspace runtime is not loaded inside the host
10
+ *
11
+ * Dependencies:
12
+ * - only imports runtime lifecycle/service modules that are synchronous at load time
13
+ *
14
+ * Boundaries:
15
+ * - read-only operator flows stay available through command/tool surface
16
+ * - structured mutating flows such as policy set / credential verify remain unavailable here
17
+ * - full evidence-backed workspace runtime can be reintroduced later behind a host-safe boundary
18
+ *
19
+ * Test coverage:
20
+ * - tests/integration/cli/plugin-runtime-registration.test.ts
21
+ * - tests/integration/cli/plugin-packaging-walkthrough.test.ts
22
+ */
5
23
  import { startRuntimeService, } from "./runtime/core/second-nature/runtime/service-entry.js";
6
24
  import { getLifecycleState, recordRegistration, } from "./runtime/core/second-nature/runtime/lifecycle-service.js";
7
- const INTERNAL_RUNTIME_PLATFORM_ID = "second-nature-runtime";
8
25
  const INTERNAL_RUNTIME_TRACE_PREFIX = "sn-runtime-";
9
- const INTERNAL_RUNTIME_CHANNEL = "plugin_host";
26
+ const HOST_SAFE_LIMITATION_MESSAGE = "Host-safe plugin package keeps synchronous register/load semantics, but mutating workspace runtime flows remain unavailable here.";
10
27
  let activationSpine = null;
11
- function createFallbackCommands() {
12
- const commandNames = ["status", "policy", "credential", "quiet", "report", "session", "audit", "explain"];
13
- return commandNames.map((name) => ({
14
- name,
15
- description: `Fallback command shell for ${name}`,
16
- execute: async (_input) => ({
28
+ function trimRuntimeEvidence(spine) {
29
+ if (spine.runtimeEvidence.length > 12) {
30
+ spine.runtimeEvidence.splice(0, spine.runtimeEvidence.length - 12);
31
+ }
32
+ }
33
+ function latestRuntimeEvidence(spine) {
34
+ return spine.runtimeEvidence[spine.runtimeEvidence.length - 1];
35
+ }
36
+ function createUnavailableActionError(code, message, requiredUserInput, nextStep) {
37
+ return {
38
+ ok: false,
39
+ error: {
40
+ code,
41
+ message,
42
+ requiredUserInput,
43
+ nextStep,
44
+ },
45
+ message: HOST_SAFE_LIMITATION_MESSAGE,
46
+ };
47
+ }
48
+ function parseExplainSubject(subjectRaw) {
49
+ const trimmed = subjectRaw.trim();
50
+ if (!trimmed) {
51
+ throw new Error("explain_subject_invalid");
52
+ }
53
+ const separatorIndex = trimmed.indexOf(":");
54
+ if (separatorIndex === -1) {
55
+ throw new Error("explain_subject_requires_id");
56
+ }
57
+ const kind = trimmed.slice(0, separatorIndex).trim();
58
+ const id = trimmed.slice(separatorIndex + 1).trim();
59
+ if (!id) {
60
+ throw new Error("explain_subject_requires_id");
61
+ }
62
+ switch (kind) {
63
+ case "decision":
64
+ return { subjectType: "decision", subjectId: id };
65
+ case "platform":
66
+ case "platform-selection":
67
+ return { subjectType: "platform-selection", subjectId: id };
68
+ case "outreach":
69
+ return { subjectType: "outreach", subjectId: id };
70
+ case "soul":
71
+ case "soul-change":
72
+ return { subjectType: "soul-change", subjectId: id };
73
+ default:
74
+ throw new Error("explain_subject_unsupported");
75
+ }
76
+ }
77
+ function buildStatusPayload(spine) {
78
+ const runtimeEvidence = latestRuntimeEvidence(spine);
79
+ const updatedAt = runtimeEvidence?.createdAt ?? new Date(spine.lifecycleState.lastChangedAt).toISOString();
80
+ return {
81
+ ok: true,
82
+ data: {
83
+ runtime: {
84
+ host: "openclaw-plugin",
85
+ serviceStatus: spine.runtimeHandle.ready ? "running" : "idle",
86
+ 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: [],
102
+ },
103
+ },
104
+ };
105
+ }
106
+ function buildQuietPayload(scope) {
107
+ return {
108
+ ok: true,
109
+ data: {
110
+ scope,
111
+ mode: "unknown",
112
+ sourceCount: 0,
113
+ reportCount: 0,
114
+ recentJournalCount: 0,
115
+ },
116
+ };
117
+ }
118
+ function buildReportPayload(day) {
119
+ return {
120
+ ok: true,
121
+ data: {
122
+ day: day && day.trim() ? day : new Date().toISOString().slice(0, 10),
123
+ summary: "",
124
+ highlights: [],
125
+ sourceRefs: [],
126
+ },
127
+ };
128
+ }
129
+ function buildSessionPayload(sessionId) {
130
+ if (!sessionId) {
131
+ return {
17
132
  ok: false,
18
- command: name,
19
- message: "Plugin loaded in packaging fallback mode; reinstall full workspace build for command runtime.",
20
- }),
21
- }));
133
+ error: {
134
+ code: "MISSING_SESSION_ID",
135
+ message: "session show requires sessionId",
136
+ requiredUserInput: ["session_id"],
137
+ nextStep: "reinvoke_session_with_session_id",
138
+ },
139
+ };
140
+ }
141
+ return {
142
+ ok: true,
143
+ data: {
144
+ requestedSessionId: sessionId,
145
+ traceId: sessionId,
146
+ decisionCount: 0,
147
+ attemptCount: 0,
148
+ governanceCount: 0,
149
+ keyFactors: [],
150
+ evidenceRefs: [],
151
+ },
152
+ };
22
153
  }
23
- function createFallbackRouter() {
24
- const commands = createFallbackCommands();
154
+ function buildCredentialPayload(platformId) {
155
+ return {
156
+ ok: true,
157
+ data: {
158
+ platformId: platformId && platformId.trim() ? platformId : "unknown",
159
+ status: "missing",
160
+ nextStep: "provide_credential_context",
161
+ },
162
+ };
163
+ }
164
+ function buildExplainPayload(spine, subjectRaw) {
165
+ if (!subjectRaw?.trim()) {
166
+ return {
167
+ ok: false,
168
+ error: {
169
+ code: "MISSING_EXPLAIN_SUBJECT",
170
+ message: "explain requires subject",
171
+ requiredUserInput: ["subject"],
172
+ nextStep: "reinvoke_explain_with_subject",
173
+ },
174
+ };
175
+ }
176
+ let subject;
177
+ try {
178
+ subject = parseExplainSubject(subjectRaw);
179
+ }
180
+ catch (error) {
181
+ const code = error.message;
182
+ if (code === "explain_subject_requires_id") {
183
+ return createUnavailableActionError("EXPLAIN_SUBJECT_REQUIRES_ID", "subject must include identifier", ["subject"], "reinvoke_explain_with_supported_subject");
184
+ }
185
+ if (code === "explain_subject_unsupported") {
186
+ return createUnavailableActionError("EXPLAIN_SUBJECT_UNSUPPORTED", "supported subjects are decision:<id>, platform:<id>, outreach:<id>, soul:<id>", ["subject"], "reinvoke_explain_with_supported_subject");
187
+ }
188
+ return createUnavailableActionError("EXPLAIN_SUBJECT_INVALID", "invalid explain subject", ["subject"], "reinvoke_explain_with_supported_subject");
189
+ }
190
+ const runtimeEvidence = latestRuntimeEvidence(spine);
191
+ return {
192
+ ok: true,
193
+ data: {
194
+ subjectType: subject.subjectType,
195
+ conclusion: "Plugin surface is loaded in host-safe mode with a minimal activation spine.",
196
+ keyFactors: [
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",
207
+ },
208
+ };
209
+ }
210
+ function buildHeartbeatCheckPayload(spine, input) {
211
+ const runtimeEvidence = latestRuntimeEvidence(spine);
212
+ const updatedAt = runtimeEvidence?.createdAt ?? new Date(spine.lifecycleState.lastChangedAt).toISOString();
213
+ const timestamp = typeof input?.timestamp === "string" && input.timestamp.trim().length > 0 ? input.timestamp : updatedAt;
214
+ return {
215
+ ok: true,
216
+ status: "heartbeat_ok",
217
+ heartbeat: "HEARTBEAT_OK",
218
+ scope: "rhythm",
219
+ trigger: "heartbeat_bridge",
220
+ reasons: ["host_safe_bridge_ready"],
221
+ nextAction: "continue",
222
+ message: "Host-safe heartbeat bridge acknowledged the round. No additional action is required from this surface.",
223
+ data: {
224
+ runtime: {
225
+ host: "openclaw-plugin",
226
+ serviceStatus: spine.runtimeHandle.ready ? "running" : "idle",
227
+ updatedAt,
228
+ },
229
+ surface: {
230
+ tool: "second_nature_ops",
231
+ command: "second-nature heartbeat_check",
232
+ },
233
+ bridge: {
234
+ timestamp,
235
+ sessionContextProvided: typeof input?.sessionContext === "string" && input.sessionContext.trim().length > 0,
236
+ heartbeatChecklistProvided: typeof input?.heartbeatChecklist === "string" && input.heartbeatChecklist.trim().length > 0,
237
+ serviceEntryMode: "runtime_carrier_only",
238
+ },
239
+ },
240
+ };
241
+ }
242
+ function createHostSafeRouter(spine) {
243
+ const notImplemented = async (command) => ({
244
+ ok: false,
245
+ command,
246
+ message: HOST_SAFE_LIMITATION_MESSAGE,
247
+ });
248
+ const commands = [
249
+ {
250
+ name: "status",
251
+ description: "Show aggregated Second Nature status",
252
+ execute: async () => buildStatusPayload(spine),
253
+ },
254
+ {
255
+ name: "policy",
256
+ description: "Write or inspect policy state",
257
+ execute: async (input) => {
258
+ const action = typeof input?.action === "string" ? input.action : "show";
259
+ if (action === "set") {
260
+ return createUnavailableActionError("HOST_SAFE_POLICY_SET_UNAVAILABLE", "policy set is unavailable in the host-safe plugin package", ["social_daily_limit", "quiet_enabled"], "run_workspace_runtime_or_reinstall_full_build");
261
+ }
262
+ return notImplemented("policy");
263
+ },
264
+ },
265
+ {
266
+ name: "credential",
267
+ description: "Inspect or recover credential state",
268
+ execute: async (input) => {
269
+ const action = typeof input?.action === "string" ? input.action : "show";
270
+ if (action === "verify") {
271
+ 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
+ }
273
+ const platformId = typeof input?.platformId === "string" ? input.platformId : undefined;
274
+ return buildCredentialPayload(platformId);
275
+ },
276
+ },
277
+ {
278
+ name: "quiet",
279
+ description: "Inspect Quiet lifecycle state",
280
+ execute: async (input) => {
281
+ const scope = typeof input?.scope === "string" ? input.scope : undefined;
282
+ return buildQuietPayload(scope);
283
+ },
284
+ },
285
+ {
286
+ name: "report",
287
+ description: "Show daily report artifacts",
288
+ execute: async (input) => {
289
+ const day = typeof input?.day === "string" ? input.day : undefined;
290
+ return buildReportPayload(day);
291
+ },
292
+ },
293
+ {
294
+ name: "session",
295
+ description: "Inspect continuity session details",
296
+ execute: async (input) => {
297
+ const sessionId = typeof input?.sessionId === "string" ? input.sessionId : undefined;
298
+ return buildSessionPayload(sessionId);
299
+ },
300
+ },
301
+ {
302
+ name: "audit",
303
+ description: "Inspect audit and evidence views",
304
+ execute: async () => notImplemented("audit"),
305
+ },
306
+ {
307
+ name: "explain",
308
+ description: "Answer why-question explain requests",
309
+ execute: async (input) => {
310
+ const subject = typeof input?.subject === "string" ? input.subject : undefined;
311
+ return buildExplainPayload(spine, subject);
312
+ },
313
+ },
314
+ {
315
+ name: "heartbeat_check",
316
+ description: "Acknowledge the shipping heartbeat bridge round",
317
+ execute: async (input) => buildHeartbeatCheckPayload(spine, input),
318
+ },
319
+ ];
25
320
  return {
26
321
  commands,
27
322
  resolve(name) {
@@ -29,33 +324,43 @@ function createFallbackRouter() {
29
324
  },
30
325
  };
31
326
  }
327
+ function createActivationSpine() {
328
+ const spine = {
329
+ router: undefined,
330
+ runtimeHandle: startRuntimeService({ workspaceRoot: process.cwd() }),
331
+ lifecycleState: getLifecycleState(),
332
+ serviceStartRecorded: false,
333
+ runtimeEvidence: [],
334
+ };
335
+ spine.router = createHostSafeRouter(spine);
336
+ return spine;
337
+ }
32
338
  function ensureActivationSpine() {
33
339
  if (activationSpine) {
34
340
  return activationSpine;
35
341
  }
36
- try {
37
- const runtimeDeps = createCliRuntimeDeps();
38
- const router = createCommandRouter({ deps: runtimeDeps });
39
- activationSpine = {
40
- runtimeDeps,
41
- router,
42
- decisionLedger: new DecisionLedger(runtimeDeps.observabilityDb),
43
- executionTelemetry: new ExecutionTelemetry(runtimeDeps.observabilityDb),
44
- runtimeHandle: startRuntimeService({ workspaceRoot: process.cwd() }),
45
- lifecycleState: getLifecycleState(),
46
- serviceStartRecorded: false,
47
- };
48
- return activationSpine;
342
+ activationSpine = createActivationSpine();
343
+ return activationSpine;
344
+ }
345
+ function recordRuntimeEvidence(spine, origin) {
346
+ if (origin === "service_start" && spine.serviceStartRecorded) {
347
+ return;
49
348
  }
50
- catch {
51
- activationSpine = {
52
- router: createFallbackRouter(),
53
- runtimeHandle: { ready: true, version: "0.1.7-minimal", close() { } },
54
- lifecycleState: getLifecycleState(),
55
- serviceStartRecorded: false,
56
- };
57
- return activationSpine;
349
+ if (origin === "service_start") {
350
+ spine.serviceStartRecorded = true;
58
351
  }
352
+ spine.runtimeEvidence.push({
353
+ traceId: `${INTERNAL_RUNTIME_TRACE_PREFIX}${origin}-${spine.lifecycleState.registerCount}-${Date.now()}`,
354
+ capability: origin === "register"
355
+ ? spine.lifecycleState.registerCount === 1
356
+ ? "runtime.activate"
357
+ : "runtime.reload"
358
+ : "runtime.heartbeat",
359
+ origin,
360
+ createdAt: new Date().toISOString(),
361
+ status: "succeeded",
362
+ });
363
+ trimRuntimeEvidence(spine);
59
364
  }
60
365
  function refreshRegistrationState() {
61
366
  const spine = ensureActivationSpine();
@@ -65,62 +370,6 @@ function refreshRegistrationState() {
65
370
  recordRuntimeEvidence(spine, "register");
66
371
  return spine;
67
372
  }
68
- function recordRuntimeEvidence(spine, origin) {
69
- const decisionLedger = spine.decisionLedger;
70
- const executionTelemetry = spine.executionTelemetry;
71
- if (!decisionLedger || !executionTelemetry) {
72
- return;
73
- }
74
- if (origin === "service_start" && spine.serviceStartRecorded) {
75
- return;
76
- }
77
- if (origin === "service_start") {
78
- spine.serviceStartRecorded = true;
79
- }
80
- const now = new Date().toISOString();
81
- const traceId = `${INTERNAL_RUNTIME_TRACE_PREFIX}${origin}-${spine.lifecycleState.registerCount}-${Date.now()}`;
82
- const decisionId = `decision-${traceId}`;
83
- const tickId = `tick-${traceId}`;
84
- const intentId = `intent-${traceId}`;
85
- const capability = origin === "register"
86
- ? spine.lifecycleState.registerCount === 1
87
- ? "runtime.activate"
88
- : "runtime.reload"
89
- : "runtime.heartbeat";
90
- void (async () => {
91
- await decisionLedger.recordHeartbeatDecision({
92
- id: decisionId,
93
- tickId,
94
- traceId,
95
- intentId,
96
- runtimeScope: "rhythm",
97
- triggerSource: "heartbeat_bridge",
98
- decisionStatus: "heartbeat_ok",
99
- reasons: [
100
- `origin:${origin}`,
101
- `phase:${spine.lifecycleState.phase}`,
102
- `registrations:${spine.lifecycleState.registerCount}`,
103
- ],
104
- mode: "active",
105
- createdAt: now,
106
- });
107
- await executionTelemetry.startAttempt({
108
- traceId,
109
- decisionId,
110
- intentId,
111
- platformId: INTERNAL_RUNTIME_PLATFORM_ID,
112
- capability,
113
- channel: INTERNAL_RUNTIME_CHANNEL,
114
- status: "started",
115
- startedAt: now,
116
- });
117
- await executionTelemetry.completeAttempt(traceId, "succeeded", "committed");
118
- })().catch(() => {
119
- if (origin === "service_start") {
120
- spine.serviceStartRecorded = false;
121
- }
122
- });
123
- }
124
373
  function parseCommandInput(rawArgs) {
125
374
  const tokens = rawArgs?.trim().split(/\s+/).filter(Boolean) ?? [];
126
375
  if (tokens.length === 0) {
@@ -176,6 +425,17 @@ function parseCommandInput(rawArgs) {
176
425
  command,
177
426
  input: rest[0] ? { platformId: rest[0] } : undefined,
178
427
  };
428
+ case "heartbeat_check":
429
+ return {
430
+ ok: true,
431
+ command,
432
+ input: rest.length > 0
433
+ ? {
434
+ timestamp: rest[0],
435
+ sessionContext: rest.length > 1 ? rest.slice(1).join(" ") : undefined,
436
+ }
437
+ : undefined,
438
+ };
179
439
  case "explain":
180
440
  return {
181
441
  ok: true,
@@ -221,7 +481,6 @@ export default {
221
481
  name: "Second Nature",
222
482
  description: "Registers command/tool/service surface with load-reload lifecycle semantics.",
223
483
  register(api) {
224
- const spine = refreshRegistrationState();
225
484
  const runtimeService = createRuntimeService();
226
485
  const lifecycleService = createLifecycleService();
227
486
  api.registerService(runtimeService);
@@ -231,6 +490,7 @@ export default {
231
490
  description: "Route Agent-facing operational commands for Second Nature.",
232
491
  acceptsArgs: true,
233
492
  handler: async (ctx) => {
493
+ const spine = ensureActivationSpine();
234
494
  const parsed = parseCommandInput(ctx.args);
235
495
  if (!parsed.ok) {
236
496
  return {
@@ -262,6 +522,7 @@ export default {
262
522
  required: ["command"],
263
523
  },
264
524
  async execute(_id, params) {
525
+ const spine = ensureActivationSpine();
265
526
  const resolved = spine.router.resolve(params.command);
266
527
  if (!resolved) {
267
528
  return {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "second-nature",
3
3
  "name": "Second Nature",
4
- "version": "0.1.7",
4
+ "version": "0.1.8",
5
5
  "entry": "./index.js",
6
6
  "description": "OpenClaw native plugin package with synchronous surface registration and a bundled runtime spine.",
7
7
  "capabilities": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haaaiawd/second-nature",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
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",
@@ -108,40 +108,23 @@ export function createConnectorPolicyLayer(ctx) {
108
108
  }
109
109
  let lastFailure;
110
110
  for (let attempt = 1; attempt <= retryPolicy.maxRetries; attempt += 1) {
111
- const traceId = makeTraceId(request, plan);
112
- const attemptId = `attempt-${traceId}-${attempt}`;
111
+ const traceId = `${makeTraceId(request, plan)}:${attempt}`;
113
112
  if (ctx.telemetry) {
114
- await ctx.telemetry.recordExecutionAttempt({
115
- id: attemptId,
113
+ await ctx.telemetry.startAttempt({
116
114
  traceId,
117
115
  decisionId: identity.decisionId,
118
116
  intentId: identity.intentId,
119
117
  platformId: request.platformId,
120
118
  capability: request.intent,
121
119
  channel: plan.channel,
122
- status: "started",
123
120
  retryPolicy: JSON.stringify(retryPolicy),
124
121
  idempotencyKey: request.idempotencyKey,
125
- startedAt: new Date().toISOString(),
126
122
  });
127
123
  }
128
124
  const raw = await ctx.executionRunner.run(plan, request);
129
125
  if (raw.success) {
130
126
  if (ctx.telemetry) {
131
- await ctx.telemetry.recordExecutionAttempt({
132
- id: `${attemptId}-done`,
133
- traceId,
134
- decisionId: identity.decisionId,
135
- intentId: identity.intentId,
136
- platformId: request.platformId,
137
- capability: request.intent,
138
- channel: plan.channel,
139
- status: "succeeded",
140
- retryPolicy: JSON.stringify(retryPolicy),
141
- idempotencyKey: request.idempotencyKey,
142
- startedAt: new Date().toISOString(),
143
- finishedAt: new Date().toISOString(),
144
- });
127
+ await ctx.telemetry.completeAttempt(traceId, "succeeded");
145
128
  }
146
129
  return {
147
130
  status: "success",
@@ -161,21 +144,7 @@ export function createConnectorPolicyLayer(ctx) {
161
144
  channel: raw.channel,
162
145
  };
163
146
  if (ctx.telemetry) {
164
- await ctx.telemetry.recordExecutionAttempt({
165
- id: `${attemptId}-failed`,
166
- traceId,
167
- decisionId: identity.decisionId,
168
- intentId: identity.intentId,
169
- platformId: request.platformId,
170
- capability: request.intent,
171
- channel: plan.channel,
172
- status: "failed",
173
- failureClass: classified.class,
174
- retryPolicy: JSON.stringify(retryPolicy),
175
- idempotencyKey: request.idempotencyKey,
176
- startedAt: new Date().toISOString(),
177
- finishedAt: new Date().toISOString(),
178
- });
147
+ await ctx.telemetry.completeAttempt(traceId, "failed", undefined, classified.class);
179
148
  }
180
149
  if (ctx.cooldownPort) {
181
150
  await ctx.cooldownPort.markFailure(request.platformId, intent, classified.class, classified.retryAfterMs);
@@ -7,7 +7,6 @@ export interface ExecutionAttemptInput {
7
7
  platformId: string;
8
8
  capability: string;
9
9
  channel: string;
10
- status: ExecutionAttempt["status"];
11
10
  commitState?: IntentCommitState;
12
11
  failureClass?: string;
13
12
  retryPolicy?: string;