@zq-silk/yui 2.20.0 → 2.22.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 (142) hide show
  1. package/README.md +5 -0
  2. package/dist/cli/commandCatalog.js +88 -28
  3. package/dist/cli/dynamicCompletion.js +4 -1
  4. package/dist/cli/helpRenderer.js +12 -1
  5. package/dist/cli/interactionPolicy.js +2 -0
  6. package/dist/cli/invocationAuthority.js +2 -6
  7. package/dist/cli/invocationRouter.js +5 -5
  8. package/dist/cli/managedDiagnostics.js +24 -16
  9. package/dist/cli/roleWizard.js +5 -1
  10. package/dist/commands/durableJobCommands.js +2 -3
  11. package/dist/commands/globalRoleCommands.js +33 -8
  12. package/dist/commands/inboxCommands.js +39 -12
  13. package/dist/commands/operatorCommands.js +2 -5
  14. package/dist/commands/releaseCommands.js +16 -2
  15. package/dist/commands/roleConfiguration.js +25 -2
  16. package/dist/commands/sessionCommands.js +5 -2
  17. package/dist/commands/taskCommands.js +225 -99
  18. package/dist/commands/taskContextCommand.js +26 -4
  19. package/dist/commands/taskFactCommands.js +20 -7
  20. package/dist/commands/taskIntegrationCommands.js +3 -3
  21. package/dist/commands/taskRoleRuntimeStatus.js +15 -5
  22. package/dist/commands/taskUsageCommand.js +2 -6
  23. package/dist/commands/textInput.js +2 -2
  24. package/dist/context/contextFamilies.js +10 -0
  25. package/dist/context/currentSkills.js +6 -4
  26. package/dist/context/runContextPack.js +44 -5
  27. package/dist/context/runInputContract.js +1 -1
  28. package/dist/context/sessionBootstrapManifest.js +7 -5
  29. package/dist/context/sessionSkillNotice.js +53 -0
  30. package/dist/context/taskCatalog.js +4 -13
  31. package/dist/context/taskContext.js +135 -103
  32. package/dist/context/taskSearch.js +3 -7
  33. package/dist/controlPlaneCli.js +23 -25
  34. package/dist/controller/agentRuntimeObserver.js +57 -12
  35. package/dist/controller/clientRuntime.js +37 -8
  36. package/dist/controller/controller.js +3 -1
  37. package/dist/controller/diagnosticJournal.js +10 -2
  38. package/dist/controller/fileSchedulerStoreAdapter.js +72 -24
  39. package/dist/controller/jobClient.js +2 -2
  40. package/dist/controller/jobControl.js +2 -2
  41. package/dist/controller/jobDefinitionControl.js +5 -1
  42. package/dist/controller/messageHealth.js +4 -3
  43. package/dist/controller/providerRetryAdmission.js +15 -1
  44. package/dist/controller/providerRetryDelivery.js +18 -2
  45. package/dist/controller/runtime.js +15 -5
  46. package/dist/controller/runtimeEventInbox.js +107 -13
  47. package/dist/controller/runtimeEventProcessor.js +3 -3
  48. package/dist/controller/taskRunRecovery.js +153 -0
  49. package/dist/core/controllerClient.js +16 -2
  50. package/dist/core/controllerServer.js +14 -5
  51. package/dist/core/controllerTelemetry.js +51 -5
  52. package/dist/errors/cliFailure.js +14 -5
  53. package/dist/executor/agentAdapter.js +32 -4
  54. package/dist/executor/agentConfigurationFields.js +2 -0
  55. package/dist/executor/taskAgentCapabilities.js +2 -2
  56. package/dist/integration/gitIntegrationService.js +3 -2
  57. package/dist/integration/integrationSourceApplication.js +12 -1
  58. package/dist/interaction/notificationPresentation.js +11 -16
  59. package/dist/interaction/operatorPresentation.js +1 -1
  60. package/dist/message/messageContinuation.js +3 -1
  61. package/dist/output/boundedRead.js +36 -7
  62. package/dist/output/rolePresentation.js +3 -1
  63. package/dist/runtime/agentHost.js +12 -3
  64. package/dist/runtime/codexAppServerRuntime.js +110 -24
  65. package/dist/runtime/codexInteractiveHost.js +46 -0
  66. package/dist/runtime/providerRetry.js +5 -2
  67. package/dist/runtime/providerRuntimeIdentity.js +1 -1
  68. package/dist/runtime/structuredProviderHost.js +32 -34
  69. package/dist/scheduler/wakeupQueue.js +10 -4
  70. package/dist/storage/sqliteSchema.js +9 -0
  71. package/dist/storage/storageVersions.js +1 -1
  72. package/dist/task/taskAuthority.js +7 -3
  73. package/dist/tmux/tmuxManager.js +4 -2
  74. package/dist/web/webSettings.js +2 -0
  75. package/docs/authorization.md +18 -3
  76. package/docs/cli-information-contract.md +245 -6
  77. package/docs/cli-information-contract.zh-CN.md +107 -5
  78. package/docs/managed-turn-and-session-runtime.md +82 -21
  79. package/docs/managed-turn-and-session-runtime.zh-CN.md +56 -13
  80. package/docs/provider-retry.md +11 -0
  81. package/docs/release-workflow.md +62 -0
  82. package/docs/release-workflow.zh-CN.md +46 -0
  83. package/docs/roles-and-configuration.md +28 -0
  84. package/docs/roles-and-configuration.zh-CN.md +21 -0
  85. package/docs/storage-baseline.md +4 -1
  86. package/docs/storage-baseline.zh-CN.md +1 -1
  87. package/docs/task-delivery.md +7 -0
  88. package/docs/task-delivery.zh-CN.md +5 -0
  89. package/docs/task-discovery.md +5 -5
  90. package/docs/task-discovery.zh-CN.md +4 -4
  91. package/docs/testing/review-evaluation.md +7 -7
  92. package/docs/testing/review-evaluation.zh-CN.md +7 -7
  93. package/docs/testing/verification-levels.md +45 -2
  94. package/docs/testing/verification-levels.zh-CN.md +21 -2
  95. package/i18n/README.zh-CN.md +6 -0
  96. package/package.json +1 -1
  97. package/skills/yui-leader/SKILL.md +98 -189
  98. package/skills/yui-leader/VERSION +1 -1
  99. package/skills/yui-leader/references/artifacts.md +41 -0
  100. package/skills/yui-leader/references/assignment-execution.md +140 -0
  101. package/skills/yui-leader/references/completion.md +79 -0
  102. package/skills/yui-leader/references/delivery-scope.md +26 -0
  103. package/skills/yui-leader/references/execution.md +16 -487
  104. package/skills/yui-leader/references/implementation.md +81 -0
  105. package/skills/yui-leader/references/planning.md +7 -45
  106. package/skills/yui-leader/references/review.md +90 -0
  107. package/skills/yui-leader/references/task-progress.md +23 -0
  108. package/skills/yui-leader/references/work-allocation.md +118 -0
  109. package/skills/yui-operator/SKILL.md +77 -331
  110. package/skills/yui-operator/VERSION +1 -1
  111. package/skills/yui-operator/references/body-transport.md +62 -0
  112. package/skills/yui-operator/references/configuration.md +47 -0
  113. package/skills/yui-operator/references/lifecycle.md +41 -0
  114. package/skills/yui-operator/references/progress.md +39 -0
  115. package/skills/yui-operator/references/routing.md +57 -0
  116. package/skills/yui-operator/references/submission.md +56 -0
  117. package/skills/yui-operator/references/task-delivery.md +5 -2
  118. package/skills/yui-operator/references/web-lifecycle.md +19 -0
  119. package/skills/yui-operator/scripts/verify-submission.mjs +37 -0
  120. package/skills/yui-reviewer/SKILL.md +4 -2
  121. package/skills/yui-reviewer/VERSION +1 -1
  122. package/skills/yui-runtime/SKILL.md +177 -505
  123. package/skills/yui-runtime/VERSION +1 -1
  124. package/skills/yui-runtime/references/archive.md +51 -0
  125. package/skills/yui-runtime/references/command-discovery.md +41 -0
  126. package/skills/yui-runtime/references/completed-followup.md +65 -0
  127. package/skills/yui-runtime/references/context-ordering.md +3 -34
  128. package/skills/yui-runtime/references/context-reads.md +61 -0
  129. package/skills/yui-runtime/references/dispatched-run.md +61 -0
  130. package/skills/yui-runtime/references/execution-failure.md +105 -0
  131. package/skills/yui-runtime/references/global-context.md +18 -0
  132. package/skills/yui-runtime/references/global-input-controls.md +44 -0
  133. package/skills/yui-runtime/references/host-custody.md +30 -0
  134. package/skills/yui-runtime/references/inbox-recovery.md +77 -0
  135. package/skills/yui-runtime/references/incremental-context.md +40 -0
  136. package/skills/yui-runtime/references/publication.md +4 -104
  137. package/skills/yui-runtime/references/recovery.md +32 -192
  138. package/skills/yui-runtime/references/session-identity.md +18 -0
  139. package/skills/yui-runtime/references/session-replacement.md +45 -0
  140. package/skills/yui-runtime/references/uncertain-execution.md +29 -0
  141. package/skills/yui-worker/SKILL.md +7 -4
  142. package/skills/yui-worker/VERSION +1 -1
package/README.md CHANGED
@@ -459,6 +459,11 @@ manage global installations; do not use the global `yui` to validate local chang
459
459
  Live-model, paid or shared-resource
460
460
  tests require an explicit request for those resources.
461
461
 
462
+ For topic-specific evaluation and shared evidence tools, see
463
+ [evaluation tooling](scripts/eval/README.md).
464
+ `npm run eval:check` is fast and offline; `eval:context:wiring` is an explicit isolated
465
+ fake-Provider check, outside the default core gate. It is not model validation.
466
+
462
467
  ## Community and support
463
468
 
464
469
  - Questions, bugs and feature requests: open a
@@ -1,4 +1,5 @@
1
1
  import { supportedAgentAdapterIds } from "../agent/adapterCatalog.js";
2
+ import { CONTEXT_FAMILIES } from "../context/contextFamilies.js";
2
3
  import { supportedAgentExecutionComponentIds } from "../agent/executionComponents.js";
3
4
  import { productConfigurationOptions } from "../nativeAgent/product/config.js";
4
5
  import { catalogCommands, catalogCommandOptions } from "../nativeAgent/product/catalog.js";
@@ -142,6 +143,7 @@ const roleProfileOptions = [
142
143
  ];
143
144
  const roleAgentOptions = [
144
145
  "--model", "--effort", "--permission-strategy", "--sandbox", "--approval", "--permission-mode",
146
+ "--exclude-tmpdir-env-var", "--exclude-slash-tmp",
145
147
  "--allowed-tool", "--disallowed-tool", "--search"
146
148
  ];
147
149
  const roleProfileClearOptions = [
@@ -151,7 +153,7 @@ const roleProfileClearOptions = [
151
153
  ];
152
154
  const roleAgentClearOptions = [
153
155
  "--clear-model", "--clear-effort", "--clear-allowed-tools", "--clear-disallowed-tools",
154
- "--clear-search", "--clear-agent-config"
156
+ "--clear-search", "--clear-agent-config", "--clear-exclude-tmpdir-env-var", "--clear-exclude-slash-tmp"
155
157
  ];
156
158
  const agentProfileOptions = [
157
159
  "--description", "--instructions", "--skill",
@@ -164,6 +166,8 @@ const agentProfileClearOptions = [
164
166
  const roleAgentOptionValues = {
165
167
  "--sandbox": ["read-only", "workspace-write", "danger-full-access"],
166
168
  "--approval": ["untrusted", "on-request", "never"],
169
+ "--exclude-tmpdir-env-var": ["true", "false"],
170
+ "--exclude-slash-tmp": ["true", "false"],
167
171
  "--permission-strategy": ["default", "bypass", "configured"],
168
172
  "--search": ["true"]
169
173
  };
@@ -234,7 +238,8 @@ const globalSessionChildren = [
234
238
  {
235
239
  name: "retry", discovery: { surface: "public", audiences: ["public", "operator"] },
236
240
  summary: "Inspect or control bounded Provider recovery for this Global Session.",
237
- usage: "yui session retry <role> [show|cancel|disable|enable]"
241
+ usage: "yui session retry <role> [show|cancel|disable|enable] [--cursor <cursor> (show only)]",
242
+ options: ["--cursor"]
238
243
  }
239
244
  ];
240
245
  const profileChildren = [
@@ -401,19 +406,19 @@ const taskChildren = [
401
406
  fileOptions: ["--summary-file"]
402
407
  },
403
408
  {
404
- name: "list", discovery: { surface: "public", audiences: ["public", "operator", "leader"] },
409
+ name: "list", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment"] },
405
410
  summary: "Discover Tasks through a bounded, filterable catalog.",
406
411
  usage: "yui task list [--all] [--source <ordinary|job>] [--status <status>] [--project <id>] [--search <text>] [--attention <category>] [--limit <1..100>] [--cursor <cursor>]",
407
412
  options: ["--all", "--source", "--status", "--project", "--search", "--attention", "--limit", "--cursor"]
408
413
  },
409
414
  {
410
- name: "search", discovery: { surface: "public", audiences: ["public", "operator", "leader"] },
415
+ name: "search", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment"] },
411
416
  summary: "Search authorized Task bodies and return exact, reference-only source citations.",
412
417
  usage: "yui task search <query> [--task <id>] [--kind <brief|message|decision|result|completion>] [--limit <1..100>] [--cursor <cursor>]",
413
418
  options: ["--task", "--kind", "--limit", "--cursor"]
414
419
  },
415
420
  { name: "show", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment"] }, summary: "Show Task metadata and counts; long details use contentPage.", usage: "yui task show <id> [--cursor <cursor>]", options: ["--cursor"] },
416
- { name: "usage", discovery: { surface: "public", audiences: ["public", "operator", "leader"] }, summary: "Read bounded Task usage and sourced costs; request detail pages explicitly.", usage: "yui task usage <task> [--limit <0..50>] [--offset <n>]", options: ["--limit", "--offset"] },
421
+ { name: "usage", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment"] }, summary: "Read bounded Task usage and sourced costs; request detail pages explicitly.", usage: "yui task usage <task> [--limit <0..50>] [--offset <n>]", options: ["--limit", "--offset"] },
417
422
  {
418
423
  name: "artifact", discovery: { surface: "managed", audiences: ["operator", "leader"] },
419
424
  summary: "Save Task files in local Git and read current or commit-pinned content.",
@@ -426,10 +431,41 @@ const taskChildren = [
426
431
  },
427
432
  {
428
433
  name: "context", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment", "unbound"] },
429
- summary: "Read compact authorized facts, fixed-bound delta, or inspect a Context reference.",
430
- usage: "yui task context [read|list|delta|inspect] <task> [--after <cursor>] [--continuation <cursor>] [--cursor <cursor>] [--limit <n>] [--store <store> --ref <id>] [--digest <digest>] [--view <current|all>]",
431
- options: ["--after", "--continuation", "--cursor", "--limit", "--store", "--ref", "--digest", "--status", "--work-item", "--view"],
432
- optionValues: { "--view": ["current", "all"] }
434
+ summary: "Read current authorized facts; discover references or inspect complete originals with a focused subcommand.",
435
+ executable: true,
436
+ usage: "yui task context <task>",
437
+ sections: [{ id: "read", title: "Context reads", entries: ["read", "list", "inspect", "delta"] }],
438
+ children: [
439
+ {
440
+ name: "read", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment", "unbound"] },
441
+ summary: "Read the current bounded Task index, equivalent to task context <task>.",
442
+ usage: "yui task context read <task>"
443
+ },
444
+ {
445
+ name: "list", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment", "unbound"] },
446
+ summary: "Discover one authorized family. --after filters creation time, not later edits; current excludes explicit ACK/retirement.",
447
+ usage: "yui task context list <task> --store <store> [--cursor <cursor>] [--limit <1..100>] [--view current|all] [--status <status>] [--after <timestamp>] [--work-item <id>]",
448
+ options: ["--store", "--cursor", "--limit", "--view", "--status", "--after", "--work-item"],
449
+ optionValues: { "--view": ["current", "all"], "--store": CONTEXT_FAMILIES }
450
+ },
451
+ {
452
+ name: "inspect", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment", "unbound"] },
453
+ summary: "Read complete originals. Choose one single-ref or 1–8-ref batch form; finish contentPage using the same selection and cursor.",
454
+ usage: [
455
+ "yui task context inspect <task> --store <store> --ref <id> [--digest <digest>] [--cursor <cursor>]",
456
+ "yui task context inspect <task> --context-ref <store/refId@digest> ... [--cursor <cursor>]",
457
+ "yui task context inspect <task> --refs <JSON-array-of-store-refId-digest> [--cursor <cursor>]"
458
+ ],
459
+ options: ["--store", "--ref", "--digest", "--context-ref", "--refs", "--cursor"],
460
+ optionValues: { "--store": CONTEXT_FAMILIES }
461
+ },
462
+ {
463
+ name: "delta", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment", "unbound"] },
464
+ summary: "Read fixed-bound event history after coreCursor, not current record bodies. Use throughCursor for the next window.",
465
+ usage: "yui task context delta <task> --after <cursor> [--continuation <cursor>] [--limit <1..100>]",
466
+ options: ["--after", "--continuation", "--limit"]
467
+ }
468
+ ]
433
469
  },
434
470
  {
435
471
  name: "next-action", discovery: { surface: "managed", audiences: ["operator", "leader"] },
@@ -708,11 +744,11 @@ const taskChildren = [
708
744
  { name: "list", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Discover recorded Role health; Host is unchecked until role status.", usage: "yui task role list <task> [--limit <1..100>] [--cursor <cursor>]", options: ["--limit", "--cursor"] },
709
745
  {
710
746
  name: "status", discovery: { surface: "managed", audiences: ["operator", "leader"] },
711
- summary: "Show persisted and live runtime state for one Task Role.",
712
- usage: "yui task role status <task> <role> [--cursor <cursor>]",
713
- options: ["--cursor"]
747
+ summary: "Show current execution observations; full includes nested original records.",
748
+ usage: "yui task role status <task> <role> [--view current|full] [--cursor <cursor>]",
749
+ options: ["--view", "--cursor"], optionValues: { "--view": ["current", "full"] }
714
750
  },
715
- { name: "show", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Show one Task Role.", usage: "yui task role show <task> <role> [--cursor <cursor>]", options: ["--cursor"] },
751
+ { name: "show", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Show current Role configuration; full adds Session and Run history.", usage: "yui task role show <task> <role> [--view current|full] [--cursor <cursor>]", options: ["--view", "--cursor"], optionValues: { "--view": ["current", "full"] } },
716
752
  { name: "enable", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Enable this Task Role; does not change Task execution authority.", usage: "yui task role enable <task> <role>" },
717
753
  { name: "disable", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Block new execution of this Task Role without stopping its current Run.", usage: "yui task role disable <task> <role>" },
718
754
  { name: "capabilities", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Read native options using this Role's desired or exact failed launch configuration.",
@@ -738,7 +774,8 @@ const taskChildren = [
738
774
  {
739
775
  name: "retry", discovery: { surface: "managed", audiences: ["operator", "leader"] },
740
776
  summary: "Inspect or control Provider recovery without stopping an admitted Turn.",
741
- usage: "yui task role session retry <task> <role> [show|cancel|disable|enable]"
777
+ usage: "yui task role session retry <task> <role> [show|cancel|disable|enable] [--cursor <cursor> (show only)]",
778
+ options: ["--cursor"]
742
779
  },
743
780
  {
744
781
  name: "inspect", discovery: { surface: "managed", audiences: ["operator", "leader"] },
@@ -912,9 +949,9 @@ const taskChildren = [
912
949
  { name: "list", discovery: { surface: "managed", audiences: ["operator", "leader", "assignment"] }, summary: "Discover AgentRuns for a Task or one WorkItem.", usage: "yui task run list <task|task/work> [--limit <1..100>] [--cursor <cursor>]", options: ["--limit", "--cursor"] },
913
950
  {
914
951
  name: "show", discovery: { surface: "managed", audiences: ["operator", "leader", "assignment"] },
915
- summary: "Show one AgentRun and its retained audit evidence.",
916
- usage: "yui task run show <task>/<run> [--cursor <cursor>] [--json]",
917
- options: ["--cursor", "--json"]
952
+ summary: "Read full audit evidence, current status, or the complete original result without input/configuration bodies.",
953
+ usage: "yui task run show <task>/<run> [--view full|status|result] [--cursor <cursor>] [--json]",
954
+ options: ["--view", "--cursor", "--json"]
918
955
  },
919
956
  {
920
957
  name: "retry", discovery: { surface: "managed", audiences: ["operator", "leader"] },
@@ -937,9 +974,12 @@ const taskChildren = [
937
974
  children: [
938
975
  {
939
976
  name: "expand", discovery: { surface: "managed", audiences: ["operator", "leader", "assignment"] },
940
- summary: "Expand one authorized AgentRun context reference.",
941
- usage: "yui task run context expand <task>/<run> <ref-id> --store <store> [--mode full] [--cursor <cursor>]",
942
- options: ["--store", "--mode", "--cursor"]
977
+ summary: "Read one frozen original or 1–8 explicitly selected originals from the same authorized Run.",
978
+ usage: [
979
+ "yui task run context expand <task>/<run> <ref-id> --store <store> [--mode full] [--cursor <cursor>]",
980
+ "yui task run context expand <task>/<run> --context-ref <store/refId[@digest]> ... [--cursor <cursor>]"
981
+ ],
982
+ options: ["--store", "--context-ref", "--mode", "--cursor"]
943
983
  },
944
984
  {
945
985
  name: "delta", discovery: { surface: "managed", audiences: ["operator", "leader", "assignment"] },
@@ -1122,7 +1162,7 @@ const taskChildren = [
1122
1162
  { name: "show", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Show fixed wake inputs/results; expand diagnostics with --history.", usage: "yui task wake show <task> <wake> [--history] [--cursor <cursor>]", options: ["--history", "--cursor"] },
1123
1163
  { name: "retry", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Retry a rejected notification after correcting its cause; preserve original input.",
1124
1164
  usage: "yui task wake retry <task> <wake> --reason <correction>", options: ["--reason"] },
1125
- { name: "resolve", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Release an unknown notification claim after explicit quiescence evidence, without replay.",
1165
+ { name: "resolve", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Release an unknown or rejected notification for explicit handling after quiescence evidence, without replay.",
1126
1166
  usage: "yui task wake resolve <task> <wake> --reason <quiescence-evidence>", options: ["--reason"] }
1127
1167
  ]
1128
1168
  },
@@ -1239,7 +1279,12 @@ export const ROOT_COMMAND = buildNode({
1239
1279
  }
1240
1280
  ]
1241
1281
  },
1242
- { name: "help", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment", "global", "unbound"] }, summary: "Show root or scoped command help.", usage: "yui help [command ...]", commandPathArguments: true },
1282
+ {
1283
+ name: "help", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment", "global", "unbound"] },
1284
+ summary: "Show root or scoped command help; JSON defaults to immediate child summaries.",
1285
+ usage: ["yui help [command ...]", "yui --json help [command ...] --recursive"],
1286
+ options: ["--recursive"], commandPathArguments: true
1287
+ },
1243
1288
  { name: "version", discovery: { surface: "public", audiences: ["public", "operator", "leader", "assignment", "global", "unbound"] }, summary: "Print the installed Yui version." },
1244
1289
  {
1245
1290
  name: "update", discovery: { surface: "public", audiences: ["public", "operator"] },
@@ -1811,8 +1856,7 @@ export function findCommandNode(path, root = ROOT_COMMAND) {
1811
1856
  return node;
1812
1857
  }
1813
1858
  export const findCommand = findCommandNode;
1814
- /** Structured help projection consumed by `config describe --json` and Operator. */
1815
- export function describeCommandTree(node) {
1859
+ function describeCommand(node) {
1816
1860
  return {
1817
1861
  path: node.path.slice(1).join(" "),
1818
1862
  summary: node.summary,
@@ -1821,8 +1865,25 @@ export function describeCommandTree(node) {
1821
1865
  options: node.options,
1822
1866
  optionValues: node.optionValues,
1823
1867
  argumentValues: node.argumentValues,
1824
- values: node.values,
1825
- children: visibleChildren(node).map(describeCommandTree)
1868
+ values: node.values
1869
+ };
1870
+ }
1871
+ /** Complete caller-filtered tree for explicit recursive help and offline tools. */
1872
+ export function describeCommandTree(node) {
1873
+ return { ...describeCommand(node), children: visibleChildren(node).map(describeCommandTree) };
1874
+ }
1875
+ /** Complete current-command details; descendants require explicit navigation. */
1876
+ export function describeCommandHelp(node) {
1877
+ return {
1878
+ ...describeCommand(node),
1879
+ children: visibleChildren(node).map(child => ({
1880
+ path: child.path.slice(1).join(" "), summary: child.summary
1881
+ })),
1882
+ discovery: {
1883
+ children: "complete-immediate-summaries",
1884
+ details: "yui --json help <command ...>",
1885
+ tree: "yui --json help [command ...] --recursive"
1886
+ }
1826
1887
  };
1827
1888
  }
1828
1889
  export function validateCommandCatalog(root) {
@@ -1857,7 +1918,6 @@ export function validateCommandCatalog(root) {
1857
1918
  || node.children.length > 0
1858
1919
  || node.values.length > 0
1859
1920
  || node.sections.length > 0
1860
- || node.options.length > 0
1861
1921
  || node.hiddenOptions.length > 0
1862
1922
  || Object.keys(node.optionValues).length > 0
1863
1923
  || Object.keys(node.argumentValues).length > 0
@@ -1865,7 +1925,7 @@ export function validateCommandCatalog(root) {
1865
1925
  || node.fileArguments.length > 0
1866
1926
  || node.executableOptions.length > 0;
1867
1927
  if (ownsOtherCompletionMetadata) {
1868
- throw new Error(`Command-path provider must be a visible metadata-free leaf: ${node.path.join(" ")}`);
1928
+ throw new Error(`Command-path provider must be a visible leaf with only flag options: ${node.path.join(" ")}`);
1869
1929
  }
1870
1930
  }
1871
1931
  const immediate = new Set();
@@ -8,7 +8,10 @@ export async function resolveCompletionCandidates(input) {
8
8
  const root = input.root ?? ROOT_COMMAND;
9
9
  if (words[0] === "help") {
10
10
  const { node, consumed } = resolveCommand(words.slice(1), root);
11
- return consumed === words.length - 1 ? prefix(visibleChildren(node).map(child => child.name), input.current) : [];
11
+ if (consumed !== words.length - 1)
12
+ return [];
13
+ return prefix(input.current.startsWith("-") ? findChild(root, "help")?.options ?? []
14
+ : visibleChildren(node).map(child => child.name), input.current);
12
15
  }
13
16
  const { node, consumed } = resolveCommand(words, root);
14
17
  if (node.kind === "group" && consumed < words.length)
@@ -1,4 +1,14 @@
1
- import { visibleCommandSections } from "./commandCatalog.js";
1
+ import { orderedImmediateTokens, visibleCommandSections } from "./commandCatalog.js";
2
+ /** A path error needs nearby choices, not another complete help document.
3
+ * The caller supplies the already-filtered discovery node. */
4
+ export function renderCommandPathHint(node) {
5
+ const choices = orderedImmediateTokens(node);
6
+ const path = node.path.slice(1).join(" ");
7
+ return [
8
+ ...(choices.length === 0 ? [] : [`Visible choices here: ${choices.join(", ")}`]),
9
+ `Full help: yui --json help${path ? ` ${path}` : ""}`
10
+ ].join("\n") + "\n";
11
+ }
2
12
  export function renderCommandHelp(node, version) {
3
13
  const title = node.path.length === 1
4
14
  ? `Yui ${version}`
@@ -30,6 +40,7 @@ function describeOption(option) {
30
40
  "--detach": "Return after Controller starts Web; use --status / --stop. Operator and --json starts always return.",
31
41
  "--port": "Set the local listen port.",
32
42
  "--json": "Emit machine-readable JSON.",
43
+ "--recursive": "Expand the complete caller-filtered command tree (requires --json).",
33
44
  "--project": "Select a Project.",
34
45
  "--role": "Select a Task role.",
35
46
  "--summary": "Set summary text.",
@@ -88,6 +88,7 @@ export const INTERACTION_POLICIES = Object.freeze([
88
88
  "--responsibility": "value", "--constraint": "value", "--expected-output": "value",
89
89
  "--system-prompt": "value", "--skill": "value", "--model": "value",
90
90
  "--effort": "value", "--permission-strategy": "value", "--sandbox": "value", "--approval": "value",
91
+ "--exclude-tmpdir-env-var": "value", "--exclude-slash-tmp": "value",
91
92
  "--permission-mode": "value", "--allowed-tool": "value", "--disallowed-tool": "value",
92
93
  "--search": "value"
93
94
  }
@@ -374,6 +375,7 @@ export const INTERACTION_POLICIES = Object.freeze([
374
375
  "--constraint": "value", "--expected-output": "value", "--system-prompt": "value",
375
376
  "--skill": "value", "--model": "value", "--effort": "value",
376
377
  "--permission-strategy": "value", "--sandbox": "value", "--approval": "value", "--permission-mode": "value",
378
+ "--exclude-tmpdir-env-var": "value", "--exclude-slash-tmp": "value",
377
379
  "--allowed-tool": "value", "--disallowed-tool": "value", "--search": "value"
378
380
  }
379
381
  },
@@ -4,7 +4,7 @@ import { requireManagedGlobalCaller } from "../runtime/managedCaller.js";
4
4
  import { routeInvocation } from "./invocationRouter.js";
5
5
  import { findInteractionPolicy } from "./interactionPolicy.js";
6
6
  import { TASK_RECORD_ID_PREFIXES } from "../task/taskRecordReference.js";
7
- import { taskDiagnosticTarget } from "./managedDiagnostics.js";
7
+ import { isTaskReadCommand } from "./managedDiagnostics.js";
8
8
  /** Configuration reads remain available; every Home configuration mutation
9
9
  * has one owner, irrespective of which config subcommand parses its flags. */
10
10
  export function assertConfigurationAuthority(args, store, env) {
@@ -37,12 +37,8 @@ export function assertTaskInvocationScope(args, env) {
37
37
  }
38
38
  if (args[0] !== "task" || ["list", "search"].includes(args[1] ?? ""))
39
39
  return;
40
- const diagnostic = taskDiagnosticTarget(args);
41
- if (diagnostic !== undefined) {
42
- if (diagnostic !== env.YUI_TASK_ID)
43
- throw usageError("Command target is outside the caller's Task.");
40
+ if (isTaskReadCommand(args))
44
41
  return;
45
- }
46
42
  const invocation = routeInvocation([...args]);
47
43
  if (invocation.kind !== "execute")
48
44
  return;
@@ -18,20 +18,20 @@ export function routeInvocation(args, discoveryRoot = ROOT_COMMAND) {
18
18
  return { ...result, helpNode };
19
19
  }
20
20
  function resolveHelpPath(path, root) {
21
- if (path.length === 0)
22
- return { kind: "help", node: root };
21
+ const recursive = path.at(-1) === "--recursive";
22
+ const segments = recursive ? path.slice(0, -1) : path;
23
23
  let node = root;
24
24
  let nearestGroup = root;
25
- for (const segment of path) {
25
+ for (const segment of segments) {
26
26
  const child = findChild(node, segment);
27
27
  if (child === undefined || child.hidden) {
28
- return { kind: "path-error", typedPath: path.join(" "), helpNode: nearestGroup };
28
+ return { kind: "path-error", typedPath: path.join(" "), helpNode: nearestGroup, discoveryOnly: true };
29
29
  }
30
30
  node = child;
31
31
  if (node.kind !== "leaf")
32
32
  nearestGroup = node;
33
33
  }
34
- return { kind: "help", node };
34
+ return { kind: "help", node, recursive };
35
35
  }
36
36
  function resolveExecutionPath(args) {
37
37
  let node = ROOT_COMMAND;
@@ -1,20 +1,28 @@
1
- /** Read/repair routing, not an alternative grant. Callers still prove their
2
- * Home and Role identity; writes still require current Session authority. */
3
- export function taskDiagnosticTarget(args) {
1
+ /** Explicit effect classification, not a verb-name heuristic. Ordinary reads
2
+ * authenticate the caller but do not borrow the target Task's authority.
3
+ * Mixed commands (retry, base status) stay mutating unless this exact form is
4
+ * read-only. Domain parsers still reject unknown flags and malformed targets. */
5
+ export function isTaskReadCommand(args) {
4
6
  if (args[0] !== "task")
5
- return undefined;
6
- if (["show", "context", "next-action", "archive-preflight"].includes(args[1] ?? "")) {
7
- return args[1] === "context" && ["read", "list", "inspect", "delta"].includes(args[2] ?? "")
8
- ? args[3] : args[2];
9
- }
10
- if (args[1] === "role" && ["list", "status", "show"].includes(args[2] ?? ""))
11
- return args[3];
12
- if (args[1] === "role" && args[2] === "session" && args[3] === "inspect")
13
- return args[4];
14
- if (["message", "run", "wake", "input"].includes(args[1] ?? "")
7
+ return false;
8
+ if (["list", "search", "show", "usage", "next-action", "remote-delivery", "archive-preflight"].includes(args[1] ?? ""))
9
+ return true;
10
+ if (args[1] === "context")
11
+ return true;
12
+ if (["brief", "decision", "milestone", "event", "message", "run", "wake", "input", "work", "publication"].includes(args[1] ?? "")
15
13
  && ["list", "show"].includes(args[2] ?? ""))
16
- return args[3]?.split("/")[0];
17
- return undefined;
14
+ return true;
15
+ if (args[1] === "artifact" && ["list", "read"].includes(args[2] ?? ""))
16
+ return true;
17
+ if (args[1] === "run" && args[2] === "context")
18
+ return true;
19
+ if (args[1] === "role" && ["list", "status", "show"].includes(args[2] ?? ""))
20
+ return true;
21
+ if (args[1] === "role" && args[2] === "session") {
22
+ return args[3] === "inspect"
23
+ || args[3] === "retry" && (args.length === 6 || args.length === 7 && args[6] === "show");
24
+ }
25
+ return false;
18
26
  }
19
27
  export function operatorOfflineCommand(args) {
20
28
  return (args[0] === "controller"
@@ -25,5 +33,5 @@ export function operatorOfflineCommand(args) {
25
33
  || (args[0] === "session" && ["context", "reconcile"].includes(args[1] ?? ""))
26
34
  || (args[0] === "role" && args[1] === "message" && ["list", "show"].includes(args[2] ?? ""))
27
35
  || (args[0] === "task" && args[1] === "list")
28
- || taskDiagnosticTarget(args) !== undefined;
36
+ || isTaskReadCommand(args);
29
37
  }
@@ -459,7 +459,11 @@ function agentFields(binding, catalog) {
459
459
  agentField("permission-strategy", "Permission strategy", permission.strategy, "--permission-strategy", ["--permission-strategy", "default"], catalogField(catalog, "permission.strategy")),
460
460
  ...(binding.adapterId === "codex" && permission.strategy === "configured" ? [
461
461
  agentField("sandbox", "Sandbox", permission.sandbox, "--sandbox", ["--permission-strategy", "default"], catalogField(catalog, "permission.sandbox")),
462
- agentField("approval", "Approval", permission.approval, "--approval", ["--permission-strategy", "default"], catalogField(catalog, "permission.approval"))
462
+ agentField("approval", "Approval", permission.approval, "--approval", ["--permission-strategy", "default"], catalogField(catalog, "permission.approval")),
463
+ ...(permission.sandbox === "workspace-write" ? [
464
+ agentField("exclude-tmpdir-env-var", "Exclude TMPDIR write access", permission.excludeTmpdirEnvVar, "--exclude-tmpdir-env-var", ["--clear-exclude-tmpdir-env-var"], catalogField(catalog, "permission.excludeTmpdirEnvVar")),
465
+ agentField("exclude-slash-tmp", "Exclude /tmp write access", permission.excludeSlashTmp, "--exclude-slash-tmp", ["--clear-exclude-slash-tmp"], catalogField(catalog, "permission.excludeSlashTmp"))
466
+ ] : [])
463
467
  ] : []),
464
468
  ...(binding.adapterId === "codex" ? [
465
469
  agentField("search", "Web search", config.search, "--search", ["--clear-search"], catalogField(catalog, "search"))
@@ -2,7 +2,7 @@ import { usageError } from "../errors/cliError.js";
2
2
  import { ensureFileTaskController } from "../controller/clientRuntime.js";
3
3
  import { callFileTaskController } from "../controller/clientRuntime.js";
4
4
  import { acknowledgeDurableJob, cancelDurableJob, getDurableJob, startDurableJob } from "../controller/jobClient.js";
5
- import { resolveJobCaller, taskLocalActor } from "../task/taskAuthority.js";
5
+ import { resolveJobCaller, resolveJobReadCaller, taskLocalActor } from "../task/taskAuthority.js";
6
6
  import { boundedJobArtifactPayload } from "../artifacts/jobArtifactTransport.js";
7
7
  import { readFileSync, statSync } from "node:fs";
8
8
  /**
@@ -177,8 +177,7 @@ async function startJob(args, options) {
177
177
  }
178
178
  async function getJob(args, options) {
179
179
  const ref = parseRefArgs(args, "get");
180
- const caller = resolveJobCaller(options.environment, ref.taskId);
181
- await ensureFileTaskController(options.home, { environment: options.environment });
180
+ const caller = resolveJobReadCaller(options.environment, ref.taskId);
182
181
  const job = await getDurableJob(options.home, ref.taskId, ref.jobId, caller);
183
182
  if (options.json === true)
184
183
  return `${JSON.stringify(job, null, 2)}\n`;
@@ -151,6 +151,21 @@ function roleContext(args, store, options) {
151
151
  historyRead: "yui inbox list --view history --json",
152
152
  note: "Historical absence of handling evidence is not new work or permission to replay effects."
153
153
  });
154
+ // Only the managed Turn's exact inputs, not the available queue or history.
155
+ // Keep pending's cursor lineage unchanged; oversized originals retain their
156
+ // existing exact detail read. No delivery/claim/ACK is performed here.
157
+ let originalBudget = 8 * 1024;
158
+ const visibleIds = new Set(pending.items.map(message => message.id));
159
+ const category = globalInboxCategory(name, sessions);
160
+ const currentOriginals = selfRead ? current.filter(message => {
161
+ if (!visibleIds.has(message.id) || category(message) !== "current")
162
+ return false;
163
+ const bytes = Buffer.byteLength(JSON.stringify(message));
164
+ if (bytes > 4 * 1024 || bytes > originalBudget)
165
+ return false;
166
+ originalBudget -= bytes;
167
+ return true;
168
+ }) : [];
154
169
  const observedAt = new Date();
155
170
  const { oldestAgeMs, messages: _backlogMessages, ...backlog } = globalInputBacklog(queued, sessions, observedAt, {
156
171
  attention: name === "operator" ? store.getWorkMailbox({ kind: "operator" }) : null,
@@ -191,6 +206,7 @@ function roleContext(args, store, options) {
191
206
  },
192
207
  // Reading pending input is neither delivery nor implementation.
193
208
  pending,
209
+ currentOriginals,
194
210
  backlog,
195
211
  reads: {
196
212
  ownInbox: "yui inbox list --view current --json",
@@ -233,13 +249,16 @@ function roleContext(args, store, options) {
233
249
  ""
234
250
  ].join("\n") };
235
251
  }
236
- function currentGlobalInboxMessages(messages, name, sessions) {
252
+ function globalInboxCategory(name, sessions) {
237
253
  const actor = { scope: "global", roleName: name, agentId: sessions?.activeAgentId ?? "",
238
254
  nativeSessionId: sessions?.sessions[sessions.activeAgentId]?.nativeSessionId ?? "" };
239
255
  const binding = sessions?.providerBinding;
240
256
  const turn = binding?.conversations.find(c => c.epoch === binding.currentConversationEpoch)?.conversationId === actor.nativeSessionId
241
257
  ? binding?.run : undefined;
242
- const category = (message) => inboxEntryCategory(message, actor, turn);
258
+ return (message) => inboxEntryCategory(message, actor, turn);
259
+ }
260
+ function currentGlobalInboxMessages(messages, name, sessions) {
261
+ const category = globalInboxCategory(name, sessions);
243
262
  return pendingGlobalInboxMessages(messages).filter(message => category(message) !== "history")
244
263
  .sort((a, b) => Number(category(b) === "current") - Number(category(a) === "current"));
245
264
  }
@@ -506,11 +525,14 @@ function roleSession(args, store, options) {
506
525
  const [command, rawName, ...tail] = args;
507
526
  if (command === "retry") {
508
527
  const name = roleName(rawName);
509
- const [action = "show", ...extra] = tail;
528
+ const parsed = readOptions(tail, ["--cursor"]);
529
+ const [action = "show", ...extra] = parsed.positionals;
510
530
  if (extra.length > 0 || !["show", "cancel", "disable", "enable"].includes(action)) {
511
531
  throw usageError("Usage: yui session retry <role> [show|cancel|disable|enable]");
512
532
  }
513
- return store.transaction(tx => {
533
+ if (action !== "show" && parsed.cursor !== undefined)
534
+ throw usageError("Only retry show accepts --cursor.");
535
+ return store[action === "show" ? "readTransaction" : "transaction"](tx => {
514
536
  const role = requireRole(name, tx);
515
537
  const sessions = tx.getGlobalRoleSessionSet(name);
516
538
  let binding = sessions?.providerBinding ?? null;
@@ -523,12 +545,15 @@ function roleSession(args, store, options) {
523
545
  }
524
546
  const health = globalSessionHealth(role, sessions);
525
547
  const historical = binding?.retry !== undefined && health.retry === null;
526
- return options.jsonOutput ? JSON.stringify({
548
+ const detail = {
527
549
  roleName: name, retry: providerRetryProjection(binding), disabled: binding?.retryDisabled ?? false,
528
550
  selectedNativeSessionId: health.nativeSessionId,
529
551
  retryScope: historical ? "historical-session" : "current-session"
530
- }) + "\n" : (historical ? "Historical Session evidence (not the selected Session's current failure): " : "")
531
- + renderProviderRetry(binding) + "\n";
552
+ };
553
+ return options.jsonOutput ? JSON.stringify(action === "show"
554
+ ? boundedDocument(detail, `global:${name}/retry`, parsed.cursor) : detail) + "\n"
555
+ : (historical ? "Historical Session evidence (not the selected Session's current failure): " : "")
556
+ + renderProviderRetry(binding) + "\n";
532
557
  });
533
558
  }
534
559
  if (command !== "record" && command !== "replace") {
@@ -715,7 +740,7 @@ function globalRoleMessage(args, store, options) {
715
740
  ["--request-id", false],
716
741
  ...(action === "steer" ? [["--expected-target", false]] : [])
717
742
  ]));
718
- const body = readCommandText(positionalBody, parsed.one("--body-file"), "--body", usage);
743
+ const body = readCommandText(positionalBody, parsed.one("--body-file"), "--body", usage, { preserveFileWhitespace: true });
719
744
  const requestId = required(parsed.one("--request-id"), "--request-id");
720
745
  const expectedTarget = action === "steer"
721
746
  ? required(parsed.one("--expected-target"), "--expected-target")