aboutsummaryrefslogtreecommitdiff
path: root/modules/ext
Commit message (Collapse)AuthorAgeFilesLines
* feat(newos4): cut/copy in Files, paste into WebDAV (Issue D2)Agando12 days3-1/+76
| | | | | | | | | | | | | | | | | | | | | | | | The two panes kept separate clipboards (filemgr._clipboard vs webdav._selected), so "cut here, paste there" did not exist — the operator's last phone-test item. filemgr.js _openOverlay() publishes a read-only view of its clipboard on the terminal object: webx11.fileClipboard() / fileClipboardClear() / fileClipboardSet(paths, mode). webdav.js the bulk bar gains "📥 Paste N" (hidden when the clipboard is empty). Handler: for each path readFile -> _webdavRequest('PUT', dest + '/' + name, {body}); only 200/201/204 counts. For mode "cut" the local file is deleted AFTER the server accepted the bytes, never before. A failed PUT keeps the local copy, prints "📥 Paste failed: <name> — HTTP n", and leaves that path in the clipboard so "📥 Paste 1" is a retry. Successes leave it. Summary "📥 Pasted N item(s) to <path>" (+ "— M failed"), then the pane reopens there. Semantics: cut moves (upload then delete local), copy leaves the local file and keeps the clipboard so the same files can go into several folders. Verified with the transport stubbed in the live page (this browser has no WebDAV credential): button "📥 Paste 2" for a 2-path cut PUT ok (201) -> local file null (moved) PUT fail(500) -> local file "BBB" (kept) clipboard after -> {mode:"cut", paths:["/fail-d.txt"]}, button "📥 Paste 1" node --check both modules, no-undef clean (55 files), v4.6.101 x3 in main.html, syntax OK, help 362/362.
* fix(newos4): four phone-test defects — no preview close, single-file ↵Agando12 days3-113/+238
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | share, dead-end fullscreen, silent WebDAV move All four came from the operator's phone pass on v4.6.95 and each collapsed to a line of code. A "No file selected to download": the preview pane had no close control; the only ✕ was the file manager's own, and it calls _closeOverlay() which wipes _multiSelect/_selectedFile/_selectMode. On a phone the preview covers the list, so closing it before pressing Download always emptied the selection. The toolbar now starts with ✕ -> _clearPreview(), which keeps the selection and leaves fullscreen first; Download with no targets names the fix instead of stating a dead end. B share/copy: 🔗 existed only in the preview toolbar and took a single path, and after the Android share sheet there was no copy affordance. Added _sharePaths(paths, mode) used by both the toolbar (1 path, 📋 copy and 🔗 share) and a new action-bar 🔗 Share (whole selection), plus _inlineLinkBox() which renders a selectable input/textarea with all URLs when neither the share sheet nor the clipboard is available. No prompt() anywhere on this path. C fullscreen: requestFullscreen targeted .fm-preview-body, which sits INSIDE the pane but excludes the toolbar, so ⛶ and ✗ disappeared and only the OS back gesture got out. Now fullscreens #filemgr-preview — toolbar, ✕ and ⛶ stay on screen and ⛶ toggles. D webdav move: bulk Move asked for the destination with prompt(), which returns null in iOS standalone PWAs and most Android WebViews, so it silently did nothing and looked unimplemented. Destination is now an inline row in the bulk bar (44px input + "Move here"/"Cancel", prefilled). Verified on the served code: ext bundle md5 5f440c77b6ab5529729aee8019a6c351 (served == local), webdav.js carries wdav-move-dest x2, and a headless browser probe on the real page shows the toolbar as ["✕","⛶","📋","🔗"], closing the preview prints "Preview closed — selection kept" with the selection intact, selecting 3 files and copying yields a textarea with the 3 real WebDAV URLs, and Download with nothing selected explains what to do. 6 PASS on the URL test, no-undef clean, v4.6.99, help 362/362. Not done, deliberately: cut/copy + paste across the VFS/WebDAV border. Recorded as Issue D2 in the plan with the exact insertion points, the upload-then-delete ordering rule and the failure case.
* feat(newos4): mobile download/share UX — deferred blob revoke, ↵Agando12 days2-73/+209
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | multi-select, Web Share, 44px targets Executes .hermes/plans/2026-10-24_051600-newos4-mobile-download-share.md (approved via the feedback dashboard; marker autonomy: safe). Front-end only, v4.6.94 -> v4.6.95. T1 modules/ext/filemgr.js — URL.revokeObjectURL ran in the same tick as a.click(); iOS Safari and Android Chrome hand the blob: URL to the download manager asynchronously, so the transfer was aborted while the status line still said "Downloaded". Now revoked after 30 s. T2 download honours the multi-selection via _getSelectedPaths() (falling back to _selectedFile), reports "⬇ Downloaded N files" and "❌ Skipped <path>" instead of a silent partial success. T3 share: navigator.share -> clipboard.writeText -> inline read-only <input> (focused, selected). prompt() is suppressed in iOS standalone PWAs and most Android WebViews, which is why tapping 🔗 did nothing. Unresolvable space now reports "🔗 Share unavailable — no space resolved". T4 both preview toolbar buttons: min-height/min-width 44px, touch-action manipulation, 1em, gap 10px (was 24px/0.85em/6px — the smallest tap targets in the UI). T5 _previewShareUrl falls back _resolveSpaceName -> _detectSpaceName (webdav.js:22) -> page path, and returns null rather than emitting /spaces//<path>. T6 the URL helpers are now module-scope pure functions exported for Node, so modules/test/test-download-url.js tests the shipped code instead of a local copy (4 -> 6 cases). Also fixes a latent bug that made require() impossible: `typeof window.webx11` throws under Node because typeof does not protect a member access on an undefined global. Verified on the served bundle (filemgr.js is concatenated into critical-ext-bundle.js, NOT core-bundle.js — the plan's T7 grep pointed at the wrong file): HTTP 200, 129 867 B, 2x navigator.share, 3x fmBuildShareUrl, deferred revoke present, 11x min-height:44px. Live browser probe on /spaces/newos4/main.html: _previewShareUrl('docs/a.md') -> https://webx11.duckdns.org/spaces/newos4/docs/a.md (no double slash); with navigator.share absent and clipboard blocked, clicking 🔗 produced .fm-share-input containing that URL; button style ends min-height:44px;min-width:44px;touch-action:manipulation; toolbar gap:10px. node modules/test/test-download-url.js -> 6 PASS. lint-no-undef clean (55 files). maintain: PASS version v4.6.95 x3, syntax OK, HTTP 200 /main.html. Also adds admin/docs/session-overview-2026-10-26.md (glm-5.3-compressed session record).
* fix(newos4): audit names broken refs instead of counting documentation ↵Agando2026-10-231-5/+16
| | | | | | | | | | | | | (v4.6.86-87) The reference checker ran /skill-view \S+/ over every skill's prose, so 'skill-view <name>' and a quoted example in skills-system-guide were counted as missing skills: 'Broken refs: 2' with no names, both phantom. Placeholders and quoted names are now ignored (trailing punctuation stripped first), and the survivors are listed in the audit line and in the suggestion. Verified: clean tree -> Broken refs: 0. A probe skill referencing 'ghost-skill' -> Broken refs: 1 (probe-broken-ref → ghost-skill), while '<name>.' and '"module-management"' in the same file are ignored.
* fix(newos4): the audit stops inventing '999d unused' (v4.6.85)Agando2026-10-231-1/+3
| | | | | | | | | | | | getStaleSkills() returned daysUnused=999 for a skill that had useCount 0 and no lastUsed — a placeholder rendered by the audit as '999d unused', indistinguishable from a measurement. It told the operator to archive procedural memory that had simply never been instrumented. Now: daysUnused null + neverUsed true when there is no lastUsed; real day count otherwise; the audit prints '(never used)'. Verified: probe skill with no telemetry -> {daysUnused: null, neverUsed: true}; one last used 2026-08-01 -> 83; no 999 anywhere in getStaleSkills() or the audit output.
* fix(newos4): skill-create stops mangling what the agent wrote (v4.6.82)Agando2026-10-231-15/+36
| | | | | | | | | | | | | Two defects in one parser, both silent: - content = args.slice(2).join(' ') destroyed every newline, so markdown arrived as one line - the last argument was treated as tags whenever it contained a comma, and stayed in the body: a multi-line skill became a single line with ~13 bogus tags, reported as success Bodies can now be read from a VFS path (the only way markdown survives an argv splitter), tags are opt-in via --tags=, category via --category=. skill-patch takes a path too. Verified: body from file -> 6 newlines preserved, tags [alpha,beta], category testing; inline body containing four commas -> tags [], body intact.
* fix(newos4): skill points at the served contract URL, not a VFS path (v4.6.75)Agando2026-10-231-1/+1
| | | | | | The OS4 agent reported the skill cites /_docs/chat-contract.md, which does not exist in its VFS — correct: the file lives on the host and is served over HTTP. Browser VFS and disk are two stores, so a path-only pointer is a dead end. Now names the URL.
* docs(newos4): seed a chatting-with-hermes skill (v4.6.74)Agando2026-10-231-0/+72
| | | | | | | | | | A command that exists but is undocumented might as well not exist: the agent had no way to learn that `hermes` exists, that `chat` is taken, that replies are asynchronous, or that the cursor is milliseconds. Skill covers the commands, the chat_hermes tool, the failure table (401/413/429/503/507), the rules that keep it useful, and how to verify a send. Seeded from skill-pack-core._buildSkills() so every fresh session gets it; mirrored to skills/chatting-with-hermes.{md,json} + index.json (19 entries).
* docs(newos4): merge the two shell-composition skills into one seeded skill ↵Agando2026-10-231-0/+52
| | | | | | | | | | | | | | | | | | | | | (v4.6.65) Packet 9. `terminal-commands-silently-failing` and `command-composition-rules` described the same bug family from two angles, and since v4.6.58 both were describing behaviour that is now refused outright. - new seeded skill `command-composition-rules` in skill-pack-core's _buildSkills(): the rule, why the refusal exists (with the 42-42 / 34k-a measurement), what works (one command per call, wc multi-path, interactive-only pipes, quoted operators), how to verify a plausible-looking result, and the pitfalls - its History section names both retired skills so a reader arriving from either search finds the surviving one - mirrored onto disk as skills/command-composition-rules.md + .json and added to skills/index.json (18 entries) so the repo copy matches what sessions receive Verified live on v4.6.65: seeding reported 15 skills (was 14), the file and index entry exist in the fresh VFS, and the natural-language query "does the terminal have a shell and what is refused" returns command-composition-rules first (13.78, 3/4).
* fix(newos4): unmeasured skills are untracked, world-model writes verified, ↵Agando2026-10-231-0/+5
| | | | | | | | | | | | | | | | | | | | | | | skill audit External review packet (os4-external-review-v4.6.51.html) triaged against the code: 2 findings confirmed and fixed, 4 could not be reproduced and were recorded as such. - module-memory-graph.js: getStaleSkills() treated a missing lastUsed as 999 days unused, so skill-audit recommended archiving every skill (22 of 22). Skills with no usage telemetry are now collected by getUntrackedSkills() and never counted stale. Live: "Stale: 0" + "Untracked: 22 (no usage telemetry — NOT stale)". - module-world-model.js: _saveToVFS() ignored fsWriteJSON()'s return value and promoted whatever a truthy read returned. Now write -> read-back -> byte compare -> promote, with every return checked. Regression test modules/test/test-world-model-save.js (red on the old code: promoted=true with errs=[]; green now). - scripts/newos4-skill-audit.py: 5 mechanical probes (version x3, read_file paging + context budget, selection symbols, required scripts, extKeys) + skill presence; exits non-zero on drift. 7/7 pass today. Weekly job cb6bc2a16216 runs it Mondays. Not reproduced (recorded in admin/docs/newos4-external-review-verification-2026-10-23.md): world_model_query empty-payload throw (live call returns JSON), pipes-as-command-names, ls skills empty (23 entries via fs.readDir), ~66 agent dirs (4 live).
* fix(newos4): download link uses the user's space; WebDAV share copies ↵Agando2026-10-213-27/+209
| | | | | | | | | | | | verified file links; preview fullscreen+share; files->WebDAV upload button (v4.6.45) - download: URL built from _resolveSpaceName() (config url = logged-in user), not the page space - WebDAV browser 🔗: shares selected FILES only, URL-encoded, HEAD-verified (200) before claiming success; folders offer a tar fallback instead of a guaranteed-403 link - file manager preview: ⛶ fullscreen + 🔗 copy-link toolbar (was none) - file manager toolbar: ☁ WebDAV publishes selected/current file via webdav-push - modules/test/test-download-url.js: 4 PASS - rebuild bundles, bump v4.6.44 -> v4.6.45 (loader + 3 script tags)
* newOS4 v4.6.40: review fixes (bug diagnostics, trash tree, dir paste, stale ↵Agando2026-10-183-9/+22
| | | | capture, preview)
* newOS4 v4.6.36: fix CourseModule print-capture swallowing all command outputAgando2026-10-181-2/+16
|
* newOS4 v4.6.35: file manager multi-select + safe paste/rename/delete (Part B)Agando2026-10-182-162/+320
|
* newOS4 course: post-exec review fixes (telemetry detail sanitize, skill-sync ↵Agando2026-10-181-0/+1
| | | | retry, atlas check)
* newOS4: interactive AI course (terminal module, portal, atlas, telemetry, ↵Agando2026-10-181-0/+323
| | | | daily maintenance+cron) + free store card
* auto: 2026-07-29_20:45 changesAgando2026-10-151-1/+7
|
* auto: 2026-07-29_20:45 changesAgando2026-10-081-6/+424
|
* newOS4 v4.6.18: nginx dav trailing-slash semanticsAgando2026-10-021-4/+20
| | | | | | | | | | | Discovered by dav-health-check.sh E2E (10/10 pass now): - nginx dav module REQUIRES trailing slash on MKCOL (no-slash → 409) and on directory DELETE (no-slash → 409/404); existing dir + slash MKCOL → 405 (the real 'already exists' signal) - _normalizeRemotePath now PRESERVES trailing slashes (collection ops) - _ensureDir MKCOLs with trailing slash - _deleteFile retries with slash on 409/404 (collection delete) - health-check expectations corrected (405 = existing, slash required)
* newOS4 webdav path fix + WebX11 resilience package (2026-10-02)Agando2026-10-021-26/+85
| | | | | | | | | | | | | | | | | | | | Root cause fixes (mindtech incident): - webdav.js: _normalizeRemotePath strips full URLs/space prefixes, applied to all request entry points + _absoluteUrl for MOVE/COPY Destinations - _ensureDir: __list__ existence fast-path (kills MKCOL 409 storms) - dashboard-files.js: updateFilesJson parses __list__ autoindex (no more '#' entries), ensureSpaceExists only re-inits on genuine 404 - 20-test regression suite: scripts/test-webdav-paths.mjs Resilience: - dav-auth-check.py: server-side WebDAV write auth microservice (nginx auth_request on 8904) — anonymous/wrong-token writes now 401 - fail2ban-telegram.py: ban alerts + auto-unban for known space users - backup-spaces.sh: daily hardlink snapshots, 14-day retention - space-health-check.py: junk dirs / myfiles.json / version drift / session sanity → Telegram alerts - dashboard-files.js: visible 503 error panel with Retry + auto-retry - v4.6.16: main.html + module-loader LATEST_VER aligned (was drifted)
* newOS4 v4.6.15: reentrant print-capture stack, AI tail -f block, read-only ↵Agando2026-09-292-18/+22
| | | | sed in safeRead, security test harness (21 checks)
* auto: 2026-07-29_20:45 changesAgando2026-08-061-310/+718
|
* feat: add kanban module to newOS4 — todo/doing/done board with prioritiesAgando2026-07-291-0/+190
|
* auto: 2026-07-09_06:00 changesAgando2026-07-096-347/+2089
|
* auto: 2026-07-02_06:00 changesAgando2026-07-022-1/+1240
|
* auto: 2026-06-23_06:00 changesAgando2026-06-231-3/+6
|
* auto: 2026-06-22_18:00 changesAgando2026-06-225-10/+923
|
* auto: 2026-06-19_18:01 changesAgando2026-06-191-6/+37
|
* auto: 2026-06-18_18:00 changesAgando2026-06-181-1/+11
|
* auto: 2026-06-18_06:00 changesAgando2026-06-185-13/+62
|
* auto: 2026-06-17_06:01 changesAgando2026-06-172-2/+16
|
* auto: 2026-06-16_06:00 changesAgando2026-06-161-0/+167
|
* auto: 2026-06-15_06:00 changesAgando2026-06-151-44/+156
|
* auto: 2026-06-13_18:00 changesAgando2026-06-131-0/+2363
|
* auto: 2026-06-11_18:00 changesAgando2026-06-111-190/+996
|
* auto: 2026-06-10_18:00 changesAgando2026-06-101-11/+39
|
* auto: 2026-06-10_06:00 changesAgando2026-06-101-0/+76
|
* auto: 2026-06-09_18:00 changesAgando2026-06-091-6/+84
|
* auto: 2026-06-09_06:00 changesAgando2026-06-096-18/+379
|
* auto: 2026-06-08_18:00 changesAgando2026-06-084-9/+386
|
* auto: 2026-06-06_18:01 changesAgando2026-06-061-0/+42
|
* auto: 2026-06-06_06:00 changesAgando2026-06-065-14/+288
|
* auto: 2026-06-04_06:00 changesAgando2026-06-041-2/+75
|
* auto: 2026-06-03_06:00 changesAgando2026-06-031-43/+106
|
* auto: 2026-06-02_18:00 changesAgando2026-06-022-133/+666
|
* auto: 2026-06-01_18:00 changesAgando2026-06-011-4/+23
|
* auto: 2026-06-01_06:00 changesAgando2026-06-011-2/+6
|
* auto: 2026-05-30_18:00 changesAgando2026-05-301-2/+12
|
* auto: 2026-05-30_06:00 changesAgando2026-05-302-0/+281
|
* auto: 2026-05-28_18:00 changesAgando2026-05-2815-57/+179
|