| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Dashboard (/admin/feedback.html, admin-gated)
- User-feedback tab over the live :8908 API: list, filter, search, publish reply,
archive/reopen. Reply is what the reporter sees in /stear -> Your reports & replies.
- Agent-items tab: 3 plans parked at autonomy:review + 19 defect reports, one click each.
- Snapshot age line + stale warning (>30 min), and the last apply outcome with failures.
- Existing /admin/ tab relabelled "Client error log" (it renders feedback_log.json, not
the feedback store) and now links to the review dashboard.
Decision path
- admin/api/feedback-decide.php: exact-match nginx location + auth_request, Origin check,
item_id allowlist, append-only decisions.jsonl with fwrite+fsync verification.
- scripts/newos4-feedback-apply.py (darkbot): last decision per item wins, superseded rows
recorded, reject reverts safe->review, per-item try/except, ledger saved per mutation,
realpath containment, exact standalone-line marker flip, file mode preserved, queue
rotation at 1 MB. Steering directives now carry the report title.
- scripts/newos4-feedback-collect.py: snapshot for the dashboard, 40-line plan head,
steering shape assert (-1 = unknown), recent_apply outcomes.
- newos4-feedback-sync.sh: flock -n so overlapping runs cannot double-apply.
Guide + terminal
- feedback-guide.html: which channel (terminal feedback / /stear / automatic reports),
expectations, exact payload per channel, how to write a report that gets fixed.
Linked from /stear, index.html footer and help.html.
- newOS4: feedback list|read|reply|archive|reopen|stats|dashboard|help (+ feedback-admin
alias), admin-token derived per call, argument-validated dispatch so a sentence like
"feedback list is broken on mobile" is still a message, "feedback -- <text>" forces it.
- help.html: 8 rows, coverage 362/362.
Review: glm-5.3 REWORK -> 15 findings fixed, 5 refuted with evidence, 2 doc-only.
Guide corrected (invented "60 MB per batch" replaced by the real 512 KB/5-per-10-min limits).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
double print (v4.6.78-80)
12 findings accepted, 3 refuted with evidence (see _docs/chat-review-glm-2026-10-23.md).
Data loss: a corrupt thread read as [] and the next append rewrote it with one message —
now 500 and the file is left alone. Cursor after a >50-message truncation pointed at the
thread tail, making the oldest permanently unfetchable — now the last message actually
sent, plus truncated:true. Two posts in the same millisecond shared a cursor — epoch is
now strictly increasing.
Security: chat.py show() had no id validation and joined argv onto CHAT_DIR ('../../x'
read any .json as darkbot) — THREAD_RE added. The auto-reply prompt now treats message
text as untrusted data and forbids acting on instructions found in it.
Ops: relay housekeeping swept neither .lock-* nor orphaned .tmp-*; a crashed listing
looked identical to an empty queue; grep AWAITING also matched message bodies; hermes-poll
printed every reply twice.
Verified: corrupt file -> 500 with the file untouched; traversal -> 'invalid thread id';
hermes-poll -> exactly one line per reply.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
1. chat.py renamed the temp file AFTER releasing the flock, so two writers could each
read the pre-replace snapshot and the later rename silently dropped the earlier
message. os.replace now happens inside the lock.
2. The agent cursor was global. After hermes-reset it pointed past the end of the new
empty thread, so every read returned nothing — the agent would think it had been
ignored. Key is now per thread and reset clears every chat cursor.
3. chat-relay.sh had no overlap guard: a slow agent run (up to 5 min) could collide with
the next tick and answer the same thread twice. flock -n on /tmp/chat-relay.lock.
Verified: stale cursor 'webx11_chat_agent_cursor_oldthread00000' set to 9999999999999,
hermes-reset -> zero cursor keys remain, read returns {messages:[], note:'no new messages...'}.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Phase C as repo edits (browser edits in _mods/ do not survive a reload).
- `hermes <msg>`: sends through the chat endpoint and always prints an outcome —
'📨 Sending…' then either '✅ sent id=… epoch=…' or a coded error with a hint
(429 retry later, 503 host busy, 401 run hermes-reset). `feedback` stays as the alias.
- NOT named `chat`: ChatStudioModule already registers `chat` and dispatch walks modules
in order, so a second `chat` was silently unreachable. Found by test, not by reading.
- `hermes-poll` / `feedback-inbox`, `hermes-reset` (token rotation).
- Poller: 30 s, paused while the tab is hidden, polls on visibilitychange, first poll
adopts the cursor and prints nothing, cursor persisted in webx11_chat_state.
- `chat_hermes` tool: send + read from inside the agent loop.
- Contract/help updated for the rename.
Acceptance: 'hermes acceptance test' in the browser, reply written host-side with
scripts/chat.py, appeared in the terminal by itself 30 s later with no command typed
(cursor 1792776973800).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
dashboard (v4.6.55)
Root cause: splitPipe() splits on every '|', so `help |`, `| wc -l`, `a || b` produced a stage with
no argv and executePipeChain() called parts[0].toLowerCase() on undefined — 989 occurrences, first
filed 2026-10-20, unfixable from the report because bug reports dropped the stack that named
executePipeChain:3955. Same unguarded read existed in _classify().
- terminal.js: _classify() returns an inert classification for empty argv; executePipeChain()
parses each stage once, filters stages with no argv (so the last real stage stays final), warns
only when the whole pipeline is empty. Last-stage test now compares against the filtered length.
- module-system.js: `bug` diagnostics include the stack (10 frames, 1200 chars); auto-filed reports
carry it too — they are the majority of the inbox and were previously message-only.
- report.php: per-stack 2 KB cap; fingerprint pinned to message/source/count so adding `stack`
cannot break dedupe against reports filed before today.
- ingest.php: first_frame() parsed once on ingest, stored as `frame` on each signature.
- newos4-triage.py: FRAME| line with the first application frame.
- dashboard.php: frame under each Top Errors row.
- modules/test/test-pipe-guard.js: ordering tripwire (guard must precede the parts[0] read).
Verified: test RED exit=1 -> GREEN exit=0; browser matrix on v4.6.55 (help |, | wc -l,
echo hi || echo bye, ls | | wc -l, |) -> 0 new error signatures, "|" warns;
auto-filed report now carries stack (RPT-...f3e31124, archived after the probe);
frame = modules/core/core-bundle.js:3955:42; maintain OK; skill audit 7/7.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(v4.6.52-53)
Root cause: _syncToBackend() re-sent the whole error DB with cumulative counts every
300s, and ingest.php did count += client count per batch. 33 real signatures had
accumulated 116,696 "occurrences" (one self-referential row alone: 46,133).
Backend
- ingest.php: per-(session,hash) synced map, adds only the delta, resets prev when the
client count shrank (cleared localStorage), caps delta at 5000, bounds synced at 500
hashes and sessions at 200, normalises timestamps to +00:00, 30-day retention that
also purges dropped hashes from every synced map, returns `accepted` (entries) next
to `ingested` (occurrences).
- stats.php/dashboard.php: total_errors = occurrences, unique_errors = signatures,
last-ingest card. The two numbers were inconsistent by ~3,500x.
- health.php: reports self_referential count and status=degraded instead of ok.
- Pruned live data: 33 -> 23 records, 116,696 -> 58,759 occurrences, max cluster
110,226 -> 52,387 (archive kept in data/debug/archive/).
- nginx: stats/errors/clusters/dashboard/agent-replies now behind
auth_request /_wx11_admin_auth (302 without a session); ingest/report/health stay
public for telemetry. Verified: reads 302, ingest 200, report 400.
Client
- module-debug-supervisor.js: sends only hashes whose count changed (persisted
webx11_debug_synced), records synced counts only after success, stops auto-filing
aborts/timeouts and debug-pipeline requests as bug reports (2 of the last 5 reports
were "user aborted a request").
Verified with a scratch php -S copy: same batch POSTed 3x -> count stays 5;
count=99999 -> clamped to 1000; retention dropped 10 legacy rows.
|
| | |
|
| |
|
|
| |
generator, telemetry-loop fix)
|
| |
|
|
| |
modal, AI platforms, news W30
|
| |
|