Skip to content

Puter.js types and docs drift audit - 2026-08-01 #3485

Description

@reynaldichernando

puter.js SDK — TypeScript & documentation drift audit
Pinned to commit 535cf57 (branch main). Every finding below is reproducible against that tree.

Full deep audit of every API family — impl (src/puter-js/src/modules/ + src/index.js; UI param handling in src/gui/src/IPC.js), types (src/puter-js/types/), and docs (src/docs/src/).

Legend: 🟡 types (impl/docs have it, types don't/wrong) · 🔵 docs (impl/types have it, docs don't/wrong) · 🔴 both · 🐛 impl-bug (advertised param the impl ignores, or phantom typed method) · 🆕/🗑 manifest-drift (file added/removed vs the audit manifest).


⚠️ Structural change since last audit: several modules restructured flat file → directory

The biggest change this week is a large-scale refactor of single-file modules into directories (index.js + per-method files + lib/). The public surface is mostly unchanged, but the manifest's "flat .js" expectation is now stale, and the refactor surfaced several new, undocumented/untyped methods.

Module Was (manifest) Now (disk) New methods surfaced
AI modules/AI.js modules/ai/ (index + chat, image, models, ocr, sts, stt, tts, video, lib/)
Apps modules/Apps.js modules/apps/ checkName (documented), getDeveloperProfile (undocumented)
Hosting modules/Hosting.js modules/hosting/
KV modules/KV.js modules/kv/
OS modules/OS.js modules/os/ user, version (typed, no docs family — OK per manifest)
Perms modules/Perms.js modules/perms/ (appRootDir, folders, grants, groups, permissions) grant/revoke ×10, group ×4 (typed, undocumented), requestRead/WriteAppRootDir (untyped + undocumented)
Email (absent from manifest) modules/Email.js + email.d.ts send (typed, no docs family at all)

🆕 src/docs/src/Objects/ttsengine.md, ttsvoice.md, and src/docs/src/Apps/checkName.md also exist beyond the manifest's Objects/Apps lists. 🗑 No manifest-listed impl/doc file is missing from disk.


Highest-impact shortlist (all families)

  1. 🐛 UI alert() / prompt() / socialShare(url) hang forever on documented no-/minimal-arg forms. The IPC handlers gate ALERT/PROMPT on message !== undefined and read socialShare options.left without guarding options === undefined, so the documented minimal calls never post a response (or throw a TypeError) and the returned promise never settles. IPC.js:229,249,329.
  2. 🐛 AI test_mode option silently dropped in 4 methods (txt2img, txt2speech, speech2txt, speech2speech). Types + docs promise { test_mode: true } returns a free sample, but only the positional boolean reaches the wire-level flag — the options-object field never does. txt2vid/img2txt promote it correctly, proving the omission. Users testing via the documented object form burn real credits.
  3. 🔴 KV MAX_VALUE_SIZE is 399*1024 (399 KB / 408,576 B) but documented & typed as "400 KB" in 6 sites + 1 impl JSDoc. kv/lib/validate.js:4.
  4. 🔴 Hosting create/update dirPath marked required but is optional, and update with no dirPath sends root_dir: null to disconnect the directory — a real capability hidden from types and docs. hosting/create.js:37, hosting/update.js:21-22.
  5. 🔴 Perms requestReadAppRootDir / requestWriteAppRootDir are live public methods with zero type + zero doc coverage. perms/appRootDir.js:65,76.
  6. 🐛 UI alert body_icon/icon and notify type/duration are documented options silently ignored on the desktop/app path (IPC forwards neither). IPC.js:238,283.
  7. 🔵 New public methods missing all docs: puter.email.send, apps.getDeveloperProfile, workers.getLoggingHandle, 14 perms grant/revoke/group methods, UI toggleWindow/disableMenuItem/enableMenuItem.
  8. 🔴 AI ChatResponseChunk is missing the image and error chunk shapes that chat.md documents and shows in streaming examples.

AI

Function Item Issue Tag impl ref
chat option vision ChatOptions.vision? typed but impl never reads userParams.vision (only sets it internally when media present) — phantom option 🐛 chat.js:207-233
chat option provider impl reads + types declare, but chat.md omits it 🔵 chat.js:20,231
chat option response impl copies, types declare, docs never mention 🔵 chat.js:14
chat option context_management impl copies + typed (escape hatch), chat.md doesn't list 🔵 chat.js:23
chat option driver (alias of provider) legacy alias in impl + types, docs don't mention 🔵 chat.js:231-233
chat overload chat(prompt, testMode, options) documented + impl-supported, no matching TS overload (chat(p, true, {…}) type-errors) 🟡 chat.js:113-123; ai.d.ts:428-433
chat ChatMessage.images non-optional, forcing every input message to carry images; should be optional 🟡 ai.d.ts:14
chat (stream) chunk image chat.md documents part.image (type:"image_url") chunks; ChatResponseChunk + chatresponsechunk.md omit them 🔴 ai.d.ts:107-130; chatresponsechunk.md:12-21
chat (stream) chunk error chat.md documents an error chunk w/ part.message; type + object doc omit it 🔴 ai.d.ts:108-129; chatresponsechunk.md:12-21
chat ChatResponse.choices typed but chatresponse.md doesn't list choices 🔵 ai.d.ts:92
txt2img option test_mode type + doc advertise it, impl never promotes options.test_mode to wire flag (positional only) 🐛 image.js:38-50; ai.d.ts:223; txt2img.md:36
txt2img Replicate per-model options doc lists guidance,go_fast,output_quality,output_megapixels,safety_tolerance,prompt_upsampling,generation_mode,style,contrast,prompt_enhance — none on Txt2ImgOptions 🟡 image.js:68-77; txt2img.md:134-149
txt2img option input_image_mime_type typed + used in doc example, not in any options table 🔵 ai.d.ts:179
txt2img options service/driver typed, docs list neither (only provider) 🔵 ai.d.ts:180-182
txt2speech option test_mode type + doc advertise, impl only checks positional booleans 🐛 tts.js:111; ai.d.ts:288
speech2txt option test_mode type + doc advertise, impl never promotes options.test_mode 🐛 stt.js:59-83; ai.d.ts:397
speech2speech option test_mode type + doc advertise, impl positional-only 🐛 sts.js:74-98; ai.d.ts:421
speech2speech camelCase aliases impl accepts voiceId,modelId,outputFormat,voiceSettings,fileFormat,removeBackgroundNoise,optimizeStreamingLatency,enableLogging; none typed/documented — and speech2speech.md:90 example uses removeBackgroundNoise 🔴 sts.js:16-41; ai.d.ts:408-422
speech2speech option provider typed + forwarded, docs list omits 🔵 ai.d.ts:411
txt2vid option duration (alias seconds) impl maps durationseconds, typed, txt2vid.md documents only seconds 🔵 video.js:66-68; ai.d.ts:238
listModelProviders AI.md index has doc page + TS decl, omitted from AI.md Functions list 🔵 ai.d.ts:426; AI.md:194-203

FileSystem

Function Item Issue Tag impl ref
move dedupeName option docs list it, but move.js builds body with no dedupe field — silently ignored 🐛 move.js:49-60; FS/move.md:34
move newName option impl reads + typed, docs never mention 🔵 move.js:31; FS/move.md:29-35
move callback overload copy has (src,dst,options,success,error) overload; move doesn't 🟡 move.js:26; filesystem.d.ts:226
move newMetadata impl reads (newMetadata/new_metadata) + typed, undocumented 🔵 move.js:57
read cache option impl reads options.cache; absent from ReadOptions type + docs 🔴 read.js:45; filesystem.d.ts:81-88
read options+callbacks overload impl supports combined form; type has only separate forms 🟡 filesystem.d.ts:240-242
stat returnWorkers option impl reads (OR'd into return_subdomains); missing from type + docs 🔴 stat.js:58,73
stat consistency option typed + read, not documented 🔵 stat.js:37
readdir recursive option impl sends it; missing from type + docs 🔴 readdir.js:42
readdir depth option impl sends it; missing from type + docs 🔴 readdir.js:43
readdir no_subdomains option impl reads it; missing from type 🟡 readdir.js:36
readdir consistency/no_thumbs/no_assocs typed + read, undocumented 🔵 readdir.js:35-42
mkdir shortcutTo option typed + read (shortcut_to), not documented 🔵 mkdir.js:39
mkdir rename alias impl accepts rename alias of dedupeName; doc lists only dedupeName 🔵 mkdir.js:38
mkdir recursive alias impl accepts recursive alias of createMissingParents; doc lists only createMissingParents 🔵 mkdir.js:41
readdirSubdomains existence wired as puter.fs.readdirSubdomains but not on FS type + undocumented 🔴 readdirSubdomains.js; index.js:46
sign docs impl + type present, no FS/sign.md, not in FS.md list 🔵 sign.js; filesystem.d.ts:288
revokeReadURL docs impl + type present, no doc page, not in FS.md list 🔵 revokeReadUrl.js; filesystem.d.ts:303
getReadURL FS.md index has doc page but omitted from FS.md Functions index 🔵 FS.md:299-308
space example space.md example calls puter.space() — no such top-level alias 🔵 FS/space.md:34
upload init/start/progress/abort callbacks typed + read, upload.md documents none 🔵 upload/index.js:87-91
upload createMissingAncestors/createFileParent/shortcutTo/appUID/strict/name typed + read, undocumented 🔵 filesystem.d.ts:152-160
write data-less write(path) overload impl + docs allow it, but type makes data required 🟡 write.js:71-74; filesystem.d.ts:285
write createMissingAncestors + callbacks typed, not in write.md 🔵 write.js:37,45
FSItem uid/uuid/isDirectory impl + type expose them; fsitem.md documents only id 🔵 FSItem.js:53-54,104
FSItem readURL/writeURL/metadataURL public on impl + type, undocumented 🔵 FSItem.js:19-33
FSItem.write data param type docs say String|File|Blob; impl + type also accept ArrayBuffer/view 🔵 FSItem.js:169

KV

Function Item Issue Tag impl ref
MAX_VALUE_SIZE constant value is 399*1024 (408,576 B) but documented/typed as "400 KB" in 6 sites 🔴 kv/lib/validate.js:4; kv.d.ts:16,29,157; KV/set.md:29,37; kv/index.js:34
list offset-only / includeTotal-only impl returns KVListPage when any of limit/cursor/offset/includeTotal/fetchUntilFull set; type pagination overload requires limit or cursor → list({offset}) typed string[] but runtime is KVListPage 🟡 kv/list.js:177-182; kv.d.ts:115-117
add object-form overload impl accepts add({key, pathAndValueMap, optConfig}); absent from types + docs 🟡🔵 kv/add.js:29,37
incr/decr object-form overload impl accepts {key, pathAndAmountMap, optConfig}; absent from types + docs 🟡🔵 kv/lib/args.js:53-59
get/del/flush object-form overloads JSDoc says accepts object form; no type/doc overload 🟡🔵 kv/get.js:41
clear alias undocumented clear = alias of flush in impl + types, not in KV.md/flush.md 🔵 kv/index.js:53-54
decr 64-bit note incr documents 64-bit limit; decr omits it (same backend limit) 🔵🟡 KV/decr.md:7
KVValue type quality string|number|boolean|object|unknown collapses to unknown 🟡 kv.d.ts:2

(MAX_KEY_SIZE = 1024 = "1 KB" is consistent. add/incr/decr defaults, set-batch overloads, list pattern semantics, expire/expireAt, KVListPage/KVPair object docs all match.)

Apps

Function Item Issue Tag impl ref
getDeveloperProfile whole method NEW, exported + bound + typed (apps.d.ts:208), no doc page, absent from Apps.md list 🆕🔵 apps/getDeveloperProfile.js
create title param doc labels "(required)" — it's optional (falls back to name) 🔵 apps/create.js:42; Apps/create.md:34
create indexURL param doc says "not provided → no index page"; impl throws 'Index URL is required' 🔵 apps/create.js:56; Apps/create.md:25
get options-only overload impl supports get({stats_period,…}) with no name; types only get(name, options?) 🟡🔵 apps/get.js:25-27
App.users user_email app.md says users are {username, user_uuid}; type AppUser also has optional user_email 🔵 apps.d.ts:4-16

(checkName is new vs the manifest but fully wired — doc + type + list all present.)

Auth

Function Item Issue Tag impl ref
getUser sync throw non-async fn throws 401 before returning its Promise → getUser().catch() throws instead of rejecting; whoami (async) rejects correctly 🐛 Auth.js:211-218
signIn request_auth option public option in impl JSDoc, absent from type options 🟡 Auth.js:36; auth.d.ts:112
signIn request_auth option not documented in signIn.md Parameters 🔵 signIn.md:26-30
getUser params/overloads docs say "Parameters: None", impl + types accept options + (success, error) 🔵 getUser.md:15-18
whoami docs public in types + impl, no doc page 🔵 Auth.js:259
getMonthlyUsage/getDetailedAppUsage Auth.md index have doc pages + types but omitted from Auth.md Functions list 🔵 Auth.md:100-103
User object feature_flags/hasDevAccountAccess/otp interface fields not in user.md 🔵 auth.d.ts:15,16,21

Perms

Function Item Issue Tag impl ref
requestReadAppRootDir existence exposed on puter.perms but neither typed nor documented 🔴🆕 perms/appRootDir.js:65; index.js:87
requestWriteAppRootDir existence exposed but neither typed nor documented 🔴🆕 perms/appRootDir.js:76; index.js:88
grantUser/grantGroup/grantApp/grantAppAnyUser/grantOrigin docs typed (perms.d.ts:2-6), no doc pages, absent from Perms.md list 🔵🆕 perms/grants.js:15-61
revokeUser/revokeGroup/revokeApp/revokeAppAnyUser/revokeOrigin docs typed (perms.d.ts:8-12), undocumented 🔵🆕 perms/grants.js:72-118
createGroup/addUsersToGroup/removeUsersFromGroup/listGroups docs typed (perms.d.ts:14-17), undocumented 🔵🆕 perms/groups.js:13-46
requestPermission existence deprecated alias of request; not typed, not documented 🟡 perms/permissions.js:23
Perms.md platforms frontmatter Perms.md declares [apps]; method pages declare [websites, apps] 🔵 Perms.md:5

Email (new module — no docs family)

Function Item Issue Tag impl ref
send docs family public + fully typed (puter.email.send), but no src/docs/src/Email* exists at all 🔵🆕 Email.js:51; index.js:292

(No type drift: positional + options overloads and EmailSendOptions/EmailSendResult/EmailAttachment interfaces align with impl.)

UI (impl in UI.js / IPC.js = src/gui/src/IPC.js)

Function Item Issue Tag impl ref
alert message undefined alert() with no message → IPC gated message !== undefined → no response, promise hangs forever 🐛 IPC.js:229
alert body_icon/icon typed + documented, but IPC forwards only type → silently ignored on desktop path 🐛 IPC.js:230-238
prompt message undefined prompt() with no message hangs forever (same IPC gate) 🐛 IPC.js:249
prompt options.defaultValue impl/types/IPC support it; prompt.md never documents the options arg 🔵 UI.js:857; IPC.js:253
socialShare options omitted documented socialShare(url) → IPC reads options.left unguarded → TypeError, promise hangs 🐛 IPC.js:329
socialShare return type types say void; impl returns a Promise (which never resolves — no original_msg_id reply) 🟡 UI.js:844
notify type ignored documented option never read by IPC showNotification 🐛 IPC.js:283
notify duration ignored documented option never read/forwarded (no-op on desktop) 🐛 IPC.js:283
notify return value fallback resolves uid || null; type says Promise<string> 🟡 UI.js:906-908
showSpinner ref-count claim types + docs claim ref-counted "until all instances hidden"; impl early-returns, single hideSpinner removes overlay 🔴 UI.js:2298
contextMenu theme option typed + impl reads spec.theme; contextMenu.md never mentions 🔵 UI.js:1723
contextMenu x/y position impl reads spec.x/spec.y; neither typed nor documented 🟡🔵 UI.js:1726-1727
setMenubar theme option typed + impl reads spec.theme; setMenubar.md never mentions 🔵 UI.js:1364
setMenubar item id field MenuItem.id in types + required for setMenuItemChecked/etc; docs don't document 🔵 ui.d.ts:133
toggleWindow existence public method in impl, absent from types + docs 🆕 UI.js:1342
disableMenuItem existence public impl + IPC handler, absent from types + docs 🆕 UI.js:1659
enableMenuItem existence public impl + IPC handler, absent from types + docs 🆕 UI.js:1669
setMenuItemIcon/IconActive/Checked docs in types + impl (with IPC handlers), no doc files, not in UI.md 🔵 UI.js:1680,1692,1703
requestPermission docs typed + impl + IPC handler, no doc / UI.md entry 🔵 UI.js:1377; IPC.js:1314
requestUpgrade docs typed + impl, undocumented (borderline) 🔵 UI.js:1064
exit UI.md label UI.md lists puter.ui.exit() — no such UI method; actual API is puter.exit() (exit.md is correct) 🔵 UI.md:36
contextMenu/hideWindow/showWindow UI.md index doc files exist but are not listed in the UI.md "Available Functions" index 🔵🗑 UI.md
setWindowX/setWindowY/setWindowPosition "positive number" docs say x/y "Must be a positive number"; impl clamps to viewport (y floored at taskbar_height, not 0) 🔵 IPC.js:1092-1118
on('connection') replay claim grouped with localeChanged/themeChanged as "called immediately with most recent value", but connection is never stored in #lastBroadcastValue → never replays 🟡🔵 UI.js:586-619
launchApp #(as) pseudonym impl supports #(as) split in appName; undocumented in types + docs 🔵 UI.js:1957
launchApp app_name alias LaunchAppOptions.app_name typed (alias for name); docs only mention name 🔵 ui.d.ts:90

Workers

Function Item Issue Tag impl ref
getLoggingHandle docs public + typed (workers.d.ts:64) but absent from all docs (incl. Workers.md list) 🔵 Workers.js:233
getLoggingHandle close() unbound logStreamObject.close = socket.close (unbound) → handle.close() throws TypeError: Illegal invocation; sibling cancel binds correctly 🐛 Workers.js:270
getLoggingHandle getLoggingUrl args dropped makeDriverMethod called with no argNames then invoked with 2 positional args → driverArgs is {}, auth token + worker name silently discarded 🐛 Workers.js:234
getLoggingHandle log event log event / onLog / close / stream coercion documented nowhere 🔵 Workers.js:264-270
exec x-puter-no-auth header opt-out (unauthenticated request) header documented only in source JSDoc, not exec.md 🔵 Workers.js:97-100
exec options optionality exec.md options not tagged (Optional); type marks init? optional 🔵 Workers.js:93; workers.d.ts:52
list empty-object call list({}) matches no overload (bare list()), unlike hosting's list(options?) 🟡 Workers.js:141; workers.d.ts:63

(router.md/types.md describe the deployed-worker runtime — verified, internally consistent, not mapped to Workers.js.)

Hosting

Function Item Issue Tag impl ref
create dirPath optionality impl optional — create(subdomain) alone yields {subdomain}; types declare dirPath: string required + create.md marks it (required) 🔴 hosting/create.js:31,37-39
update dirPath optionality + disconnect impl optional; omitting it sends root_dir: null to disconnect the directory; type requires it + update.md never mentions the disconnect behavior 🔴 hosting/update.js:16,21-22
create object-form root_dir optionality impl passes object as-is (root_dir effectively optional); published overload + types + create.md mark it required 🟡 hosting/create.js:27,40-42

(get/delete + Subdomain object doc match. No camelCase rootDir alias — snake_case root_dir only, consistent.)

Networking

Function Item Issue Tag impl ref
Socket 'drain' event declared SocketEvent + registered in EventListener but never emitted anywhere — a consumer wiring addListener('drain') waits forever 🟡 PSocket.js:28; networking.d.ts:7,35
Socket on('drain') overload union includes 'drain' but there is no on(event:'drain', …) overload (self-inconsistent type) 🟡 networking.d.ts:7 vs 27-33
net.generateWispV1URL docs public typed method on puter.net, absent from Networking.md Functions 🔵 index.js:759; networking.d.ts:62
net.fetch input/url param type + impl accept RequestInfo|URL (incl. a Request); docs describe first arg as url (String) only 🔵 requests.js:47; fetch.md:18
TLSSocket 'error' payload read-loop emit('error', e) forwards a raw caught value (may be non-Error); type/docs promise Error 🟡 PTLS.js:92; networking.d.ts:31

(Socket/TLSSocket constructors, write/close/addListener, open/data/error/close + tls* events all match.)

Peer

Function Item Issue Tag impl ref
serve/connect options.port impl reads + forwards options.port (server-create & client-connect), but missing from PuterPeerOptions and both docs 🔴 Peer.js:98,286; peer.d.ts:1-6
connection 'error' .error field typed readonly error: string, but impl always emits new Error(...) / RTCError; docs treat it as an object (event.error?.message) — type is wrong, should be Error/unknown 🟡 Peer.js:348,277,327; peer.d.ts:42-44
connection 'message' .data field typed ArrayBuffer|string; data channel sets no binaryType, so binary frames arrive as Blob (omitted) 🟡 Peer.js:227-230; peer.d.ts:28-30
AppConnection object doc ownership Objects/AppConnection.md documents the puter.ui app-connection (usesSDK/postMessage/close), unrelated to peer.d.ts — naming collision; no Objects page for PuterPeerConnection/PuterPeerServer 🔵 AppConnection.md; peer.d.ts:94

(ensureTurnRelays, serve/connect returns, iceServers/forceRelay, PuterPeerServer/PuterPeerConnection surfaces + connection/open/close events all match.)

OS / Utils / Drivers

Function Item Issue Tag impl ref
Utils print escapeHTML option impl + types expose it; undocumented in Utils/print.md 🔵 index.js:1443
Utils print variadic params impl variadic (...args); types declare single text: string 🟡 index.js:1436; puter.d.ts:92
Utils env doc value list Utils/env.md lists only app/web/gui; impl + type also yield nodejs/web-worker/service-worker 🔵 index.js:459-480
Utils puter.on/off existence public host-app event API absent from puter.d.ts 🟡 index.js:1154,1161
Drivers.call 4-arg overload impl accepts (iface, implementation, method, parameters); types declare only 2/3-arg 🟡 Drivers.js:84-88; drivers.d.ts:9-10

(OS user/version match types cleanly — no OS docs family, correct per manifest. randName/appID/exit match.)


🐛 impl-bug bucket (code fixes, not doc/type edits)

# Bug ref
1 UI alert()/prompt() with no message never get an IPC response → promise hangs forever (handlers gated on message !== undefined) IPC.js:229,249
2 UI socialShare(url) (documented minimal form) reads options.left without guarding options === undefined → TypeError, promise hangs IPC.js:329
3 UI alert body_icon/icon never forwarded to UIAlert — silently ignored on desktop path IPC.js:238
4 UI notify type and duration never forwarded to UINotification — silently ignored on desktop path IPC.js:283
5 UI showSpinner early-returns instead of ref-counting; a single hideSpinner removes the overlay, contradicting the documented "until all instances hidden" UI.js:2298
6 AI test_mode options-object field never promoted to the wire-level flag in txt2img/txt2speech/speech2txt/speech2speech (positional boolean only); txt2vid/img2txt do it correctly image.js:38-50, tts.js:111, stt.js:59-83, sts.js:74-98
7 AI chat ChatOptions.vision? typed but never read from user options (only set internally when media present) — phantom option chat.js:207-233
8 FS move dedupeName documented but request body never includes a dedupe field — option is a no-op move.js:49-60
9 Auth getUser (non-async) throws the 401 before returning its Promise → getUser().catch() throws synchronously instead of rejecting (whoami handles it correctly) Auth.js:211-218
10 Workers getLoggingHandle().close() is socket.close copied unbound → TypeError: Illegal invocation when the documented close path is used Workers.js:270
11 Workers getLoggingHandle builds the getLoggingUrl driver method with no argNames, then passes 2 positional args → both auth token and worker name are dropped from the driver call (driverArgs = {}) Workers.js:234
12 KV assertKeySize/assertValueSize test .length (UTF-16 element count), not byte size; multibyte strings under-enforce, and non-string/array values have undefined .length so the value-size check is skipped entirely (pre-existing, flagged as a correctness gap) kv/lib/validate.js:17-28

🆕/🗑 manifest-drift

  • 🆕 Flat→directory restructure of AI, Apps, Hosting, KV, OS, Perms modules (each now <module>/index.js + per-method files + lib/). Public surface mostly unchanged; the manifest's "flat .js" entries are stale.
  • 🆕 Email modulemodules/Email.js + types/modules/email.d.ts, wired at index.js:292; entirely absent from the manifest, and no docs family exists.
  • 🆕 New public methods from the restructure: apps/getDeveloperProfile.js (undocumented), apps/checkName.js (documented), os/user.js + os/version.js (typed, no docs — OK per manifest), perms/{appRootDir,grants,groups}.js (grant/revoke/group typed-undocumented; requestRead/WriteAppRootDir untyped+undocumented).
  • 🆕 New docs beyond manifest: Objects/ttsengine.md, Objects/ttsvoice.md, Apps/checkName.md.
  • 🗑 None — no manifest-listed impl or doc file is missing from disk.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions