@zq-silk/yui 0.6.16 → 0.7.1

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 (70) hide show
  1. package/dist/cli/commandCatalog.js +3 -7
  2. package/dist/cli.js +12 -33
  3. package/dist/commands/executionAuditCommands.js +19 -0
  4. package/dist/commands/globalRoleCommands.js +70 -0
  5. package/dist/commands/taskActor.js +3 -2
  6. package/dist/commands/taskCommands.js +160 -41
  7. package/dist/commands/taskContextCommand.js +1 -1
  8. package/dist/commands/taskInputCommands.js +3 -2
  9. package/dist/commands/taskRoleRuntimeStatus.js +3 -3
  10. package/dist/context/contextSnapshot.js +228 -0
  11. package/dist/context/roleSessionContext.js +3 -1
  12. package/dist/context/runContextContract.js +162 -0
  13. package/dist/context/runContextPack.js +322 -0
  14. package/dist/context/sessionBootstrapManifest.js +81 -0
  15. package/dist/context/sessionProtocolIdentity.js +23 -0
  16. package/dist/controller/agentRuntimeObserver.js +6 -1
  17. package/dist/controller/controller.js +4 -3
  18. package/dist/controller/fileSchedulerStoreAdapter.js +446 -145
  19. package/dist/controller/jobControl.js +2 -1
  20. package/dist/controller/runtime.js +83 -0
  21. package/dist/controller/runtimeHookRunFence.js +6 -2
  22. package/dist/controller/sessionOwnerReconciliation.js +5 -0
  23. package/dist/coordination/workMailbox.js +25 -22
  24. package/dist/executor/agentAdapter.js +7 -2
  25. package/dist/executor/agentExecutor.js +23 -0
  26. package/dist/executor/effectiveLaunch.js +24 -0
  27. package/dist/executor/executorRegistry.js +7 -1
  28. package/dist/executor/fileRoleLaunchPlanner.js +73 -27
  29. package/dist/lifecycle/exactRunTerminalization.js +2 -3
  30. package/dist/lifecycle/providerErrorClass.js +8 -3
  31. package/dist/observability/executionAudit.js +87 -2
  32. package/dist/repository/taskWorkspacePreparer.js +2 -2
  33. package/dist/run/agentRun.js +101 -16
  34. package/dist/run/providerRetry.js +167 -56
  35. package/dist/run/providerRetryConfig.js +5 -1
  36. package/dist/run/runControlRequest.js +50 -0
  37. package/dist/runtime/agentDriver.js +47 -0
  38. package/dist/runtime/agentHost.js +327 -0
  39. package/dist/runtime/builtinAgentDrivers.js +23 -1
  40. package/dist/runtime/builtinTranscriptObserver.js +4 -0
  41. package/dist/runtime/builtinTranscriptUsage.js +2 -0
  42. package/dist/runtime/exactControlPlane.js +2 -2
  43. package/dist/runtime/globalProcessExitStore.js +38 -0
  44. package/dist/runtime/launchBroker.js +95 -0
  45. package/dist/runtime/processExitObservation.js +60 -0
  46. package/dist/runtime/runtimeBinding.js +6 -0
  47. package/dist/runtime/runtimeObservation.js +27 -6
  48. package/dist/runtime/runtimeProjection.js +6 -3
  49. package/dist/runtime/runtimeStopReceipt.js +42 -0
  50. package/dist/runtime/sessionTerminationGuard.js +13 -0
  51. package/dist/runtime/tmuxAdapters.js +203 -220
  52. package/dist/scheduler/activeRoleRunDelivery.js +24 -3
  53. package/dist/scheduler/leaderWakeupProcessor.js +18 -60
  54. package/dist/scheduler/roleRunLiveness.js +61 -27
  55. package/dist/storage/migration/productionRegistry.js +264 -0
  56. package/dist/storage/sqliteSchema.js +23 -2
  57. package/dist/storage/sqliteStore.js +48 -4
  58. package/dist/storage/taskStore.js +54 -5
  59. package/dist/storage/upgrade/recordVersions.js +3 -1
  60. package/dist/storage/upgrade/sqliteStateMigration.js +10 -0
  61. package/dist/task/taskRecordReference.js +1 -0
  62. package/dist/tmux/tmuxManager.js +15 -4
  63. package/dist/web/assets/client/components.js +1 -1
  64. package/package.json +1 -1
  65. package/skills/yui-leader/SKILL.md +10 -5
  66. package/skills/yui-operator/SKILL.md +4 -0
  67. package/skills/yui-reviewer/SKILL.md +4 -0
  68. package/skills/yui-runtime/SKILL.md +61 -0
  69. package/skills/yui-worker/SKILL.md +82 -218
  70. package/dist/executor/managedClaudeRunner.js +0 -121
@@ -0,0 +1,60 @@
1
+ export const RUNTIME_PROCESS_EXIT_SCHEMA_VERSION = 1;
2
+ export function validateRuntimeProcessExitObservation(observation) {
3
+ if (observation.schemaVersion !== RUNTIME_PROCESS_EXIT_SCHEMA_VERSION) {
4
+ throw new Error("Runtime process-exit observation version is invalid.");
5
+ }
6
+ identity(observation.observationId, "observationId");
7
+ identity(observation.hostInstanceId, "hostInstanceId");
8
+ optionalIdentity(observation.providerProcessInstanceId, "providerProcessInstanceId");
9
+ optionalIdentity(observation.taskId, "taskId");
10
+ identity(observation.roleName, "roleName");
11
+ optionalIdentity(observation.runId, "runId");
12
+ identity(observation.launchId, "launchId");
13
+ optionalIdentity(observation.nativeSessionId, "nativeSessionId");
14
+ if (observation.processKind !== "agent-host" && observation.processKind !== "provider-child") {
15
+ throw new Error("Runtime process kind is invalid.");
16
+ }
17
+ if (!Number.isSafeInteger(observation.hostSequence) || observation.hostSequence < 1) {
18
+ throw new Error("Runtime host sequence is invalid.");
19
+ }
20
+ if (observation.exitCode !== undefined
21
+ && (!Number.isSafeInteger(observation.exitCode) || observation.exitCode < 0)) {
22
+ throw new Error("Runtime process exit code is invalid.");
23
+ }
24
+ optionalIdentity(observation.signal, "signal");
25
+ if (!Number.isFinite(Date.parse(observation.observedAt))) {
26
+ throw new Error("Runtime process observedAt is invalid.");
27
+ }
28
+ optionalIdentity(observation.stopReceiptId, "stopReceiptId");
29
+ optionalIdentity(observation.lastProviderEventId, "lastProviderEventId");
30
+ optionalIdentity(observation.diagnosticTailRef, "diagnosticTailRef");
31
+ return Object.freeze({ ...observation });
32
+ }
33
+ export function classifyRuntimeProcessExit(observation, input) {
34
+ validateRuntimeProcessExitObservation(observation);
35
+ if (observation.stopReceiptId !== undefined)
36
+ return "yui-requested-stop";
37
+ if (observation.processKind === "provider-child" && input.turnFailureObserved === true) {
38
+ return "provider-turn-failed";
39
+ }
40
+ if (observation.processKind === "provider-child"
41
+ && input.childLifecycle === "per-turn"
42
+ && observation.exitCode === 0
43
+ && input.turnTerminalObserved === true) {
44
+ return "expected-per-turn-exit";
45
+ }
46
+ if ((observation.exitCode !== undefined && observation.exitCode !== 0)
47
+ || observation.signal !== undefined) {
48
+ return "host-abnormal";
49
+ }
50
+ return "unknown";
51
+ }
52
+ function identity(value, label) {
53
+ if (typeof value !== "string" || value.trim().length === 0 || value.includes("\0")) {
54
+ throw new Error(`Runtime process ${label} is invalid.`);
55
+ }
56
+ }
57
+ function optionalIdentity(value, label) {
58
+ if (value !== undefined)
59
+ identity(value, label);
60
+ }
@@ -10,6 +10,9 @@ export function createRuntimeBinding(input) {
10
10
  if (initialPromptRunId !== undefined && hostCreated !== true) {
11
11
  throw new TypeError("An initial prompt Run id requires a newly-created runtime host.");
12
12
  }
13
+ const launchPromptUncertainRunId = input.launchPromptUncertainRunId === undefined
14
+ ? undefined
15
+ : requireSafeIdentity(input.launchPromptUncertainRunId, "Uncertain launch prompt Run id");
13
16
  return {
14
17
  id: requireSafeIdentity(input.id, "Runtime binding id"),
15
18
  launchId: requireSafeIdentity(input.launchId, "Launch id"),
@@ -19,6 +22,9 @@ export function createRuntimeBinding(input) {
19
22
  hostRef: requireText(input.hostRef, "Session host reference"),
20
23
  ...(hostCreated === undefined ? {} : { hostCreated }),
21
24
  ...(initialPromptRunId === undefined ? {} : { initialPromptRunId }),
25
+ ...(launchPromptUncertainRunId === undefined
26
+ ? {}
27
+ : { launchPromptUncertainRunId }),
22
28
  ...(input.nativeSessionId === undefined
23
29
  ? {}
24
30
  : { nativeSessionId: requireText(input.nativeSessionId, "Native session id") })
@@ -274,8 +274,12 @@ function normalizePayload(kind, input) {
274
274
  if (!["model", "tool", "subagent", "provider", "resource"].includes(input.activity ?? "")) {
275
275
  throw new Error("activity.observed requires an activity kind.");
276
276
  }
277
- if (input.usage !== undefined)
278
- validateUsage(input.usage);
277
+ if (input.usage !== undefined) {
278
+ const usage = input.usage;
279
+ validateUsage(usage.semantics === undefined
280
+ ? { ...usage, semantics: "cumulative-session" }
281
+ : usage);
282
+ }
279
283
  }
280
284
  if (kind === "observer.health") {
281
285
  requireIdentity(input.sourceId, "Runtime observer source id");
@@ -339,7 +343,12 @@ function normalizePayload(kind, input) {
339
343
  ...(input.activityId === undefined
340
344
  ? {}
341
345
  : { activityId: requireIdentity(input.activityId, "Runtime activity id") }),
342
- ...(input.usage === undefined ? {} : { usage: Object.freeze({ ...input.usage }) }),
346
+ ...(input.usage === undefined
347
+ ? {}
348
+ : { usage: Object.freeze({
349
+ ...input.usage,
350
+ semantics: input.usage.semantics ?? "cumulative-session"
351
+ }) }),
343
352
  ...(observerSource === undefined ? {} : { observerSource }),
344
353
  ...(input.sourceId === undefined
345
354
  ? {}
@@ -468,7 +477,10 @@ function normalizeFailure(input) {
468
477
  : { lastOutput: requireText(input.lastOutput, "Runtime failure last output") }),
469
478
  ...(input.runTerminal === undefined
470
479
  ? {}
471
- : { runTerminal: requireBoolean(input.runTerminal, "Runtime failure runTerminal") })
480
+ : { runTerminal: requireBoolean(input.runTerminal, "Runtime failure runTerminal") }),
481
+ ...(input.retryAfterMs === undefined
482
+ ? {}
483
+ : { retryAfterMs: requirePositiveMilliseconds(input.retryAfterMs) })
472
484
  });
473
485
  }
474
486
  function requireBoolean(value, label) {
@@ -476,9 +488,18 @@ function requireBoolean(value, label) {
476
488
  throw new Error(`${label} must be boolean.`);
477
489
  return value;
478
490
  }
491
+ function requirePositiveMilliseconds(value) {
492
+ if (!Number.isSafeInteger(value) || value <= 0) {
493
+ throw new Error("Runtime failure retryAfterMs must be a positive safe integer.");
494
+ }
495
+ return value;
496
+ }
479
497
  function validateUsage(input) {
480
- for (const [name, value] of Object.entries(input)) {
481
- if (!Number.isSafeInteger(value) || value < 0) {
498
+ if (!["cumulative-session", "request-context", "remaining-context"].includes(input.semantics)) {
499
+ throw new Error("Runtime usage semantics are invalid.");
500
+ }
501
+ for (const [name, value] of Object.entries(input).filter(([name]) => name !== "semantics")) {
502
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
482
503
  throw new Error(`Runtime usage ${name} must be a non-negative safe integer.`);
483
504
  }
484
505
  }
@@ -489,10 +489,13 @@ function next(current, patch) {
489
489
  });
490
490
  }
491
491
  function usageAdvanced(previous, current) {
492
+ if (current.semantics === "remaining-context")
493
+ return false;
494
+ if (current.semantics === "request-context")
495
+ return usageTotal(current) > 0;
492
496
  // A first cumulative snapshot may contain history from a resumed native
493
- // Session. It establishes the generation baseline but cannot prove that
494
- // tokens were consumed during the current observation window.
495
- if (previous === undefined)
497
+ // Session. It establishes a baseline but cannot prove current progress.
498
+ if (previous === undefined || previous.semantics !== "cumulative-session")
496
499
  return false;
497
500
  return usageTotal(current) > usageTotal(previous);
498
501
  }
@@ -0,0 +1,42 @@
1
+ import { createHash } from "node:crypto";
2
+ import { chmodSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
+ import { join, resolve } from "node:path";
4
+ export function writeRuntimeStopReceipt(home, launchId, requestedAt) {
5
+ const receipt = Object.freeze({
6
+ schemaVersion: 1,
7
+ receiptId: `runtime-stop-${createHash("sha256")
8
+ .update(`${launchId}\0${requestedAt.toISOString()}`)
9
+ .digest("hex")}`,
10
+ launchId,
11
+ requestedAt: requestedAt.toISOString()
12
+ });
13
+ const path = stopReceiptPath(home, launchId);
14
+ mkdirSync(resolve(join(home, "runtime", "stop-receipts")), { recursive: true, mode: 0o700 });
15
+ const temporary = `${path}.tmp-${process.pid}`;
16
+ writeFileSync(temporary, `${JSON.stringify(receipt)}\n`, { mode: 0o600 });
17
+ renameSync(temporary, path);
18
+ chmodSync(path, 0o600);
19
+ return receipt;
20
+ }
21
+ export function readRuntimeStopReceipt(home, launchId) {
22
+ try {
23
+ const value = JSON.parse(readFileSync(stopReceiptPath(home, launchId), "utf8"));
24
+ if (value.schemaVersion !== 1 || value.launchId !== launchId
25
+ || typeof value.receiptId !== "string" || !Number.isFinite(Date.parse(value.requestedAt))) {
26
+ throw new Error("Runtime stop receipt is invalid.");
27
+ }
28
+ return Object.freeze({ ...value });
29
+ }
30
+ catch (error) {
31
+ if (error.code === "ENOENT")
32
+ return null;
33
+ throw error;
34
+ }
35
+ }
36
+ export function removeRuntimeStopReceipt(home, launchId) {
37
+ rmSync(stopReceiptPath(home, launchId), { force: true });
38
+ }
39
+ function stopReceiptPath(home, launchId) {
40
+ const name = createHash("sha256").update(launchId).digest("hex");
41
+ return resolve(join(home, "runtime", "stop-receipts", `${name}.json`));
42
+ }
@@ -20,6 +20,19 @@ export async function terminateSessionOwners(owner, records, ports, options = {}
20
20
  const pollMs = positiveDuration(options.pollMs, DEFAULT_TERMINATION_POLL_MS, "pollMs");
21
21
  const now = ports.now();
22
22
  ports.emit({ stage: "stop-requested", owner, at: now });
23
+ // Persist one exact launch receipt before any graceful stop can kill the
24
+ // Host. The owner-wide event remains for compatibility and summary display.
25
+ for (const record of records) {
26
+ ports.emit({
27
+ stage: "stop-requested",
28
+ owner,
29
+ launchId: record.launchId,
30
+ ...(record.nativeSessionId === undefined
31
+ ? {}
32
+ : { nativeSessionId: record.nativeSessionId }),
33
+ at: now
34
+ });
35
+ }
23
36
  // A launch-fence scan is a point-in-time observation, not a durable owner
24
37
  // inventory: /proc entries can disappear between the directory and
25
38
  // environment reads. Retain every exact child identity observed during the