@tea-agent/loop-agent 0.36.4-beta.0 → 0.37.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/AGENTS.md +2 -6
  2. package/CHANGELOG.md +72 -163
  3. package/README.md +1 -1
  4. package/bin/loop-agent.js +1 -37
  5. package/dist/application/task-lifecycle/advance.js +0 -1
  6. package/dist/application/task-lifecycle/observe.js +0 -15
  7. package/dist/application/task-lifecycle/plan-transitions.js +0 -15
  8. package/dist/cli/command-definitions.js +0 -7
  9. package/dist/cli/program.js +3 -8
  10. package/dist/commands/init-upgrade.js +19 -351
  11. package/dist/commands/init.js +67 -14
  12. package/dist/commands/run-dag-progress.js +0 -14
  13. package/dist/commands/task-advance.js +3 -33
  14. package/dist/executors/dag-pi-executor.js +30 -47
  15. package/dist/executors/pi-sdk-executor.js +0 -34
  16. package/dist/executors/shell-executor.js +95 -6
  17. package/dist/infrastructure/harness/atomic-write.js +1 -2
  18. package/dist/shared/operator/capabilities.js +13 -200
  19. package/dist/shared/package-metadata.js +0 -42
  20. package/dist/task/frontend-project-capability.js +12 -162
  21. package/dist/task/source-prepare/completeness.js +0 -17
  22. package/dist/task/source-prepare/parse-intent.js +1 -15
  23. package/dist/task/source-prepare/semantic-intake.js +23 -144
  24. package/dist/worker/console/chat/artifact-card.js +1 -8
  25. package/dist/worker/console/chat/chat-event-store.js +0 -61
  26. package/dist/worker/console/chat/human-gate-card.js +1 -9
  27. package/dist/worker/console/chat/operation-card.js +2 -71
  28. package/dist/worker/console/chat/pi-runtime.js +62 -86
  29. package/dist/worker/console/chat/routes.js +8 -36
  30. package/dist/worker/console/chat/session-store.js +0 -3
  31. package/dist/worker/console/chat/shortcuts.js +7 -9
  32. package/dist/worker/console/chat/turn-process.js +23 -97
  33. package/dist/worker/console/chat/workspace-landing.js +1 -2
  34. package/dist/worker/console/operation-runner.js +6 -155
  35. package/dist/worker/console/operator-actions.js +13 -373
  36. package/dist/worker/console/operator-user-error.js +0 -4
  37. package/dist/worker/console/recovery-cta.js +3 -50
  38. package/dist/worker/console/static/assets/index-HX1pbOyl.css +1 -0
  39. package/dist/worker/console/static/assets/index-M0BLEBfh.js +56 -0
  40. package/dist/worker/console/static/index.html +2 -2
  41. package/dist/worker/console/static-src/app/console-types.js +9 -13
  42. package/dist/worker/console/static-src/app/useOperatorActions.js +2 -4
  43. package/dist/worker/console/static-src/app/useRecoveryActions.js +56 -65
  44. package/dist/worker/console/static-src/app/useRecoveryConsole.js +1 -73
  45. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +30 -89
  46. package/dist/worker/console/static-src/operator-chat/refs.js +0 -3
  47. package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +1 -2
  48. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +11 -30
  49. package/dist/worker/console/static-src/operator-chat/useChatThread.js +6 -12
  50. package/dist/worker/console/static-src/operator-chat/useComposer.js +8 -45
  51. package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -7
  52. package/dist/worker/loop-agent/loop-agent-client.js +3 -17
  53. package/dist/worker/observability/read-model.js +0 -20
  54. package/dist/worker/observe/spec-evidence.js +8 -3
  55. package/dist/worker/observe/static/operator-chrome.d.ts +0 -1
  56. package/dist/worker/observe/static/operator-chrome.js +1 -6
  57. package/dist/worker/observe/static/views/dag-inspector.js +71 -6
  58. package/dist/worker/observe/static/views/dag.js +0 -12
  59. package/dist/worker/preflight.js +1 -2
  60. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +707 -37
  61. package/dist/workflows/dag/backend-test-case-manifest.js +4 -0
  62. package/dist/workflows/dag/backend-test-markdown-workflow.js +109 -7
  63. package/dist/workflows/dag/backend-test-module-stem.js +5 -0
  64. package/dist/workflows/dag/backend-test-pytest-collection.js +345 -24
  65. package/dist/workflows/dag/backend-test-scenario-param.js +890 -164
  66. package/dist/workflows/dag/backend-test-writer-completeness.js +47 -16
  67. package/dist/workflows/dag/dynamic-runtime/map.js +24 -8
  68. package/dist/workflows/dag/dynamic-runtime/shared.js +1 -9
  69. package/dist/workflows/dag/failure-routing.js +4 -9
  70. package/dist/workflows/dag/frontend-implementation-contract.js +39 -233
  71. package/dist/workflows/dag/frontend-prewrite-gate.js +62 -394
  72. package/dist/workflows/dag/frontend-repair.js +18 -219
  73. package/dist/workflows/dag/frontend-verification-trace.js +32 -47
  74. package/dist/workflows/dag/init-hybrid.js +86 -238
  75. package/dist/workflows/dag/lifecycle.js +0 -4
  76. package/dist/workflows/dag/node-execution.js +6 -105
  77. package/dist/workflows/dag/recovery-recommendation.js +0 -58
  78. package/dist/workflows/dag/report.js +0 -6
  79. package/dist/workflows/dag/retry-policy.js +0 -11
  80. package/dist/workflows/dag/runner.js +12 -314
  81. package/dist/workflows/dag/scheduler.js +3 -257
  82. package/dist/workflows/dag/types.js +9 -132
  83. package/dist/workflows/dag/validate.js +2 -7
  84. package/docs/README.md +3 -3
  85. package/docs/architecture/evolution.md +67 -102
  86. package/docs/templates/backend-test-dag.json +50 -32
  87. package/docs/templates/frontend-design-contract.md +14 -34
  88. package/docs/templates/frontend-task-constraints.md +13 -33
  89. package/docs/templates/frontend-task-requirement.md +20 -54
  90. package/docs/templates/init-managed-agents.md +2 -5
  91. package/harness.json +2 -2
  92. package/package.json +3 -4
  93. package/skills/loop-agent/SKILL.md +0 -1
  94. package/skills/loop-agent/references/command-reference.md +0 -3
  95. package/dist/build-stamp.json +0 -6
  96. package/dist/commands/dag-request-interrupt.js +0 -20
  97. package/dist/worker/console/chat/assistant-content.js +0 -121
  98. package/dist/worker/console/chat/semantic-activity.js +0 -471
  99. package/dist/worker/console/operation-run-facts.js +0 -190
  100. package/dist/worker/console/operation-wait.js +0 -355
  101. package/dist/worker/console/recovery-error-copy.js +0 -198
  102. package/dist/worker/console/static/assets/index-D83DYAFG.css +0 -1
  103. package/dist/worker/console/static/assets/index-IXm7oYjL.js +0 -59
  104. package/dist/worker/console/static-src/operator-chat/activity-journey.js +0 -125
  105. package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
  106. package/dist/worker/console/static-src/operator-chat/activity-references.js +0 -20
  107. package/dist/worker/console/static-src/operator-chat/slash-palette-layout.js +0 -24
  108. package/dist/worker/console/static-src/operator-chat/slash-palette-nav.js +0 -141
  109. package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
  110. package/dist/worker/observability/interrupt-eligibility.js +0 -264
  111. package/dist/workflows/dag/contract-output-registry.js +0 -14
  112. package/dist/workflows/dag/contract-validator-registrations.js +0 -8
  113. package/dist/workflows/dag/frontend-recovery-plan.js +0 -73
  114. package/dist/workflows/dag/frontend-recovery-root-manifest.js +0 -123
  115. package/dist/workflows/dag/frontend-recovery-run.js +0 -539
  116. package/dist/workflows/dag/frontend-writer-recovery.js +0 -106
  117. package/dist/workflows/dag/frontend-writer-rollback.js +0 -821
  118. package/dist/workflows/dag/interrupt-request.js +0 -559
@@ -1,6 +1,5 @@
1
1
  import { clipPreview, } from "./operation-store.js";
2
2
  import { stateEvent } from "./operation-sse.js";
3
- import { extractTrustedRunFacts } from "./operation-run-facts.js";
4
3
  /**
5
4
  * Execute a queued operation via LoopAgentClient (or inject).
6
5
  * Timeout without proven exit → needs-reconcile (never Cancel).
@@ -75,30 +74,6 @@ export async function runOperation(operationId, deps) {
75
74
  message: chunk,
76
75
  });
77
76
  },
78
- onHeartbeat: (info) => {
79
- // P1 (2026-08-13): project sibling CLI heartbeats into canonical
80
- // operation events so operationWait/operationEventSummary can consume
81
- // them. The projection is best-effort: a failed append must never
82
- // terminate the sibling CLI execution (AC-002). The injected test
83
- // runCommand path has no LoopAgentClient callback guard, so the
84
- // runner protects itself here.
85
- try {
86
- deps.events.append(operationId, {
87
- at: info.at,
88
- kind: "heartbeat",
89
- message: `heartbeat elapsedMs=${info.elapsedMs}`,
90
- data: {
91
- elapsedMs: info.elapsedMs,
92
- action: op.action,
93
- ...(op.taskId ? { taskId: op.taskId } : {}),
94
- ...(op.dagRunId ? { dagRunId: op.dagRunId } : {}),
95
- },
96
- });
97
- }
98
- catch {
99
- // Heartbeat is derived telemetry; ignore projection failures.
100
- }
101
- },
102
77
  });
103
78
  await spawnUpdate;
104
79
  finished = await finalizeFromWorkerResult(operationId, result, deps);
@@ -122,38 +97,6 @@ export async function runOperation(operationId, deps) {
122
97
  }
123
98
  return finished;
124
99
  }
125
- function taskAdvanceBusinessBlock(operation, envelope) {
126
- if (!operation || !envelope)
127
- return undefined;
128
- if (operation.action !== "taskAdvance" && operation.action !== "dagRunTask") {
129
- return undefined;
130
- }
131
- const result = envelope.result && typeof envelope.result === "object"
132
- ? envelope.result
133
- : undefined;
134
- const lifecycleState = typeof result?.lifecycleState === "string"
135
- ? result.lifecycleState
136
- : undefined;
137
- const blockers = Array.isArray(result?.blockers)
138
- ? result.blockers
139
- : [];
140
- const expectedGateStop = lifecycleState === "awaiting-write-set-approval" && blockers.length === 0;
141
- if (expectedGateStop)
142
- return undefined;
143
- if (lifecycleState !== "intake-incomplete" &&
144
- blockers.length === 0 &&
145
- envelope.outcome !== "blocked") {
146
- return undefined;
147
- }
148
- const firstBlocker = blockers[0];
149
- const code = typeof firstBlocker?.code === "string"
150
- ? firstBlocker.code
151
- : "TASK_ADVANCE_BLOCKED";
152
- const message = typeof firstBlocker?.message === "string"
153
- ? firstBlocker.message
154
- : `task advance stopped before runnable DAG completion (lifecycleState=${lifecycleState ?? "unknown"})`;
155
- return { code, message };
156
- }
157
100
  async function finalizeFromWorkerResult(operationId, result, deps) {
158
101
  const previewStdout = clipPreview(result.stdout ?? "");
159
102
  const previewStderr = clipPreview(result.stderr ?? "");
@@ -163,8 +106,6 @@ async function finalizeFromWorkerResult(operationId, result, deps) {
163
106
  resultPath: result.artifacts.resultPath,
164
107
  dir: result.artifacts.dir,
165
108
  };
166
- // Trusted structured run facts only (AC-003): never scanned from free text.
167
- const runFacts = extractTrustedRunFacts(result);
168
109
  if (result.timedOut) {
169
110
  // Supervisory timeout without classified CLI timeout → needs-reconcile
170
111
  // Only mark timed-out when we have a machine timeout result after exit.
@@ -180,35 +121,12 @@ async function finalizeFromWorkerResult(operationId, result, deps) {
180
121
  ? "CLI timed out with process exit"
181
122
  : "timeout reached without proven process exit; needs reconcile (not cancelled)",
182
123
  result: coerceEnvelope(result),
183
- ...(runFacts
184
- ? {
185
- dagRunId: runFacts.runId,
186
- ...(runFacts.runSummary ? { runSummary: runFacts.runSummary } : {}),
187
- }
188
- : {}),
189
124
  });
190
125
  stateEvent(deps.events, updated, state, updated.errorMessage);
191
- if (runFacts) {
192
- appendSafeResultEvent(deps, operationId, state, {
193
- ok: false,
194
- exitCode: result.exitCode,
195
- }, runFacts);
196
- }
197
- else {
198
- deps.events.append(operationId, {
199
- at: new Date().toISOString(),
200
- kind: "result",
201
- state,
202
- data: { ok: false, exitCode: result.exitCode },
203
- });
204
- }
205
126
  return updated;
206
127
  }
207
128
  const envelope = coerceEnvelope(result);
208
- const operation = await deps.store.get(operationId);
209
- const businessBlock = taskAdvanceBusinessBlock(operation, envelope);
210
- const processOk = envelope?.ok === true || (result.ok && result.exitCode === 0);
211
- const ok = processOk && !businessBlock;
129
+ const ok = envelope?.ok === true || (result.ok && result.exitCode === 0);
212
130
  const state = ok ? "succeeded" : "failed";
213
131
  const updated = await deps.store.update(operationId, {
214
132
  state,
@@ -220,43 +138,21 @@ async function finalizeFromWorkerResult(operationId, result, deps) {
220
138
  stdout: previewStdout,
221
139
  stderr: previewStderr,
222
140
  }),
223
- errorCode: ok
224
- ? undefined
225
- : (businessBlock?.code ?? envelope?.error?.code ?? "INTERNAL_ERROR"),
141
+ errorCode: ok ? undefined : (envelope?.error?.code ?? "INTERNAL_ERROR"),
226
142
  errorMessage: ok
227
143
  ? undefined
228
- : (businessBlock?.message ??
229
- envelope?.error?.message ??
144
+ : (envelope?.error?.message ??
230
145
  (previewStderr.trim() ||
231
146
  `command failed with exit ${result.exitCode}`)),
232
- // Atomic final patch: state/result + trusted dagRunId + safe runSummary
233
- // in a single per-op write-locked update (AC-004). The runSummary is a
234
- // projection and never launders the envelope/exit-decided state.
235
- ...(runFacts
236
- ? {
237
- dagRunId: runFacts.runId,
238
- ...(runFacts.runSummary ? { runSummary: runFacts.runSummary } : {}),
239
- }
240
- : {}),
241
147
  });
242
- stateEvent(deps.events, updated, state, updated.errorMessage);
243
- appendSafeResultEvent(deps, operationId, state, { ok, exitCode: result.exitCode }, runFacts);
244
- if (ok && operation?.action === "dagRequestInterrupt") {
245
- await projectInterruptRequestOntoTarget(operation, result.json, deps);
246
- }
247
- return updated;
248
- }
249
- /** Result event carries the same safe summary persisted on the record. */
250
- function appendSafeResultEvent(deps, operationId, state, base, runFacts) {
148
+ stateEvent(deps.events, updated, state);
251
149
  deps.events.append(operationId, {
252
150
  at: new Date().toISOString(),
253
151
  kind: "result",
254
152
  state,
255
- data: {
256
- ...base,
257
- ...(runFacts?.runSummary ? { runSummary: runFacts.runSummary } : {}),
258
- },
153
+ data: { ok, exitCode: result.exitCode },
259
154
  });
155
+ return updated;
260
156
  }
261
157
  function coerceEnvelope(result) {
262
158
  const json = result.json;
@@ -306,48 +202,3 @@ export function scheduleOperation(operationId, deps) {
306
202
  });
307
203
  });
308
204
  }
309
- async function projectInterruptRequestOntoTarget(operation, json, deps) {
310
- const params = operation.actionParams ?? {};
311
- const targetOperationId = typeof params.targetOperationId === "string"
312
- ? params.targetOperationId.trim()
313
- : "";
314
- const runId = typeof params.runId === "string" ? params.runId.trim() : "";
315
- if (!targetOperationId)
316
- return;
317
- const rec = json && typeof json === "object" ? json : {};
318
- const request = rec.request && typeof rec.request === "object"
319
- ? rec.request
320
- : rec;
321
- const status = (typeof rec.interruptStatus === "string" && rec.interruptStatus) ||
322
- (typeof request.status === "string" && request.status) ||
323
- "requested";
324
- if (status !== "requested" &&
325
- status !== "acknowledged" &&
326
- status !== "settled" &&
327
- status !== "needs-reconcile") {
328
- return;
329
- }
330
- const target = await deps.store.get(targetOperationId);
331
- if (!target)
332
- return;
333
- await deps.store.update(targetOperationId, {
334
- ...(runId && !target.dagRunId ? { dagRunId: runId } : {}),
335
- interrupt: {
336
- status,
337
- ...(typeof request.requestId === "string"
338
- ? { requestId: request.requestId }
339
- : {}),
340
- ...(typeof request.reasonCode === "string"
341
- ? { reasonCode: request.reasonCode }
342
- : {}),
343
- ...(typeof request.requestedAt === "string"
344
- ? { requestedAt: request.requestedAt }
345
- : {}),
346
- },
347
- });
348
- deps.events.append(targetOperationId, {
349
- kind: "state",
350
- message: `interrupt ${status}`,
351
- data: { interruptStatus: status, ...(runId ? { runId } : {}) },
352
- });
353
- }