youmd 0.11.0 → 0.12.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 (176) hide show
  1. package/dist/commands/brain.d.ts.map +1 -1
  2. package/dist/commands/brain.js +65 -24
  3. package/dist/commands/brain.js.map +1 -1
  4. package/dist/commands/chat.d.ts.map +1 -1
  5. package/dist/commands/chat.js +6 -1
  6. package/dist/commands/chat.js.map +1 -1
  7. package/dist/commands/conversations.d.ts +5 -0
  8. package/dist/commands/conversations.d.ts.map +1 -0
  9. package/dist/commands/conversations.js +116 -0
  10. package/dist/commands/conversations.js.map +1 -0
  11. package/dist/commands/founder.d.ts +13 -0
  12. package/dist/commands/founder.d.ts.map +1 -0
  13. package/dist/commands/founder.js +189 -0
  14. package/dist/commands/founder.js.map +1 -0
  15. package/dist/commands/handoff.d.ts +5 -0
  16. package/dist/commands/handoff.d.ts.map +1 -0
  17. package/dist/commands/handoff.js +432 -0
  18. package/dist/commands/handoff.js.map +1 -0
  19. package/dist/commands/orchestrate.d.ts +15 -0
  20. package/dist/commands/orchestrate.d.ts.map +1 -1
  21. package/dist/commands/orchestrate.js +294 -0
  22. package/dist/commands/orchestrate.js.map +1 -1
  23. package/dist/commands/project.d.ts.map +1 -1
  24. package/dist/commands/project.js +8 -1
  25. package/dist/commands/project.js.map +1 -1
  26. package/dist/commands/reconcile.d.ts +15 -0
  27. package/dist/commands/reconcile.d.ts.map +1 -0
  28. package/dist/commands/reconcile.js +260 -0
  29. package/dist/commands/reconcile.js.map +1 -0
  30. package/dist/commands/session.d.ts +28 -0
  31. package/dist/commands/session.d.ts.map +1 -0
  32. package/dist/commands/session.js +895 -0
  33. package/dist/commands/session.js.map +1 -0
  34. package/dist/commands/sync.d.ts.map +1 -1
  35. package/dist/commands/sync.js +11 -0
  36. package/dist/commands/sync.js.map +1 -1
  37. package/dist/commands/tasks.d.ts +20 -0
  38. package/dist/commands/tasks.d.ts.map +1 -1
  39. package/dist/commands/tasks.js +90 -19
  40. package/dist/commands/tasks.js.map +1 -1
  41. package/dist/generated/capability-registry.d.ts +236 -76
  42. package/dist/generated/capability-registry.d.ts.map +1 -1
  43. package/dist/generated/capability-registry.js +260 -76
  44. package/dist/generated/capability-registry.js.map +1 -1
  45. package/dist/index.js +93 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/lib/api.d.ts +317 -2
  48. package/dist/lib/api.d.ts.map +1 -1
  49. package/dist/lib/api.js +155 -2
  50. package/dist/lib/api.js.map +1 -1
  51. package/dist/lib/brain/adapters.d.ts +20 -1
  52. package/dist/lib/brain/adapters.d.ts.map +1 -1
  53. package/dist/lib/brain/adapters.js +113 -2
  54. package/dist/lib/brain/adapters.js.map +1 -1
  55. package/dist/lib/brain/approval-key-trust.d.ts +29 -0
  56. package/dist/lib/brain/approval-key-trust.d.ts.map +1 -0
  57. package/dist/lib/brain/approval-key-trust.js +139 -0
  58. package/dist/lib/brain/approval-key-trust.js.map +1 -0
  59. package/dist/lib/brain/content.d.ts +7 -2
  60. package/dist/lib/brain/content.d.ts.map +1 -1
  61. package/dist/lib/brain/content.js +49 -14
  62. package/dist/lib/brain/content.js.map +1 -1
  63. package/dist/lib/brain/descriptor-validator.d.ts +11 -0
  64. package/dist/lib/brain/descriptor-validator.d.ts.map +1 -0
  65. package/dist/lib/brain/descriptor-validator.js +185 -0
  66. package/dist/lib/brain/descriptor-validator.js.map +1 -0
  67. package/dist/lib/brain/discovery.d.ts.map +1 -1
  68. package/dist/lib/brain/discovery.js +76 -50
  69. package/dist/lib/brain/discovery.js.map +1 -1
  70. package/dist/lib/brain/index.d.ts +1 -0
  71. package/dist/lib/brain/index.d.ts.map +1 -1
  72. package/dist/lib/brain/index.js +7 -2
  73. package/dist/lib/brain/index.js.map +1 -1
  74. package/dist/lib/brain/proposal.d.ts +53 -5
  75. package/dist/lib/brain/proposal.d.ts.map +1 -1
  76. package/dist/lib/brain/proposal.js +330 -94
  77. package/dist/lib/brain/proposal.js.map +1 -1
  78. package/dist/lib/brain/safe-file.d.ts +25 -1
  79. package/dist/lib/brain/safe-file.d.ts.map +1 -1
  80. package/dist/lib/brain/safe-file.js +250 -30
  81. package/dist/lib/brain/safe-file.js.map +1 -1
  82. package/dist/lib/brain/safety.d.ts.map +1 -1
  83. package/dist/lib/brain/safety.js +5 -0
  84. package/dist/lib/brain/safety.js.map +1 -1
  85. package/dist/lib/brain/staged-apply.d.ts +2 -1
  86. package/dist/lib/brain/staged-apply.d.ts.map +1 -1
  87. package/dist/lib/brain/staged-apply.js +6 -3
  88. package/dist/lib/brain/staged-apply.js.map +1 -1
  89. package/dist/lib/brain/store.d.ts +3 -0
  90. package/dist/lib/brain/store.d.ts.map +1 -1
  91. package/dist/lib/brain/store.js +68 -0
  92. package/dist/lib/brain/store.js.map +1 -1
  93. package/dist/lib/brain/sync.d.ts +48 -0
  94. package/dist/lib/brain/sync.d.ts.map +1 -1
  95. package/dist/lib/brain/sync.js +102 -0
  96. package/dist/lib/brain/sync.js.map +1 -1
  97. package/dist/lib/brain/types.d.ts +23 -0
  98. package/dist/lib/brain/types.d.ts.map +1 -1
  99. package/dist/lib/config.d.ts +7 -0
  100. package/dist/lib/config.d.ts.map +1 -1
  101. package/dist/lib/config.js +3 -0
  102. package/dist/lib/config.js.map +1 -1
  103. package/dist/lib/goalRegistryFile.d.ts +169 -0
  104. package/dist/lib/goalRegistryFile.d.ts.map +1 -0
  105. package/dist/lib/goalRegistryFile.js +518 -0
  106. package/dist/lib/goalRegistryFile.js.map +1 -0
  107. package/dist/lib/goalsFile.d.ts +101 -0
  108. package/dist/lib/goalsFile.d.ts.map +1 -0
  109. package/dist/lib/goalsFile.js +413 -0
  110. package/dist/lib/goalsFile.js.map +1 -0
  111. package/dist/lib/handoff.d.ts +170 -0
  112. package/dist/lib/handoff.d.ts.map +1 -0
  113. package/dist/lib/handoff.js +316 -0
  114. package/dist/lib/handoff.js.map +1 -0
  115. package/dist/lib/machine-identity.d.ts +2 -0
  116. package/dist/lib/machine-identity.d.ts.map +1 -1
  117. package/dist/lib/machine-identity.js +13 -6
  118. package/dist/lib/machine-identity.js.map +1 -1
  119. package/dist/lib/onboarding.d.ts +4 -1
  120. package/dist/lib/onboarding.d.ts.map +1 -1
  121. package/dist/lib/onboarding.js +11 -3
  122. package/dist/lib/onboarding.js.map +1 -1
  123. package/dist/lib/orchestrator/loop.d.ts.map +1 -1
  124. package/dist/lib/orchestrator/loop.js +8 -3
  125. package/dist/lib/orchestrator/loop.js.map +1 -1
  126. package/dist/lib/orchestrator/run-journal.d.ts +68 -3
  127. package/dist/lib/orchestrator/run-journal.d.ts.map +1 -1
  128. package/dist/lib/orchestrator/run-journal.js +391 -37
  129. package/dist/lib/orchestrator/run-journal.js.map +1 -1
  130. package/dist/lib/orchestrator/supervisor.d.ts +11 -0
  131. package/dist/lib/orchestrator/supervisor.d.ts.map +1 -1
  132. package/dist/lib/orchestrator/supervisor.js +304 -116
  133. package/dist/lib/orchestrator/supervisor.js.map +1 -1
  134. package/dist/lib/orchestrator/tools.d.ts.map +1 -1
  135. package/dist/lib/orchestrator/tools.js +76 -3
  136. package/dist/lib/orchestrator/tools.js.map +1 -1
  137. package/dist/lib/redact.d.ts.map +1 -1
  138. package/dist/lib/redact.js +31 -6
  139. package/dist/lib/redact.js.map +1 -1
  140. package/dist/lib/remote-agent-event.d.ts +19 -0
  141. package/dist/lib/remote-agent-event.d.ts.map +1 -0
  142. package/dist/lib/remote-agent-event.js +85 -0
  143. package/dist/lib/remote-agent-event.js.map +1 -0
  144. package/dist/lib/remote-command.d.ts.map +1 -1
  145. package/dist/lib/remote-command.js +19 -0
  146. package/dist/lib/remote-command.js.map +1 -1
  147. package/dist/lib/remote-executor.d.ts +7 -1
  148. package/dist/lib/remote-executor.d.ts.map +1 -1
  149. package/dist/lib/remote-executor.js +391 -0
  150. package/dist/lib/remote-executor.js.map +1 -1
  151. package/dist/lib/sessionCheckpoint.d.ts +104 -0
  152. package/dist/lib/sessionCheckpoint.d.ts.map +1 -0
  153. package/dist/lib/sessionCheckpoint.js +191 -0
  154. package/dist/lib/sessionCheckpoint.js.map +1 -0
  155. package/dist/lib/sessionHandoff.d.ts +47 -0
  156. package/dist/lib/sessionHandoff.d.ts.map +1 -0
  157. package/dist/lib/sessionHandoff.js +305 -0
  158. package/dist/lib/sessionHandoff.js.map +1 -0
  159. package/dist/lib/stream.d.ts +3 -1
  160. package/dist/lib/stream.d.ts.map +1 -1
  161. package/dist/lib/stream.js +8 -3
  162. package/dist/lib/stream.js.map +1 -1
  163. package/dist/lib/taskLedgerProposal.d.ts +2 -2
  164. package/dist/lib/taskLedgerProposal.d.ts.map +1 -1
  165. package/dist/lib/taskLedgerProposal.js +16 -8
  166. package/dist/lib/taskLedgerProposal.js.map +1 -1
  167. package/dist/lib/tasksFile.d.ts +14 -2
  168. package/dist/lib/tasksFile.d.ts.map +1 -1
  169. package/dist/lib/tasksFile.js +39 -5
  170. package/dist/lib/tasksFile.js.map +1 -1
  171. package/dist/mcp/registry.d.ts.map +1 -1
  172. package/dist/mcp/registry.js +110 -0
  173. package/dist/mcp/registry.js.map +1 -1
  174. package/native/prebuilds/darwin-universal/youmd_safe_open.node +0 -0
  175. package/package.json +4 -2
  176. package/scripts/smoke-safe-open-node.cjs +50 -0
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.founderOverviewSummary = founderOverviewSummary;
7
+ exports.founderReviewUrl = founderReviewUrl;
8
+ exports.founderCommand = founderCommand;
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const node_child_process_1 = require("node:child_process");
11
+ const api_1 = require("../lib/api");
12
+ const config_1 = require("../lib/config");
13
+ const render_1 = require("../lib/render");
14
+ const ACCENT = chalk_1.default.hex("#C46A3A");
15
+ const DIM = chalk_1.default.dim;
16
+ function requireAuth(json) {
17
+ if ((0, config_1.isAuthenticated)())
18
+ return true;
19
+ if (json)
20
+ console.log(JSON.stringify({ ok: false, error: "not_authenticated" }));
21
+ else {
22
+ console.log("");
23
+ console.log(" " + chalk_1.default.yellow("not authenticated") + DIM(" — run ") + chalk_1.default.cyan("you login"));
24
+ console.log("");
25
+ }
26
+ return false;
27
+ }
28
+ function record(value) {
29
+ return value && typeof value === "object" && !Array.isArray(value)
30
+ ? value
31
+ : {};
32
+ }
33
+ function list(value) {
34
+ return Array.isArray(value) ? value : [];
35
+ }
36
+ function founderOverviewSummary(overview) {
37
+ const founder = record(overview.founder);
38
+ const mission = record(founder.mission);
39
+ const missionRevision = record(mission.revision);
40
+ const goals = record(overview.goals);
41
+ const reconciler = record(overview.reconciler);
42
+ return {
43
+ mission: String(missionRevision.content
44
+ ?? mission.reason
45
+ ?? mission.status
46
+ ?? "review needed"),
47
+ businesses: list(overview.businesses).length,
48
+ independentProjects: list(overview.independentProjects).length,
49
+ goals: list(goals.flat).length,
50
+ openConflicts: list(reconciler.openConflicts).length,
51
+ };
52
+ }
53
+ function founderReviewUrl(revisionRef, appUrl = (0, config_1.getAppUrl)()) {
54
+ if (!/^vision:[a-z0-9][a-z0-9:._-]{2,239}$/i.test(revisionRef)) {
55
+ throw new Error("revisionRef must be a canonical vision:* reference");
56
+ }
57
+ const url = new URL("/shell", appUrl);
58
+ url.searchParams.set("view", "businesses");
59
+ url.searchParams.set("review", revisionRef);
60
+ return url.toString();
61
+ }
62
+ function openUrl(url) {
63
+ const [binary, args] = process.platform === "darwin"
64
+ ? ["open", [url]]
65
+ : process.platform === "win32"
66
+ ? ["cmd", ["/c", "start", "", url]]
67
+ : ["xdg-open", [url]];
68
+ (0, node_child_process_1.execFile)(binary, args, { windowsHide: true }, () => {
69
+ // The URL is always printed, so a missing platform opener is non-fatal.
70
+ });
71
+ }
72
+ async function founderOverviewCommand(options) {
73
+ if (!requireAuth(options.json))
74
+ return;
75
+ const spinner = options.json ? null : new render_1.BrailleSpinner("assembling the founder control plane...");
76
+ spinner?.start();
77
+ const response = await (0, api_1.getFounderOverview)();
78
+ if (!response.ok) {
79
+ spinner?.fail("Founder OS unavailable");
80
+ const error = (0, api_1.apiErrorMessage)(response.data) ?? `HTTP ${response.status}`;
81
+ if (options.json)
82
+ console.log(JSON.stringify({ ok: false, error }));
83
+ else
84
+ console.log(" " + chalk_1.default.red(error));
85
+ return;
86
+ }
87
+ spinner?.stop("Founder OS current");
88
+ if (options.json) {
89
+ console.log(JSON.stringify({ ok: true, ...response.data }, null, 2));
90
+ return;
91
+ }
92
+ const overview = record(response.data.overview);
93
+ const summary = founderOverviewSummary(overview);
94
+ console.log("");
95
+ console.log(" " + ACCENT("founder os"));
96
+ console.log(" " + DIM("mission: ") + summary.mission);
97
+ console.log(" " + DIM("portfolio: ")
98
+ + `${summary.businesses} businesses · ${summary.independentProjects} independent projects`);
99
+ console.log(" " + DIM("goals: ")
100
+ + `${summary.goals} · `
101
+ + DIM("open conflicts: ")
102
+ + String(summary.openConflicts));
103
+ console.log("");
104
+ }
105
+ async function founderMigrateCommand(options) {
106
+ if (!requireAuth(options.json))
107
+ return;
108
+ const spinner = options.json ? null : new render_1.BrailleSpinner("reconciling the legacy founder graph...");
109
+ spinner?.start();
110
+ const response = await (0, api_1.migrateFounderPortfolio)();
111
+ if (!response.ok) {
112
+ spinner?.fail("migration refused");
113
+ const error = (0, api_1.apiErrorMessage)(response.data) ?? `HTTP ${response.status}`;
114
+ if (options.json)
115
+ console.log(JSON.stringify({ ok: false, error }));
116
+ else
117
+ console.log(" " + chalk_1.default.red(error));
118
+ return;
119
+ }
120
+ spinner?.stop("canonical founder graph reconciled");
121
+ if (options.json)
122
+ console.log(JSON.stringify({ ok: true, ...response.data }, null, 2));
123
+ else {
124
+ console.log("");
125
+ console.log(" " + DIM("history preserved; no mission, metric, or goal was invented"));
126
+ console.log("");
127
+ }
128
+ }
129
+ function founderReviewCommand(revisionRef, options) {
130
+ if (!revisionRef) {
131
+ const error = "revisionRef is required";
132
+ if (options.json)
133
+ console.log(JSON.stringify({ ok: false, error }));
134
+ else
135
+ console.log("\n " + chalk_1.default.yellow(error) + DIM(" — use you founder review vision:...\n"));
136
+ return;
137
+ }
138
+ try {
139
+ const url = founderReviewUrl(revisionRef);
140
+ openUrl(url);
141
+ if (options.json) {
142
+ console.log(JSON.stringify({
143
+ ok: true,
144
+ reviewUrl: url,
145
+ revisionRef,
146
+ decisionRequiresHumanClick: true,
147
+ secretValuesExposed: false,
148
+ }, null, 2));
149
+ return;
150
+ }
151
+ console.log("");
152
+ console.log(" " + ACCENT("human review opened"));
153
+ console.log(" " + DIM("revision: ") + revisionRef);
154
+ console.log(" " + DIM("accept or reject only after inspecting the exact timeline and diff"));
155
+ console.log(" " + chalk_1.default.cyan(url));
156
+ console.log("");
157
+ }
158
+ catch (error) {
159
+ const message = error instanceof Error ? error.message : "invalid revisionRef";
160
+ if (options.json)
161
+ console.log(JSON.stringify({ ok: false, error: message }));
162
+ else
163
+ console.log("\n " + chalk_1.default.red(message) + "\n");
164
+ }
165
+ }
166
+ async function founderCommand(subcommand, args = [], options = {}) {
167
+ switch (subcommand) {
168
+ case undefined:
169
+ case "overview":
170
+ case "status":
171
+ return founderOverviewCommand(options);
172
+ case "migrate":
173
+ return founderMigrateCommand(options);
174
+ case "review":
175
+ case "decide":
176
+ return founderReviewCommand(args[0], options);
177
+ default:
178
+ if (options.json) {
179
+ console.log(JSON.stringify({ ok: false, error: `unknown subcommand: ${subcommand}` }));
180
+ }
181
+ else {
182
+ console.log("");
183
+ console.log(" " + chalk_1.default.yellow(`unknown subcommand: ${subcommand}`));
184
+ console.log(" " + DIM("try: ") + chalk_1.default.cyan("you founder overview | migrate | review <vision:ref>"));
185
+ console.log("");
186
+ }
187
+ }
188
+ }
189
+ //# sourceMappingURL=founder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"founder.js","sourceRoot":"","sources":["../../src/commands/founder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export interface HandoffOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function handoffCommand(subcommand: string | undefined, options?: HandoffOptions): Promise<void>;
5
+ //# sourceMappingURL=handoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff.d.ts","sourceRoot":"","sources":["../../src/commands/handoff.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAoVD,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqEhH"}
@@ -0,0 +1,432 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.handoffCommand = handoffCommand;
40
+ const os = __importStar(require("os"));
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const api_1 = require("../lib/api");
43
+ const config_1 = require("../lib/config");
44
+ const remote_command_1 = require("../lib/remote-command");
45
+ const remote_executor_1 = require("../lib/remote-executor");
46
+ const supervisor_1 = require("../lib/orchestrator/supervisor");
47
+ const handoff_1 = require("../lib/handoff");
48
+ const render_1 = require("../lib/render");
49
+ const machine_identity_1 = require("../lib/machine-identity");
50
+ const ACCENT = chalk_1.default.hex("#C46A3A");
51
+ const DIM = chalk_1.default.dim;
52
+ async function runFleetAction(host, action, args = {}, timeoutMs = 30000, trustedLocal = false) {
53
+ if (trustedLocal) {
54
+ return (0, remote_executor_1.executeRemoteAction)({ action, args, trustedLocal: true });
55
+ }
56
+ const dispatched = await (0, remote_command_1.dispatchRemoteCommand)({
57
+ machine: host,
58
+ action,
59
+ args,
60
+ sourceAgent: "you handoff orchestrator",
61
+ message: `${action}${typeof args.project === "string" ? ` ${args.project}` : ""}`,
62
+ });
63
+ if (!dispatched.ok) {
64
+ return {
65
+ ok: false,
66
+ action,
67
+ exitCode: null,
68
+ output: "",
69
+ error: dispatched.error,
70
+ status: "error",
71
+ secretValuesExposed: false,
72
+ };
73
+ }
74
+ const result = await (0, remote_command_1.pollForResult)({ requestId: dispatched.data.requestId, timeoutMs });
75
+ if (!result) {
76
+ return {
77
+ ok: false,
78
+ action,
79
+ exitCode: null,
80
+ output: "",
81
+ error: "no coordinator receipt before the bounded timeout",
82
+ status: "error",
83
+ secretValuesExposed: false,
84
+ };
85
+ }
86
+ return { ...result, gitState: result.gitState };
87
+ }
88
+ async function mapBounded(items, limit, fn) {
89
+ const results = new Array(items.length);
90
+ let cursor = 0;
91
+ const worker = async () => {
92
+ while (cursor < items.length) {
93
+ const index = cursor++;
94
+ results[index] = await fn(items[index]);
95
+ }
96
+ };
97
+ await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()));
98
+ return results;
99
+ }
100
+ function parseRemoteWorkers(host, output) {
101
+ if (!output.trim() || /\bno workers\b/i.test(output))
102
+ return [];
103
+ return output.split("\n").flatMap((line) => {
104
+ const match = line.match(/^(w_[A-Za-z0-9]+) \[([^\]]+)\] (\S+) (\S+)/);
105
+ if (!match)
106
+ return [];
107
+ const status = ["running", "exited", "failed", "stopped"].includes(match[2])
108
+ ? match[2]
109
+ : "unknown";
110
+ return [{ id: match[1], host, status, harness: match[3], project: match[4] === "-" ? undefined : match[4] }];
111
+ });
112
+ }
113
+ async function inventoryFleet() {
114
+ const [proofsResult, graphResult] = await Promise.all([
115
+ (0, api_1.getMachineProofs)({ limit: 50 }),
116
+ (0, api_1.getPortfolioGraph)(),
117
+ ]);
118
+ if (!proofsResult.ok || !proofsResult.data) {
119
+ throw new Error(`machine inventory unavailable (HTTP ${proofsResult.status || "unknown"})`);
120
+ }
121
+ if (!graphResult.ok || !graphResult.data) {
122
+ throw new Error(`project inventory unavailable (HTTP ${graphResult.status || "unknown"})`);
123
+ }
124
+ const localMachineKey = (0, machine_identity_1.readPhysicalMachineKey)();
125
+ const latest = new Map();
126
+ for (const proof of proofsResult.data.machines) {
127
+ const key = proof.machineKey;
128
+ const seen = latest.get(key);
129
+ if (!seen || proof.updatedAt > seen.updatedAt)
130
+ latest.set(key, proof);
131
+ }
132
+ const ambiguousHosts = (0, handoff_1.findAmbiguousMachineHosts)([...latest.values()].map((proof) => ({ machineKey: proof.machineKey, host: proof.hostName })));
133
+ if (!localMachineKey || !latest.has(localMachineKey)) {
134
+ const syntheticKey = localMachineKey || "unregistered-local-machine";
135
+ latest.set(syntheticKey, {
136
+ _id: "local",
137
+ machineKey: syntheticKey,
138
+ hostName: os.hostname(),
139
+ rootDir: process.cwd(),
140
+ status: "local",
141
+ scanned: 0,
142
+ ready: 0,
143
+ needsEnv: 0,
144
+ partial: 0,
145
+ installPassed: 0,
146
+ checksPassed: 0,
147
+ serversPassed: 0,
148
+ failures: 0,
149
+ warnings: [],
150
+ secretValuesExposed: false,
151
+ source: "you handoff",
152
+ generatedAt: Date.now(),
153
+ updatedAt: Date.now(),
154
+ });
155
+ }
156
+ const machines = await mapBounded([...latest.values()], 6, async (proof) => {
157
+ const isLocal = Boolean(localMachineKey && proof.machineKey === localMachineKey);
158
+ const ambiguousHost = ambiguousHosts.has(proof.hostName.toLowerCase());
159
+ if (ambiguousHost) {
160
+ return {
161
+ machineKey: proof.machineKey,
162
+ host: proof.hostName,
163
+ isLocal,
164
+ online: false,
165
+ managed: false,
166
+ lastSeenAt: proof.updatedAt,
167
+ note: "hostname maps to multiple stable machine keys; remote target is ambiguous",
168
+ };
169
+ }
170
+ if (isLocal) {
171
+ return { machineKey: proof.machineKey, host: proof.hostName, isLocal: true, online: true, managed: true, lastSeenAt: proof.updatedAt };
172
+ }
173
+ if (proof.machineKey === "unregistered-local-machine") {
174
+ return {
175
+ machineKey: proof.machineKey,
176
+ host: proof.hostName,
177
+ isLocal: false,
178
+ online: false,
179
+ managed: false,
180
+ lastSeenAt: proof.updatedAt,
181
+ note: "local stable machine identity is not registered; run machine sync before handoff",
182
+ };
183
+ }
184
+ const status = await runFleetAction(proof.hostName, "agent.status", {}, 15000);
185
+ return {
186
+ machineKey: proof.machineKey,
187
+ host: proof.hostName,
188
+ isLocal: false,
189
+ online: status.ok,
190
+ managed: true,
191
+ lastSeenAt: proof.updatedAt,
192
+ note: status.ok ? undefined : status.error || "daemon did not answer",
193
+ };
194
+ });
195
+ const projects = graphResult.data.projects.map((project) => {
196
+ const handoffProject = {
197
+ slug: project.slug || project.name,
198
+ directoryName: project.directoryName || project.repoName || project.slug || project.name,
199
+ repoFullName: project.repoFullName,
200
+ repoUrl: project.repoUrl,
201
+ };
202
+ return { ...handoffProject, repoIdentity: (0, handoff_1.projectRemoteIdentity)(handoffProject) };
203
+ });
204
+ const workers = [];
205
+ for (const machine of machines) {
206
+ if (!machine.online)
207
+ continue;
208
+ if (machine.isLocal) {
209
+ workers.push(...(0, supervisor_1.refreshWorkers)().map((worker) => ({
210
+ id: worker.id,
211
+ host: machine.host,
212
+ project: worker.project,
213
+ status: worker.status,
214
+ harness: worker.harness,
215
+ })));
216
+ continue;
217
+ }
218
+ const listed = await runFleetAction(machine.host, "agent.list", {}, 20000);
219
+ if (listed.ok)
220
+ workers.push(...parseRemoteWorkers(machine.host, listed.output));
221
+ else {
222
+ machine.managed = false;
223
+ machine.note = [machine.note, `worker registry unavailable: ${listed.error || listed.status}`].filter(Boolean).join("; ");
224
+ }
225
+ }
226
+ const probes = machines.flatMap((machine) => projects.map((project) => ({ machine, project })));
227
+ const repos = await mapBounded(probes, 6, async ({ machine, project }) => {
228
+ if (!machine.online)
229
+ return { machineKey: machine.machineKey, host: machine.host, project: project.slug, availability: "offline" };
230
+ const result = await runFleetAction(machine.host, "git.status", { project: project.directoryName }, 25000, machine.isLocal);
231
+ if (!result.ok) {
232
+ const unmanaged = /not found|known You\.md project root|managed/i.test(result.error || result.output);
233
+ return {
234
+ host: machine.host,
235
+ machineKey: machine.machineKey,
236
+ project: project.slug,
237
+ availability: unmanaged ? "unmanaged" : "error",
238
+ note: result.error || result.output,
239
+ };
240
+ }
241
+ return {
242
+ host: machine.host,
243
+ machineKey: machine.machineKey,
244
+ project: project.slug,
245
+ availability: "managed",
246
+ dirty: result.gitState?.dirty || false,
247
+ branch: result.gitState?.branch ?? null,
248
+ ahead: result.gitState?.ahead || 0,
249
+ behind: result.gitState?.behind || 0,
250
+ headOid: result.gitState?.headOid ?? null,
251
+ upstream: result.gitState?.upstream ?? null,
252
+ upstreamOid: result.gitState?.upstreamOid ?? null,
253
+ remoteIdentity: result.gitState?.remoteIdentity ?? null,
254
+ };
255
+ });
256
+ return { machines, projects, workers, repos };
257
+ }
258
+ function actionLabel(action) {
259
+ if (action.kind === "worker_state_receipt")
260
+ return `${action.host}: record unverified state for ${action.workerIds.length} registered worker(s)`;
261
+ if (action.kind === "push_clean")
262
+ return `${action.host}/${action.project}: push exact clean HEAD`;
263
+ if (action.kind === "pull_ff_only")
264
+ return `${action.host}/${action.project}: git pull --ff-only`;
265
+ if (action.kind === "machine_sync")
266
+ return `${action.host}: sync identity, skills, and project context`;
267
+ if (action.kind === "block")
268
+ return `${action.hosts?.join(", ") || action.project || "fleet"}: ${action.reason}`;
269
+ return `${action.host || action.project || "fleet"}: ${action.reason}`;
270
+ }
271
+ async function executePlan(plan, inventory, json) {
272
+ if (!plan.safeToRun) {
273
+ return [{
274
+ action: "handoff.blocked",
275
+ host: os.hostname(),
276
+ ok: false,
277
+ status: "blocked",
278
+ error: plan.blockingReasons.join("; ") || "handoff plan is not safe to execute",
279
+ secretValuesExposed: false,
280
+ }];
281
+ }
282
+ const guarded = await (0, handoff_1.executeGuardedHandoffPlan)(plan, async (item) => {
283
+ let action;
284
+ let args = {};
285
+ let project;
286
+ if (item.kind === "worker_state_receipt")
287
+ action = "handoff.checkpoint";
288
+ else if (item.kind === "push_clean") {
289
+ action = "handoff.push_clean";
290
+ project = item.project;
291
+ args = {
292
+ project: item.target,
293
+ expectedHead: item.expectedHead,
294
+ expectedBranch: item.expectedBranch,
295
+ expectedUpstream: item.expectedUpstream,
296
+ expectedUpstreamOid: item.expectedUpstreamOid,
297
+ expectedRemoteIdentity: item.expectedRemoteIdentity,
298
+ expectedFinalOid: item.expectedFinalOid,
299
+ };
300
+ }
301
+ else if (item.kind === "pull_ff_only") {
302
+ action = "handoff.pull_clean";
303
+ project = item.project;
304
+ args = {
305
+ project: item.target,
306
+ expectedHead: item.expectedHead,
307
+ expectedBranch: item.expectedBranch,
308
+ expectedUpstream: item.expectedUpstream,
309
+ expectedUpstreamOid: item.expectedUpstreamOid,
310
+ expectedRemoteIdentity: item.expectedRemoteIdentity,
311
+ expectedFinalOid: item.expectedFinalOid,
312
+ };
313
+ }
314
+ else
315
+ action = "handoff.sync";
316
+ const spinner = json ? null : new render_1.BrailleSpinner(actionLabel(item));
317
+ spinner?.start();
318
+ const machine = inventory.machines.find((candidate) => candidate.machineKey === item.machineKey);
319
+ if (!machine) {
320
+ return { action, host: item.host, project, ok: false, status: "blocked", error: "stable machine identity disappeared after planning", secretValuesExposed: false };
321
+ }
322
+ const result = await runFleetAction(item.host, action, args, action === "handoff.sync" || action === "handoff.push_clean" ? 380000 : 120000, machine.isLocal);
323
+ if (result.ok)
324
+ spinner?.stop(chalk_1.default.green(actionLabel(item)));
325
+ else
326
+ spinner?.fail(`${actionLabel(item)} — ${result.error || result.status}`);
327
+ return {
328
+ action,
329
+ host: item.host,
330
+ project,
331
+ ok: result.ok,
332
+ status: result.status,
333
+ output: result.output || undefined,
334
+ error: result.error,
335
+ gitState: result.gitState,
336
+ secretValuesExposed: false,
337
+ };
338
+ });
339
+ return guarded.map((receipt) => receipt.result);
340
+ }
341
+ function usage() {
342
+ console.log("");
343
+ console.log(" " + ACCENT("you handoff") + DIM(" — put the fleet at an honest stopping point"));
344
+ console.log("");
345
+ console.log(" " + chalk_1.default.cyan("you handoff") + DIM(" run the guarded handoff"));
346
+ console.log(" " + chalk_1.default.cyan("you handoff run") + DIM(" same, explicit"));
347
+ console.log(" " + chalk_1.default.cyan("you handoff plan --json") + DIM(" read-only machine plan"));
348
+ console.log("");
349
+ console.log(DIM(" Registered worker state is receipted without signals; active work remains unverified until its agent checks in."));
350
+ console.log(DIM(" Arbitrary Codex/Claude/Cursor chats are reported as unmanaged, never invented."));
351
+ console.log(DIM(" Dream-cycle scheduling is deferred until it has an explicit, testable opt-in."));
352
+ console.log("");
353
+ }
354
+ async function handoffCommand(subcommand, options = {}) {
355
+ const mode = !subcommand || subcommand === "run" ? "run" : subcommand === "plan" || subcommand === "status" ? "plan" : null;
356
+ if (subcommand === "help" || subcommand === "--help" || !mode)
357
+ return usage();
358
+ if (!(0, config_1.isAuthenticated)()) {
359
+ const message = "not authenticated — run `you login` before coordinating the fleet";
360
+ if (options.json)
361
+ console.log(JSON.stringify({ ok: false, error: message, contract: handoff_1.HANDOFF_CONTRACT }));
362
+ else
363
+ console.log("\n " + chalk_1.default.yellow(message) + "\n");
364
+ process.exitCode = 1;
365
+ return;
366
+ }
367
+ const spinner = options.json ? null : new render_1.BrailleSpinner("asking the You Agent orchestrator for the whole fleet...");
368
+ spinner?.start();
369
+ let inventory;
370
+ try {
371
+ inventory = await inventoryFleet();
372
+ }
373
+ catch (error) {
374
+ const message = error instanceof Error ? error.message : String(error);
375
+ spinner?.fail(`fleet inventory failed — ${message}`);
376
+ if (options.json)
377
+ console.log(JSON.stringify({ ok: false, mode, contract: handoff_1.HANDOFF_CONTRACT, error: message, results: [] }, null, 2));
378
+ else
379
+ console.log("\n " + ACCENT("handoff blocked") + " " + DIM(message) + "\n");
380
+ process.exitCode = 1;
381
+ return;
382
+ }
383
+ const plan = (0, handoff_1.buildHandoffPlan)(inventory);
384
+ spinner?.stop(`inventoried ${inventory.machines.length} machines, ${inventory.projects.length} projects, ${inventory.workers.length} workers`);
385
+ if (mode === "plan") {
386
+ if (options.json) {
387
+ console.log(JSON.stringify({ ok: plan.safeToRun, mode, contract: handoff_1.HANDOFF_CONTRACT, goal: (0, handoff_1.buildHandoffGoal)(mode), inventory, plan }, null, 2));
388
+ }
389
+ else {
390
+ console.log("");
391
+ for (const action of plan.actions)
392
+ console.log(" " + DIM(action.kind.padEnd(16)) + actionLabel(action));
393
+ console.log("");
394
+ }
395
+ if (!plan.safeToRun)
396
+ process.exitCode = 1;
397
+ return;
398
+ }
399
+ const results = await executePlan(plan, inventory, Boolean(options.json));
400
+ const ok = results.every((result) => result.ok) && plan.safeToRun;
401
+ try {
402
+ await (0, api_1.recordBrainActivity)({
403
+ source: "you-handoff",
404
+ channel: "orchestrator",
405
+ kind: "fleet-handoff",
406
+ title: ok ? "fleet handoff completed" : "fleet handoff needs attention",
407
+ detail: `${inventory.machines.length} machines; ${inventory.projects.length} projects; ${plan.conflicts.length} dirty conflicts; ${plan.offlineHosts.length} offline`,
408
+ status: ok ? "ok" : "warn",
409
+ sourceHost: os.hostname(),
410
+ sourceAgent: "you handoff orchestrator",
411
+ metadata: { schemaVersion: plan.schemaVersion, secretValuesExposed: false },
412
+ });
413
+ }
414
+ catch {
415
+ // The durable local/remote receipts remain the source of truth.
416
+ }
417
+ if (options.json) {
418
+ console.log(JSON.stringify({ ok, mode, contract: handoff_1.HANDOFF_CONTRACT, goal: (0, handoff_1.buildHandoffGoal)(mode), inventory, plan, results }, null, 2));
419
+ }
420
+ else {
421
+ console.log("");
422
+ console.log(" " + (ok ? chalk_1.default.green("handoff complete") : ACCENT("handoff needs attention")));
423
+ console.log(" " + DIM(`${plan.conflicts.length} conflicts · ${plan.offlineHosts.length} offline · ${plan.unmanaged.length} unmanaged clones`));
424
+ for (const action of plan.actions.filter((item) => item.kind === "block" || item.kind === "report")) {
425
+ console.log(" " + chalk_1.default.yellow(action.kind) + " " + actionLabel(action));
426
+ }
427
+ console.log("");
428
+ }
429
+ if (!ok)
430
+ process.exitCode = 1;
431
+ }
432
+ //# sourceMappingURL=handoff.js.map