@dmsdc-ai/aigentry-telepty 0.5.3 → 0.5.4

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 (2) hide show
  1. package/daemon.js +37 -4
  2. package/package.json +4 -4
package/daemon.js CHANGED
@@ -298,9 +298,20 @@ function fireAutoReport(targetId, targetSession, pendingReport, trigger, deps =
298
298
  const srcSession = _sessions[srcId];
299
299
  if (!srcSession) return;
300
300
 
301
+ // #537 / Bug B: a never-started worker (transient submit failure → claude startup
302
+ // busy→idle settle at ~4.5s) must NOT be reported TASK_COMPLETE. When a submit was
303
+ // expected, the elapsed floor and startup-polluted sawWorkingAfterInject are NOT trusted
304
+ // as proof of processing — require positive submit confirmation (screen-poll verify /
305
+ // honest force / gate-off). Paths with no submit expected keep the legacy floor/work rule.
306
+ const strongSubmitConfirmed = !!(
307
+ pendingReport.submitConfirmedAt ||
308
+ (pendingReport.submitConfirm && pendingReport.submitConfirm.accepted === true)
309
+ );
301
310
  const confirmed = trigger === 'ready-signal' && pendingReport.submitExpected
302
311
  ? false
303
- : (elapsedNum >= AUTO_REPORT_MIN_REAL_SECONDS || hasSubmitEvidence);
312
+ : pendingReport.submitExpected
313
+ ? strongSubmitConfirmed
314
+ : (elapsedNum >= AUTO_REPORT_MIN_REAL_SECONDS || hasSubmitEvidence);
304
315
  const injTag = pendingReport.injectId ? ` inject=${pendingReport.injectId}` : '';
305
316
  const reportMsg = confirmed
306
317
  ? `TASK_COMPLETE: ${targetId} is now idle after processing inject (${elapsed}s, via ${trigger}${injTag})`
@@ -1184,6 +1195,19 @@ function terminalLevelSubmit(id, session) {
1184
1195
  return null;
1185
1196
  }
1186
1197
 
1198
+ // #537 / Bug B: a forced submit is only HONESTLY confirmed when its strategy actually
1199
+ // reached the rendered surface. On a cmux-backed session the surface is cmux; a `pty_cr`
1200
+ // fallback means `cmux send-key` failed ("Failed to write to socket") and the live CLI
1201
+ // never received Enter. Terminal-level strategies (kitty/cmux) are real delivery; a pty_cr
1202
+ // fallback on a cmux surface is NOT. Pure + exported so the decision is unit-testable.
1203
+ function forceSubmitDeliveredToSurface(session, strategy) {
1204
+ if (!strategy) return false;
1205
+ if (session && session.backend === 'cmux' && session.cmuxWorkspaceId && strategy === 'pty_cr') {
1206
+ return false;
1207
+ }
1208
+ return true;
1209
+ }
1210
+
1187
1211
  async function deliverInjectionToSession(id, session, prompt, options = {}) {
1188
1212
  const now = Date.now();
1189
1213
  if (!options.bypassBootstrapQueue && shouldQueueBootstrapOperation(session)) {
@@ -2190,11 +2214,19 @@ app.post('/api/sessions/:id/submit', async (req, res) => {
2190
2214
  }
2191
2215
  const strategy = terminalLevelSubmit(id, session);
2192
2216
  if (strategy) {
2217
+ // #537 / Bug B: force-confirm must reflect ACTUAL delivery. A pty_cr fallback on a
2218
+ // cmux surface means cmux send-key failed and Enter never reached the CLI — record
2219
+ // UNCONFIRMED so the ENFORCE-REPORT gate never labels a never-delivered inject DONE.
2220
+ const deliveredToSurface = forceSubmitDeliveredToSurface(session, strategy);
2193
2221
  if (injectedBody) {
2194
- markPendingReportSubmitConfirmed(id, { reason: 'force', attempts: 1 });
2222
+ if (deliveredToSurface) {
2223
+ markPendingReportSubmitConfirmed(id, { reason: 'force', attempts: 1 });
2224
+ } else {
2225
+ markPendingReportSubmitUnconfirmed(id, { reason: 'cmux_send_failed', attempts: 1, retryable: true });
2226
+ }
2195
2227
  }
2196
- emitSubmitBus({ strategy, attempts: 1, gated: false, forced: true });
2197
- return res.json({ success: true, strategy, attempts: 1, gated: false, forced: true });
2228
+ emitSubmitBus({ strategy, attempts: 1, gated: false, forced: true, submit_confirmed: deliveredToSurface });
2229
+ return res.json({ success: true, strategy, attempts: 1, gated: false, forced: true, submit_confirmed: deliveredToSurface });
2198
2230
  }
2199
2231
  if (injectedBody) {
2200
2232
  markPendingReportSubmitUnconfirmed(id, { reason: 'strategy_failed', attempts: 0, retryable: false });
@@ -3488,6 +3520,7 @@ if (require.main === module) {
3488
3520
  // production call sites is unchanged. NOT a public API — internal/test use only.
3489
3521
  module.exports = {
3490
3522
  fireAutoReport, // #32: provenance-tagged auto-report (deps DI: now/deliver/...)
3523
+ forceSubmitDeliveredToSurface, // #537/Bug B: honest force-confirm (pty_cr on cmux = not delivered)
3491
3524
  failBootstrapQueueOnTimeout, // #31: actionable bootstrap-timeout queue flush
3492
3525
  shouldApplyOwnerAliveFloor, // #29: owner-alive optimistic-floor decision (deps DI: isProcessRunning/...)
3493
3526
  scheduleBootstrapPromptPoll, // #29: arms the floor timer (deps DI: setTimeout/...)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dmsdc-ai/aigentry-telepty",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "main": "daemon.js",
5
5
  "bin": {
6
6
  "aigentry-telepty": "install.js",
@@ -35,9 +35,9 @@
35
35
  ],
36
36
  "scripts": {
37
37
  "postinstall": "node scripts/postinstall.js",
38
- "test": "node --test test/auth.test.js test/http-auth.test.js test/daemon.test.js test/daemon-singleton.test.js test/integration/daemon-launch.test.js test/cli.test.js test/telepty-kill.test.js test/idle-ttl.test.js test/telepty-clean-older-than.test.js test/lifecycle-transport-agnostic.test.js test/skill-installer.test.js test/interactive-terminal.test.js test/runtime-info.test.js test/session-routing.test.js test/session-state.test.js test/session-store-persistence.test.js test/mailbox-lock.test.js test/report-enforcement.test.js test/enforce-report.test.js test/submit-gate.test.js test/prompt-symbol-registry.test.js test/inject-submit-flags.test.js test/inject-submit-force-env.test.js test/host-spec.test.js test/cross-host-inject.test.js test/cross-machine-ssh-routing.test.js test/init.test.js test/win-resolve-executable.test.js test/version-handshake.test.js test/win-kill-process.test.js test/daemon-control-port-owner.test.js test/banner-stderr-jq-safety.test.js test/bridge-supervisor-ipc.test.js test/bridge-j3-shim.test.js test/bridge-e2e.test.js test/release-0.4.5-bugfixes.test.js && git diff --exit-code tests/snippet-protocol/v1/",
39
- "test:watch": "node --test --watch test/auth.test.js test/http-auth.test.js test/daemon.test.js test/daemon-singleton.test.js test/integration/daemon-launch.test.js test/cli.test.js test/telepty-kill.test.js test/idle-ttl.test.js test/telepty-clean-older-than.test.js test/lifecycle-transport-agnostic.test.js test/skill-installer.test.js test/interactive-terminal.test.js test/runtime-info.test.js test/session-routing.test.js test/session-state.test.js test/session-store-persistence.test.js test/mailbox-lock.test.js test/report-enforcement.test.js test/enforce-report.test.js test/submit-gate.test.js test/prompt-symbol-registry.test.js test/inject-submit-flags.test.js test/inject-submit-force-env.test.js test/host-spec.test.js test/cross-host-inject.test.js test/cross-machine-ssh-routing.test.js test/init.test.js test/win-resolve-executable.test.js test/version-handshake.test.js test/win-kill-process.test.js test/daemon-control-port-owner.test.js test/banner-stderr-jq-safety.test.js test/bridge-supervisor-ipc.test.js test/bridge-j3-shim.test.js test/bridge-e2e.test.js test/release-0.4.5-bugfixes.test.js",
40
- "test:ci": "node --test --test-reporter=spec test/auth.test.js test/http-auth.test.js test/daemon.test.js test/daemon-singleton.test.js test/integration/daemon-launch.test.js test/cli.test.js test/telepty-kill.test.js test/idle-ttl.test.js test/telepty-clean-older-than.test.js test/lifecycle-transport-agnostic.test.js test/skill-installer.test.js test/interactive-terminal.test.js test/runtime-info.test.js test/session-routing.test.js test/session-state.test.js test/session-store-persistence.test.js test/mailbox-lock.test.js test/report-enforcement.test.js test/enforce-report.test.js test/submit-gate.test.js test/prompt-symbol-registry.test.js test/inject-submit-flags.test.js test/inject-submit-force-env.test.js test/host-spec.test.js test/cross-host-inject.test.js test/cross-machine-ssh-routing.test.js test/init.test.js test/win-resolve-executable.test.js test/version-handshake.test.js test/win-kill-process.test.js test/daemon-control-port-owner.test.js test/banner-stderr-jq-safety.test.js test/bridge-supervisor-ipc.test.js test/bridge-j3-shim.test.js test/bridge-e2e.test.js test/release-0.4.5-bugfixes.test.js && git diff --exit-code tests/snippet-protocol/v1/",
38
+ "test": "node --test test/auth.test.js test/http-auth.test.js test/daemon.test.js test/daemon-singleton.test.js test/integration/daemon-launch.test.js test/cli.test.js test/telepty-kill.test.js test/idle-ttl.test.js test/telepty-clean-older-than.test.js test/lifecycle-transport-agnostic.test.js test/skill-installer.test.js test/interactive-terminal.test.js test/runtime-info.test.js test/session-routing.test.js test/session-state.test.js test/session-store-persistence.test.js test/mailbox-lock.test.js test/report-enforcement.test.js test/enforce-report.test.js test/enforce-submit-gate.test.js test/submit-gate.test.js test/prompt-symbol-registry.test.js test/inject-submit-flags.test.js test/inject-submit-force-env.test.js test/host-spec.test.js test/cross-host-inject.test.js test/cross-machine-ssh-routing.test.js test/init.test.js test/win-resolve-executable.test.js test/version-handshake.test.js test/win-kill-process.test.js test/daemon-control-port-owner.test.js test/banner-stderr-jq-safety.test.js test/bridge-supervisor-ipc.test.js test/bridge-j3-shim.test.js test/bridge-e2e.test.js test/release-0.4.5-bugfixes.test.js && git diff --exit-code tests/snippet-protocol/v1/",
39
+ "test:watch": "node --test --watch test/auth.test.js test/http-auth.test.js test/daemon.test.js test/daemon-singleton.test.js test/integration/daemon-launch.test.js test/cli.test.js test/telepty-kill.test.js test/idle-ttl.test.js test/telepty-clean-older-than.test.js test/lifecycle-transport-agnostic.test.js test/skill-installer.test.js test/interactive-terminal.test.js test/runtime-info.test.js test/session-routing.test.js test/session-state.test.js test/session-store-persistence.test.js test/mailbox-lock.test.js test/report-enforcement.test.js test/enforce-report.test.js test/enforce-submit-gate.test.js test/submit-gate.test.js test/prompt-symbol-registry.test.js test/inject-submit-flags.test.js test/inject-submit-force-env.test.js test/host-spec.test.js test/cross-host-inject.test.js test/cross-machine-ssh-routing.test.js test/init.test.js test/win-resolve-executable.test.js test/version-handshake.test.js test/win-kill-process.test.js test/daemon-control-port-owner.test.js test/banner-stderr-jq-safety.test.js test/bridge-supervisor-ipc.test.js test/bridge-j3-shim.test.js test/bridge-e2e.test.js test/release-0.4.5-bugfixes.test.js",
40
+ "test:ci": "node --test --test-reporter=spec test/auth.test.js test/http-auth.test.js test/daemon.test.js test/daemon-singleton.test.js test/integration/daemon-launch.test.js test/cli.test.js test/telepty-kill.test.js test/idle-ttl.test.js test/telepty-clean-older-than.test.js test/lifecycle-transport-agnostic.test.js test/skill-installer.test.js test/interactive-terminal.test.js test/runtime-info.test.js test/session-routing.test.js test/session-state.test.js test/session-store-persistence.test.js test/mailbox-lock.test.js test/report-enforcement.test.js test/enforce-report.test.js test/enforce-submit-gate.test.js test/submit-gate.test.js test/prompt-symbol-registry.test.js test/inject-submit-flags.test.js test/inject-submit-force-env.test.js test/host-spec.test.js test/cross-host-inject.test.js test/cross-machine-ssh-routing.test.js test/init.test.js test/win-resolve-executable.test.js test/version-handshake.test.js test/win-kill-process.test.js test/daemon-control-port-owner.test.js test/banner-stderr-jq-safety.test.js test/bridge-supervisor-ipc.test.js test/bridge-j3-shim.test.js test/bridge-e2e.test.js test/release-0.4.5-bugfixes.test.js && git diff --exit-code tests/snippet-protocol/v1/",
41
41
  "typecheck": "tsc --noEmit",
42
42
  "regen-fixtures": "node scripts/regen-snippet-fixtures.js"
43
43
  },