@zq-silk/yui 0.8.9 → 0.10.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 (51) hide show
  1. package/ARCHITECTURE.md +48 -46
  2. package/README.md +72 -42
  3. package/dist/cli/commandCatalog.js +16 -8
  4. package/dist/cli.js +27 -32
  5. package/dist/commands/executionAuditCommands.js +2 -2
  6. package/dist/commands/globalRoleCommands.js +0 -12
  7. package/dist/commands/sessionCommands.js +116 -0
  8. package/dist/commands/taskBaseCommands.js +1 -11
  9. package/dist/commands/taskCommands.js +123 -340
  10. package/dist/commands/taskCompletionGate.js +15 -12
  11. package/dist/commands/taskContextCommand.js +18 -11
  12. package/dist/commands/taskNextActionCommand.js +4 -5
  13. package/dist/commands/taskWorkspaceCommands.js +2 -2
  14. package/dist/controller/clientRuntime.js +65 -0
  15. package/dist/controller/fileSchedulerStoreAdapter.js +2 -49
  16. package/dist/doctor/doctor.js +16 -12
  17. package/dist/execution/executionGroup.js +0 -3
  18. package/dist/executor/agentAdapter.js +39 -42
  19. package/dist/executor/agentExecutor.js +4 -2
  20. package/dist/executor/codexConfigConflict.js +40 -16
  21. package/dist/executor/effectiveLaunch.js +33 -3
  22. package/dist/executor/fileRoleLaunchPlanner.js +15 -24
  23. package/dist/integration/deliveryObligation.js +72 -0
  24. package/dist/integration/gitIntegrationService.js +1 -1
  25. package/dist/lifecycle/exactRunTerminalization.js +12 -8
  26. package/dist/observability/orchestrationMetrics.js +12 -26
  27. package/dist/profile/agentProfile.js +1 -1
  28. package/dist/repository/taskBaseFreshness.js +5 -11
  29. package/dist/repository/taskWorkspaceCoordinator.js +2 -0
  30. package/dist/repository/taskWorkspacePreparer.js +173 -26
  31. package/dist/review/reviewRound.js +41 -24
  32. package/dist/role/role.js +0 -9
  33. package/dist/runtime/{firstProgressStopLoss.js → firstProgressAdvisory.js} +7 -21
  34. package/dist/scheduler/leaderWakeupProcessor.js +0 -25
  35. package/dist/setup/setupCommand.js +0 -5
  36. package/dist/storage/migration/productionRegistry.js +138 -0
  37. package/dist/storage/sqliteStore.js +2 -1
  38. package/dist/storage/taskStore.js +27 -27
  39. package/dist/storage/upgrade/upgradeOrchestrator.js +35 -7
  40. package/dist/task/completionReadiness.js +35 -25
  41. package/dist/task/nextAction.js +70 -78
  42. package/dist/task/task.js +12 -19
  43. package/dist/web/assets/client/components.js +3 -1
  44. package/dist/web/assets/client/i18n.js +6 -0
  45. package/dist/web/webSnapshot.js +0 -3
  46. package/i18n/README.zh-CN.md +33 -24
  47. package/package.json +1 -1
  48. package/skills/yui-leader/SKILL.md +55 -52
  49. package/skills/yui-operator/SKILL.md +31 -40
  50. package/skills/yui-reviewer/SKILL.md +18 -12
  51. package/skills/yui-worker/SKILL.md +5 -3
@@ -1,5 +1,121 @@
1
1
  import { usageError } from "../errors/cliError.js";
2
2
  import { defaultTableWidth, renderTable } from "../output/table.js";
3
+ export function parseSessionStopOptions(args) {
4
+ if (args.length !== 1 || args[0] !== "--all") {
5
+ throw usageError("Session stop usage: yui session stop --all.");
6
+ }
7
+ return { all: true };
8
+ }
9
+ /**
10
+ * Stop every current managed Session only when all of them are idle. The
11
+ * all-or-nothing preflight prevents a maintenance command from silently
12
+ * stopping half the topology while another Role is still working.
13
+ */
14
+ export async function runSessionStopCommand(input) {
15
+ void input.options;
16
+ if (input.environment?.YUI_SESSION_SCOPE !== undefined) {
17
+ throw usageError("Session stop must be run by the user from a normal shell, outside a managed Yui Session.");
18
+ }
19
+ const maintenance = input.runtime.beginMaintenance();
20
+ let completed = false;
21
+ try {
22
+ const initial = input.runtime.snapshot();
23
+ const initiallyBlocked = blockedSessions(initial);
24
+ if (initiallyBlocked.length > 0)
25
+ return blockedStopResult(initiallyBlocked);
26
+ // Stop and drain the Controller while the handover fence prevents a new
27
+ // Leader dispatch. The explicit full pass settles pending runtime inbox and
28
+ // lifecycle work that may exist without a current Session candidate.
29
+ await input.runtime.drainController();
30
+ await input.runtime.stopController();
31
+ // Re-read the authoritative facts after the drain because a Run that was
32
+ // already inside a pass may have changed state meanwhile.
33
+ const settled = input.runtime.snapshot();
34
+ const blockedAfterDrain = blockedSessions(settled);
35
+ if (blockedAfterDrain.length > 0) {
36
+ await input.runtime.startController();
37
+ return blockedStopResult(blockedAfterDrain);
38
+ }
39
+ for (const session of settled.candidates) {
40
+ const candidate = settled.dormant.find((entry) => sameStopCandidate(session, entry));
41
+ if (candidate === undefined) {
42
+ throw new Error(`Dormant Session changed during maintenance: ${renderSessionOwner(session)}.`);
43
+ }
44
+ await input.runtime.stopDormantSession(candidate);
45
+ }
46
+ const count = settled.candidates.length;
47
+ completed = true;
48
+ return {
49
+ output: count === 0
50
+ ? "No managed Sessions were running. The Controller remains stopped; run `yui update` now.\n"
51
+ : `Stopped ${count} managed Sessions. The Controller remains stopped; run \`yui update\` now.\n`,
52
+ data: { stopped: settled.candidates, blocked: [] },
53
+ exitCode: 0
54
+ };
55
+ }
56
+ catch (error) {
57
+ if (!completed) {
58
+ try {
59
+ await input.runtime.startController();
60
+ }
61
+ catch (restartError) {
62
+ throw new AggregateError([error, restartError], "Session maintenance failed and the Controller could not be restarted.");
63
+ }
64
+ }
65
+ throw error;
66
+ }
67
+ finally {
68
+ maintenance.release();
69
+ }
70
+ }
71
+ function blockedSessions(input) {
72
+ return input.candidates.flatMap((session) => {
73
+ const idle = input.dormant.some((candidate) => sameStopCandidate(session, candidate));
74
+ if (idle)
75
+ return [];
76
+ return [{
77
+ session,
78
+ reason: session.status === "running"
79
+ ? "running"
80
+ : "runtime-work-pending"
81
+ }];
82
+ });
83
+ }
84
+ function blockedStopResult(blocked) {
85
+ const details = blocked.map(({ session, reason }) => (`- ${renderSessionOwner(session)} (${reason === "running"
86
+ ? "a Turn or Run is still running"
87
+ : "an active Run or lifecycle operation is still pending"})`));
88
+ return {
89
+ output: [
90
+ `Cannot stop managed Sessions: ${blocked.length} Session(s) are still busy.`,
91
+ ...details,
92
+ "No Session was stopped. Let the listed work finish, then run `yui session stop --all` again."
93
+ ].join("\n") + "\n",
94
+ data: { stopped: [], blocked },
95
+ exitCode: 5
96
+ };
97
+ }
98
+ function sameStopCandidate(session, candidate) {
99
+ if (session.owner.scope !== candidate.owner.scope)
100
+ return false;
101
+ if (session.owner.roleName !== candidate.owner.roleName)
102
+ return false;
103
+ if (session.owner.scope === "task"
104
+ && candidate.owner.scope === "task"
105
+ && session.owner.taskId !== candidate.owner.taskId) {
106
+ return false;
107
+ }
108
+ return session.agentId === candidate.agentId
109
+ && session.adapterId === candidate.adapterId
110
+ && session.nativeSessionId === candidate.nativeSessionId
111
+ && session.launchId === candidate.launchId
112
+ && session.sessionUpdatedAt === candidate.sessionUpdatedAt;
113
+ }
114
+ function renderSessionOwner(session) {
115
+ return session.owner.scope === "task"
116
+ ? `${session.owner.taskId}/${session.owner.roleName}`
117
+ : `global/${session.owner.roleName}`;
118
+ }
3
119
  export function parseSessionReconcileOptions(args) {
4
120
  const allowed = new Set(["--report", "--cleanup"]);
5
121
  if (args.some((argument) => !allowed.has(argument))) {
@@ -1,5 +1,5 @@
1
1
  import { usageError } from "../errors/cliError.js";
2
- import { assertTaskBaseFreshnessForCompletion, inspectTaskBaseFreshness, renderTaskBaseFreshnessReport } from "../repository/taskBaseFreshness.js";
2
+ import { inspectTaskBaseFreshness, renderTaskBaseFreshnessReport } from "../repository/taskBaseFreshness.js";
3
3
  export async function runTaskBaseStatusCommand(args, store, options = {}) {
4
4
  const usage = "Task base status usage: yui task base status <task> [--refresh].";
5
5
  const refresh = args.includes("--refresh");
@@ -11,19 +11,9 @@ export async function runTaskBaseStatusCommand(args, store, options = {}) {
11
11
  git: options.git,
12
12
  refresh
13
13
  });
14
- assertReportIsDeliverySafe(report);
15
14
  return {
16
15
  kind: "output",
17
16
  output: renderTaskBaseFreshnessReport(report),
18
17
  data: report
19
18
  };
20
19
  }
21
- function assertReportIsDeliverySafe(report) {
22
- try {
23
- assertTaskBaseFreshnessForCompletion(report);
24
- }
25
- catch (error) {
26
- const message = error instanceof Error ? error.message : String(error);
27
- throw usageError(`${renderTaskBaseFreshnessReport(report)}${message}`);
28
- }
29
- }