youmd 0.11.0 → 0.13.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 (216) hide show
  1. package/dist/commands/brain.d.ts.map +1 -1
  2. package/dist/commands/brain.js +77 -28
  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/connect.d.ts +113 -0
  8. package/dist/commands/connect.d.ts.map +1 -0
  9. package/dist/commands/connect.js +849 -0
  10. package/dist/commands/connect.js.map +1 -0
  11. package/dist/commands/conversations.d.ts +5 -0
  12. package/dist/commands/conversations.d.ts.map +1 -0
  13. package/dist/commands/conversations.js +116 -0
  14. package/dist/commands/conversations.js.map +1 -0
  15. package/dist/commands/founder.d.ts +16 -0
  16. package/dist/commands/founder.d.ts.map +1 -0
  17. package/dist/commands/founder.js +446 -0
  18. package/dist/commands/founder.js.map +1 -0
  19. package/dist/commands/handoff.d.ts +5 -0
  20. package/dist/commands/handoff.d.ts.map +1 -0
  21. package/dist/commands/handoff.js +432 -0
  22. package/dist/commands/handoff.js.map +1 -0
  23. package/dist/commands/orchestrate.d.ts +15 -0
  24. package/dist/commands/orchestrate.d.ts.map +1 -1
  25. package/dist/commands/orchestrate.js +294 -0
  26. package/dist/commands/orchestrate.js.map +1 -1
  27. package/dist/commands/project.d.ts.map +1 -1
  28. package/dist/commands/project.js +8 -1
  29. package/dist/commands/project.js.map +1 -1
  30. package/dist/commands/reconcile.d.ts +15 -0
  31. package/dist/commands/reconcile.d.ts.map +1 -0
  32. package/dist/commands/reconcile.js +260 -0
  33. package/dist/commands/reconcile.js.map +1 -0
  34. package/dist/commands/session.d.ts +28 -0
  35. package/dist/commands/session.d.ts.map +1 -0
  36. package/dist/commands/session.js +895 -0
  37. package/dist/commands/session.js.map +1 -0
  38. package/dist/commands/sync.d.ts.map +1 -1
  39. package/dist/commands/sync.js +11 -0
  40. package/dist/commands/sync.js.map +1 -1
  41. package/dist/commands/tasks.d.ts +20 -0
  42. package/dist/commands/tasks.d.ts.map +1 -1
  43. package/dist/commands/tasks.js +90 -19
  44. package/dist/commands/tasks.js.map +1 -1
  45. package/dist/generated/capability-registry.d.ts +444 -76
  46. package/dist/generated/capability-registry.d.ts.map +1 -1
  47. package/dist/generated/capability-registry.js +497 -76
  48. package/dist/generated/capability-registry.js.map +1 -1
  49. package/dist/index.js +122 -2
  50. package/dist/index.js.map +1 -1
  51. package/dist/lib/api.d.ts +393 -2
  52. package/dist/lib/api.d.ts.map +1 -1
  53. package/dist/lib/api.js +195 -2
  54. package/dist/lib/api.js.map +1 -1
  55. package/dist/lib/brain/adapters.d.ts +22 -1
  56. package/dist/lib/brain/adapters.d.ts.map +1 -1
  57. package/dist/lib/brain/adapters.js +184 -2
  58. package/dist/lib/brain/adapters.js.map +1 -1
  59. package/dist/lib/brain/approval-key-trust.d.ts +29 -0
  60. package/dist/lib/brain/approval-key-trust.d.ts.map +1 -0
  61. package/dist/lib/brain/approval-key-trust.js +139 -0
  62. package/dist/lib/brain/approval-key-trust.js.map +1 -0
  63. package/dist/lib/brain/content.d.ts +10 -3
  64. package/dist/lib/brain/content.d.ts.map +1 -1
  65. package/dist/lib/brain/content.js +133 -30
  66. package/dist/lib/brain/content.js.map +1 -1
  67. package/dist/lib/brain/descriptor-validator.d.ts +11 -0
  68. package/dist/lib/brain/descriptor-validator.d.ts.map +1 -0
  69. package/dist/lib/brain/descriptor-validator.js +185 -0
  70. package/dist/lib/brain/descriptor-validator.js.map +1 -0
  71. package/dist/lib/brain/discovery.d.ts.map +1 -1
  72. package/dist/lib/brain/discovery.js +77 -50
  73. package/dist/lib/brain/discovery.js.map +1 -1
  74. package/dist/lib/brain/index.d.ts +2 -0
  75. package/dist/lib/brain/index.d.ts.map +1 -1
  76. package/dist/lib/brain/index.js +14 -4
  77. package/dist/lib/brain/index.js.map +1 -1
  78. package/dist/lib/brain/proposal.d.ts +53 -5
  79. package/dist/lib/brain/proposal.d.ts.map +1 -1
  80. package/dist/lib/brain/proposal.js +330 -94
  81. package/dist/lib/brain/proposal.js.map +1 -1
  82. package/dist/lib/brain/safe-file.d.ts +25 -1
  83. package/dist/lib/brain/safe-file.d.ts.map +1 -1
  84. package/dist/lib/brain/safe-file.js +250 -30
  85. package/dist/lib/brain/safe-file.js.map +1 -1
  86. package/dist/lib/brain/safety.d.ts.map +1 -1
  87. package/dist/lib/brain/safety.js +5 -0
  88. package/dist/lib/brain/safety.js.map +1 -1
  89. package/dist/lib/brain/staged-apply.d.ts +2 -1
  90. package/dist/lib/brain/staged-apply.d.ts.map +1 -1
  91. package/dist/lib/brain/staged-apply.js +6 -3
  92. package/dist/lib/brain/staged-apply.js.map +1 -1
  93. package/dist/lib/brain/store.d.ts +3 -0
  94. package/dist/lib/brain/store.d.ts.map +1 -1
  95. package/dist/lib/brain/store.js +68 -0
  96. package/dist/lib/brain/store.js.map +1 -1
  97. package/dist/lib/brain/sync.d.ts +48 -0
  98. package/dist/lib/brain/sync.d.ts.map +1 -1
  99. package/dist/lib/brain/sync.js +102 -0
  100. package/dist/lib/brain/sync.js.map +1 -1
  101. package/dist/lib/brain/types.d.ts +23 -0
  102. package/dist/lib/brain/types.d.ts.map +1 -1
  103. package/dist/lib/brain/vision.d.ts +35 -0
  104. package/dist/lib/brain/vision.d.ts.map +1 -0
  105. package/dist/lib/brain/vision.js +65 -0
  106. package/dist/lib/brain/vision.js.map +1 -0
  107. package/dist/lib/businessScaffold.d.ts +42 -0
  108. package/dist/lib/businessScaffold.d.ts.map +1 -0
  109. package/dist/lib/businessScaffold.js +150 -0
  110. package/dist/lib/businessScaffold.js.map +1 -0
  111. package/dist/lib/codex-device-auth.d.ts +94 -0
  112. package/dist/lib/codex-device-auth.d.ts.map +1 -0
  113. package/dist/lib/codex-device-auth.js +295 -0
  114. package/dist/lib/codex-device-auth.js.map +1 -0
  115. package/dist/lib/codex-job-control-plane.d.ts +67 -0
  116. package/dist/lib/codex-job-control-plane.d.ts.map +1 -0
  117. package/dist/lib/codex-job-control-plane.js +105 -0
  118. package/dist/lib/codex-job-control-plane.js.map +1 -0
  119. package/dist/lib/codex-readonly-job.d.ts +76 -0
  120. package/dist/lib/codex-readonly-job.d.ts.map +1 -0
  121. package/dist/lib/codex-readonly-job.js +196 -0
  122. package/dist/lib/codex-readonly-job.js.map +1 -0
  123. package/dist/lib/config.d.ts +7 -0
  124. package/dist/lib/config.d.ts.map +1 -1
  125. package/dist/lib/config.js +3 -0
  126. package/dist/lib/config.js.map +1 -1
  127. package/dist/lib/connected-access-native.d.ts +111 -0
  128. package/dist/lib/connected-access-native.d.ts.map +1 -0
  129. package/dist/lib/connected-access-native.js +403 -0
  130. package/dist/lib/connected-access-native.js.map +1 -0
  131. package/dist/lib/connected-context.d.ts +82 -0
  132. package/dist/lib/connected-context.d.ts.map +1 -0
  133. package/dist/lib/connected-context.js +610 -0
  134. package/dist/lib/connected-context.js.map +1 -0
  135. package/dist/lib/goalRegistryFile.d.ts +169 -0
  136. package/dist/lib/goalRegistryFile.d.ts.map +1 -0
  137. package/dist/lib/goalRegistryFile.js +518 -0
  138. package/dist/lib/goalRegistryFile.js.map +1 -0
  139. package/dist/lib/goalsFile.d.ts +101 -0
  140. package/dist/lib/goalsFile.d.ts.map +1 -0
  141. package/dist/lib/goalsFile.js +413 -0
  142. package/dist/lib/goalsFile.js.map +1 -0
  143. package/dist/lib/handoff.d.ts +170 -0
  144. package/dist/lib/handoff.d.ts.map +1 -0
  145. package/dist/lib/handoff.js +316 -0
  146. package/dist/lib/handoff.js.map +1 -0
  147. package/dist/lib/machine-identity.d.ts +2 -0
  148. package/dist/lib/machine-identity.d.ts.map +1 -1
  149. package/dist/lib/machine-identity.js +13 -6
  150. package/dist/lib/machine-identity.js.map +1 -1
  151. package/dist/lib/onboarding.d.ts +4 -1
  152. package/dist/lib/onboarding.d.ts.map +1 -1
  153. package/dist/lib/onboarding.js +11 -3
  154. package/dist/lib/onboarding.js.map +1 -1
  155. package/dist/lib/orchestrator/loop.d.ts.map +1 -1
  156. package/dist/lib/orchestrator/loop.js +8 -3
  157. package/dist/lib/orchestrator/loop.js.map +1 -1
  158. package/dist/lib/orchestrator/run-journal.d.ts +68 -3
  159. package/dist/lib/orchestrator/run-journal.d.ts.map +1 -1
  160. package/dist/lib/orchestrator/run-journal.js +391 -37
  161. package/dist/lib/orchestrator/run-journal.js.map +1 -1
  162. package/dist/lib/orchestrator/supervisor.d.ts +11 -0
  163. package/dist/lib/orchestrator/supervisor.d.ts.map +1 -1
  164. package/dist/lib/orchestrator/supervisor.js +304 -116
  165. package/dist/lib/orchestrator/supervisor.js.map +1 -1
  166. package/dist/lib/orchestrator/tools.d.ts.map +1 -1
  167. package/dist/lib/orchestrator/tools.js +76 -3
  168. package/dist/lib/orchestrator/tools.js.map +1 -1
  169. package/dist/lib/redact.d.ts.map +1 -1
  170. package/dist/lib/redact.js +40 -7
  171. package/dist/lib/redact.js.map +1 -1
  172. package/dist/lib/remote-agent-event.d.ts +19 -0
  173. package/dist/lib/remote-agent-event.d.ts.map +1 -0
  174. package/dist/lib/remote-agent-event.js +85 -0
  175. package/dist/lib/remote-agent-event.js.map +1 -0
  176. package/dist/lib/remote-command.d.ts.map +1 -1
  177. package/dist/lib/remote-command.js +19 -0
  178. package/dist/lib/remote-command.js.map +1 -1
  179. package/dist/lib/remote-executor.d.ts +7 -1
  180. package/dist/lib/remote-executor.d.ts.map +1 -1
  181. package/dist/lib/remote-executor.js +391 -0
  182. package/dist/lib/remote-executor.js.map +1 -1
  183. package/dist/lib/sessionCheckpoint.d.ts +104 -0
  184. package/dist/lib/sessionCheckpoint.d.ts.map +1 -0
  185. package/dist/lib/sessionCheckpoint.js +191 -0
  186. package/dist/lib/sessionCheckpoint.js.map +1 -0
  187. package/dist/lib/sessionHandoff.d.ts +47 -0
  188. package/dist/lib/sessionHandoff.d.ts.map +1 -0
  189. package/dist/lib/sessionHandoff.js +305 -0
  190. package/dist/lib/sessionHandoff.js.map +1 -0
  191. package/dist/lib/stream.d.ts +3 -1
  192. package/dist/lib/stream.d.ts.map +1 -1
  193. package/dist/lib/stream.js +8 -3
  194. package/dist/lib/stream.js.map +1 -1
  195. package/dist/lib/taskLedgerProposal.d.ts +2 -2
  196. package/dist/lib/taskLedgerProposal.d.ts.map +1 -1
  197. package/dist/lib/taskLedgerProposal.js +16 -8
  198. package/dist/lib/taskLedgerProposal.js.map +1 -1
  199. package/dist/lib/tasksFile.d.ts +14 -2
  200. package/dist/lib/tasksFile.d.ts.map +1 -1
  201. package/dist/lib/tasksFile.js +39 -5
  202. package/dist/lib/tasksFile.js.map +1 -1
  203. package/dist/mcp/registry.d.ts +4 -1
  204. package/dist/mcp/registry.d.ts.map +1 -1
  205. package/dist/mcp/registry.js +230 -1
  206. package/dist/mcp/registry.js.map +1 -1
  207. package/dist/mcp/server.d.ts +1 -1
  208. package/dist/mcp/server.d.ts.map +1 -1
  209. package/dist/mcp/server.js +18 -9
  210. package/dist/mcp/server.js.map +1 -1
  211. package/native/prebuilds/darwin-universal/youmd_safe_open.node +0 -0
  212. package/package.json +4 -2
  213. package/scripts/env-vault/README.md +16 -20
  214. package/scripts/env-vault/backup.sh +22 -57
  215. package/scripts/env-vault/restore.sh +18 -96
  216. package/scripts/smoke-safe-open-node.cjs +50 -0
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env bash
2
- # env-vault/restore.sh — restores .env.local files AND agent-auth secrets from
3
- # an encrypted vault created by backup.sh. NEVER prints, echoes, or logs any
4
- # secret VALUES. Restore prints which file paths were restored or skipped; list
5
- # mode prints target paths plus variable names/counts only.
2
+ # env-vault/restore.sh — restores project .env.local files only from a vault
3
+ # created by backup.sh. It never restores Codex, Claude, OpenAI, Cursor,
4
+ # browser, or provider-auth caches. NEVER prints, echoes, or logs any secret
5
+ # VALUES. Restore prints target paths plus variable names/counts only.
6
6
  #
7
7
  # Usage: bash restore.sh [--list] [--force] [--map-existing] [--existing-only]
8
8
  # [--skip-agent-auth] [--root <target-root>] <vault-file>
@@ -11,29 +11,16 @@
11
11
  # --root: destination root for .env.local files
12
12
  # (default: /Users/houstongolden/Desktop/CODE_2025)
13
13
  #
14
- # agent-auth restore map (archive name → absolute home path):
15
- # agent-auth/codex-auth.json → ~/.codex/auth.json
16
- # agent-auth/cursor-mcp.json → ~/.cursor/mcp.json
17
- # agent-auth/claude.json → ~/.claude.json
18
-
19
14
  set -euo pipefail
20
15
 
21
- # ── agent-auth restore map ─────────────────────────────────────────────────────
22
- # Maps archive name (inside agent-auth/) to its absolute home destination.
23
- # Format: "archive-name:absolute-destination-path"
24
- # Must stay in sync with AGENT_SECRET_FILES in backup.sh.
25
- AGENT_AUTH_MAP=(
26
- "codex-auth.json:${HOME}/.codex/auth.json"
27
- "cursor-mcp.json:${HOME}/.cursor/mcp.json"
28
- "claude.json:${HOME}/.claude.json"
29
- )
30
-
31
16
  # ── defaults ──────────────────────────────────────────────────────────────────
32
17
  TARGET_ROOT="${ENV_VAULT_RESTORE_ROOT:-/Users/houstongolden/Desktop/CODE_2025}"
33
18
  FORCE=false
34
19
  LIST_ONLY=false
35
20
  MAP_EXISTING=false
36
21
  EXISTING_ONLY=false
22
+ # Legacy compatibility only. Earlier vault versions could include an
23
+ # `agent-auth/` payload; those archives are rejected before any file is written.
37
24
  SKIP_AGENT_AUTH=false
38
25
  VAULT_FILE=""
39
26
 
@@ -88,7 +75,7 @@ echo "Encryption tool: ${ENC_TOOL}"
88
75
  echo "Vault file: ${VAULT_FILE}"
89
76
  echo "Target root: ${TARGET_ROOT}"
90
77
  echo "Project mapping: map-existing=${MAP_EXISTING} existing-only=${EXISTING_ONLY}"
91
- echo "Agent auth: $([[ "${SKIP_AGENT_AUTH}" == "true" ]] && echo "skip" || echo "restore")"
78
+ echo "Provider auth: excluded (legacy auth-bearing vaults are rejected)"
92
79
  echo ""
93
80
 
94
81
  normalize_project_name() {
@@ -172,12 +159,19 @@ echo ""
172
159
  # ── extract into work dir ─────────────────────────────────────────────────────
173
160
  EXTRACT_DIR="${WORK_DIR}/extracted"
174
161
  mkdir -p "${EXTRACT_DIR}"
162
+
163
+ # Do not turn an older portable vault into a credential migration vector. The
164
+ # contents are never extracted or restored, including in --list mode; the
165
+ # operator must make a new project-env-only backup from the source machine.
166
+ if tar -tf "${TAR_PATH}" | grep -Eq '(^|/)(agent-auth|\.codex|\.claude|\.cursor)(/|$)|(^|/)Library/Application Support/(Claude|Codex|Google/Chrome)(/|$)'; then
167
+ echo "ERROR: This legacy vault contains protected agent/provider auth material." >&2
168
+ echo "Refusing to restore it. Create a new project-env-only vault on the source machine." >&2
169
+ exit 1
170
+ fi
175
171
  tar -xf "${TAR_PATH}" -C "${EXTRACT_DIR}"
176
172
 
177
173
  if [[ "${LIST_ONLY}" == "true" ]]; then
178
174
  ENV_COUNT=0
179
- AGENT_PRESENT=0
180
- AGENT_MISSING=0
181
175
 
182
176
  echo "Vault contents (secret-safe inventory):"
183
177
  while IFS= read -r -d '' ENV_FILE; do
@@ -200,28 +194,8 @@ if [[ "${LIST_ONLY}" == "true" ]]; then
200
194
  (( ENV_COUNT++ )) || true
201
195
  done < <(find "${EXTRACT_DIR}" -name ".env.local" -print0)
202
196
 
203
- AGENT_AUTH_SRC="${EXTRACT_DIR}/agent-auth"
204
- echo " agent-auth:"
205
- if [[ "${SKIP_AGENT_AUTH}" == "true" ]]; then
206
- echo " skipped by --skip-agent-auth"
207
- else
208
- for ENTRY in "${AGENT_AUTH_MAP[@]}"; do
209
- ARCHIVE_NAME="${ENTRY%%:*}"
210
- DEST_PATH="${ENTRY##*:}"
211
- SRC_FILE="${AGENT_AUTH_SRC}/${ARCHIVE_NAME}"
212
- if [[ -f "${SRC_FILE}" ]]; then
213
- FILE_BYTES=$(wc -c < "${SRC_FILE}" | tr -d ' ')
214
- echo " present: agent-auth/${ARCHIVE_NAME} -> ${DEST_PATH} (${FILE_BYTES} bytes)"
215
- (( AGENT_PRESENT++ )) || true
216
- else
217
- echo " missing: agent-auth/${ARCHIVE_NAME}"
218
- (( AGENT_MISSING++ )) || true
219
- fi
220
- done
221
- fi
222
-
223
197
  echo ""
224
- echo "List summary: ${ENV_COUNT} .env.local file(s), ${AGENT_PRESENT} agent-auth file(s) present, ${AGENT_MISSING} agent-auth file(s) missing."
198
+ echo "List summary: ${ENV_COUNT} .env.local file(s); provider/runtime credentials are excluded."
225
199
  echo "No files were written and no secret values were printed."
226
200
  exit 0
227
201
  fi
@@ -267,64 +241,12 @@ while IFS= read -r -d '' ENV_FILE; do
267
241
  fi
268
242
  done < <(find "${EXTRACT_DIR}" -name ".env.local" -print0)
269
243
 
270
- # ── restore agent-auth files ───────────────────────────────────────────────────
271
- AGENT_RESTORED=0
272
- AGENT_SKIPPED=0
273
- AGENT_BACKED_UP=0
274
-
275
- AGENT_AUTH_SRC="${EXTRACT_DIR}/agent-auth"
276
-
277
- if [[ "${SKIP_AGENT_AUTH}" == "true" ]]; then
278
- echo "Skipping agent-auth restore because --skip-agent-auth was provided."
279
- echo ""
280
- elif [[ -d "${AGENT_AUTH_SRC}" ]]; then
281
- echo "Restoring agent-auth files…"
282
- for ENTRY in "${AGENT_AUTH_MAP[@]}"; do
283
- ARCHIVE_NAME="${ENTRY%%:*}"
284
- DEST_PATH="${ENTRY##*:}"
285
- SRC_FILE="${AGENT_AUTH_SRC}/${ARCHIVE_NAME}"
286
-
287
- if [[ ! -f "${SRC_FILE}" ]]; then
288
- echo " SKIPPED (not in vault): agent-auth/${ARCHIVE_NAME}"
289
- (( AGENT_SKIPPED++ )) || true
290
- continue
291
- fi
292
-
293
- DEST_DIR="$(dirname "${DEST_PATH}")"
294
- mkdir -p "${DEST_DIR}"
295
-
296
- if [[ -f "${DEST_PATH}" ]]; then
297
- if [[ "${FORCE}" == "true" ]]; then
298
- cp "${SRC_FILE}" "${DEST_PATH}"
299
- echo " RESTORED (overwrite): ${DEST_PATH}"
300
- (( AGENT_RESTORED++ )) || true
301
- else
302
- TS="$(date -u +%Y%m%dT%H%M%SZ)"
303
- BAK="${DEST_PATH}.bak.${TS}"
304
- cp "${DEST_PATH}" "${BAK}"
305
- cp "${SRC_FILE}" "${DEST_PATH}"
306
- echo " RESTORED (backed up old → $(basename "${BAK}")): ${DEST_PATH}"
307
- (( AGENT_RESTORED++ )) || true
308
- (( AGENT_BACKED_UP++ )) || true
309
- fi
310
- else
311
- cp "${SRC_FILE}" "${DEST_PATH}"
312
- echo " RESTORED (new): ${DEST_PATH}"
313
- (( AGENT_RESTORED++ )) || true
314
- fi
315
- done
316
- echo ""
317
- else
318
- echo "No agent-auth/ directory in vault — skipping agent-auth restore."
319
- echo ""
320
- fi
321
-
322
244
  echo ""
323
245
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
324
246
  echo " Restore summary"
325
247
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
326
248
  echo " .env.local — Restored: ${RESTORED} | Skipped: ${SKIPPED} | Old files backed up: ${BACKED_UP}"
327
- echo " agent-auth — Restored: ${AGENT_RESTORED} | Skipped: ${AGENT_SKIPPED} | Old files backed up: ${AGENT_BACKED_UP}"
249
+ echo " provider auth — excluded by policy; none was restored"
328
250
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
329
251
  echo ""
330
252
  echo "Secrets are now in place. Do not print or share secret files."
@@ -0,0 +1,50 @@
1
+ /* eslint-disable @typescript-eslint/no-require-imports */
2
+ const assert = require("node:assert/strict");
3
+ const fs = require("node:fs");
4
+ const os = require("node:os");
5
+ const path = require("node:path");
6
+
7
+ const addon = require(path.resolve(
8
+ __dirname,
9
+ "../native/prebuilds/darwin-universal/youmd_safe_open.node",
10
+ ));
11
+
12
+ assert.equal(addon.napiVersion, 8, "expected the ABI-stable Node-API v8 addon");
13
+ assert.equal(typeof addon.safeRead, "function", "safeRead export is missing");
14
+
15
+ const root = fs.realpathSync.native(fs.mkdtempSync(path.join(os.tmpdir(), "youmd-node-abi-")));
16
+ const outside = fs.realpathSync.native(fs.mkdtempSync(path.join(os.tmpdir(), "youmd-node-abi-outside-")));
17
+
18
+ try {
19
+ fs.mkdirSync(path.join(root, "project-context"));
20
+ fs.writeFileSync(path.join(root, "project-context", "PRD.md"), "verified\n");
21
+ fs.writeFileSync(path.join(outside, "PRD.md"), "outside\n");
22
+
23
+ const stat = fs.lstatSync(root, { bigint: true });
24
+ const bytes = addon.safeRead(
25
+ root,
26
+ "project-context/PRD.md",
27
+ 1024,
28
+ stat.dev.toString(),
29
+ stat.ino.toString(),
30
+ );
31
+ assert.equal(bytes.toString("utf8"), "verified\n");
32
+
33
+ fs.rmSync(path.join(root, "project-context"), { recursive: true });
34
+ fs.symlinkSync(outside, path.join(root, "project-context"), "dir");
35
+ assert.throws(
36
+ () => addon.safeRead(
37
+ root,
38
+ "project-context/PRD.md",
39
+ 1024,
40
+ stat.dev.toString(),
41
+ stat.ino.toString(),
42
+ ),
43
+ /symlink_rejected|unsafe_path/,
44
+ );
45
+
46
+ console.log(`safe-open ABI smoke passed on Node ${process.version}`);
47
+ } finally {
48
+ fs.rmSync(root, { recursive: true, force: true });
49
+ fs.rmSync(outside, { recursive: true, force: true });
50
+ }