aboutsummaryrefslogtreecommitdiff
path: root/scripts/newos4-feedback-collect.py
Commit message (Collapse)AuthorAgeFilesLines
* feat(feedback): chat plane on the dashboard + honest triage rankingAgando4 days1-1/+14
| | | | | | | | | | | | | | | | | | Tasks 3-8 of the chat-plane plan: - cron newos4-chat-ingest (0cc4bb4d2f82, */10, script-only, silent when idle) - collect.py: plan_key() normalises the two ledger spellings on read (5 rows carried a plan name without .md and were silently unmatched); per-item bulk_pass for the 2026-10-26 pass; counts.chat_total - feedback.html: 5th tile "from chat"; card shows who closed an item and when, with a bulk marker - triage: UNFILEABLE class -> top_real now ranks actionable errors only (first row went from an 18 203 fetch failure to the 989 toLowerCase runtime error); network/abort signatures move to policy_noise - AGENTS.md: the chat plane documented as an intake Verified: autoreview --dry-run over the 5 chat reports -> "nothing provable (5 left for the operator)" (R6 refuses auto:false); maintain 16 PASS 0 FAIL; feedback.html inline JS node --check OK; collect -> awaiting 5, chat_total 5.
* fix(newos4): pipe stage quoting, maintain ordering, help cost row, plan ↵Agando9 days1-3/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | status (v4.6.131) Four items closed in one batch; three ran as parallel subagents on disjoint files, the bundle was rebuilt once by the parent (rebuild-bundles.py serialises the working tree, which carries other sessions' work — see 161372f). 1. PIPE STAGES KEEP THEIR QUOTES. `js "a b".length | wc -c` reached eval as `a b.length` and printed a ReferenceError. terminal.js executePipeChain() now keeps `stages[i]` aligned 1:1 with `pipeParts[i]` (the `.filter(argv => argv.length > 0)` shifted the index; replaced by a lastStage scan + `if (argv.length === 0) continue`) and forwards the stage's own text to the dispatcher. The core path alone was dead code: ShellModule.init() replaces terminal.executePipeChain (shell.js:144), and that override is what runs in the browser (`executePipeChain.toString()` contained `cmdText.split`, not `lastStage`). Both now pass `cmdText`/`pipeParts[i]`. test-pipe-guard.js was rewritten for the new shape and now also asserts the shell override forwards raw text — the assertion that would have caught the shadowing. RED on HEAD: both flags false; GREEN now. 2. MAINTENANCE --fix CAN CLEAR ITS OWN WARN. check_index() ran before check_atlas(), which is what regenerates course/atlas.json, so --fix rebuilt modules-index.json from the stale atlas and the same WARN reappeared every run. check_atlas() now runs immediately before check_index(). modules-index.json regenerated: cost/usage present, 349 commands, version 2026-10-29-atlas. 3. `cost` DOCUMENTED. modules/core/module-billing.js registers `cost [on|off]` (an alias of `usage`); help.html had no row. Added above the `usage` row. help coverage 362/363 -> 363/363. 4. SHIPPED PLANS STOP ASKING FOR A DECISION. The applier only flips review<->safe, so every executed review-gated plan kept counting as an open decision (5 of 5). newos4-feedback-collect.py now reads the body: a `## Status` / `## Implementation` heading followed by shipped|executed plus a version, commit or date is `status: done`; those stay in `plans` (visible as shipped) but leave plans_review and awaiting_decision. Counts: plans_review 5 -> 0, awaiting_decision 4 -> 1 (the remaining one is a real open report, RPT-20261027-160751). admin/feedback.html read `it.status[0]`, which would render `d` for a string status; it now prefers `status_lines[0]`. Also carried, authored by earlier uncommitted sessions and already live in the bundle (attributed, not silently absorbed): modules/core/module-billing.js (new, BillingModule: cost/usage), its CORE_FILES entry in scripts/rebuild-bundles.py, and the BillingModule registry entry in terminal.js. The bundle was rebuilt from HEAD + this batch with ollama-manager.js taken from HEAD, so another session's in-flight `_httpError` refactor is deliberately NOT in the shipped bundle (grep -c _httpError core-bundle.js = 0). Verification node modules/test/test-pipe-guard.js -> {"empty":[],"blank":[],"classifyGuarded":true,"pipeGuarded":true,"shellForwardsRaw":true} node modules/test/test-parse-args.js -> 28/28 pass maintained job -> node tests 21/21 pass scripts/newos4-maintain.py -> maintenance result: OK (modules-index 349, help 363/363, changelog current v4.6.131) live v4.6.131 (real DOM, no print monkey-patch): js "a b".length | wc -c -> 1 (js printed 3, one byte) js "a b".length -> 3 js "abc".toUpperCase() -> ABC echo "two words" -> two words node -e "import('fs')" -> red error + Node-builtin hint js 6*7 -> 42 unhandledrejection -> 0 livePipeImpl: shell-override, livePipeForwardsRaw: true, costRegistered: true
* feat(feedback): autonomous first-pass reviewer — decide what is provable, ↵Agando11 days1-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | leave the rest The operator asked: "when I don't do anything, an agent can do it for me and I can just follow up or steer it." This is that agent, deterministic (no LLM): same input, same decision, and every reason is a grep or a commit hash that can be checked. spaces/newos4/scripts/newos4-feedback-autoreview.py — rules, first match wins: R1 duplicate same fingerprint already decided -> resolve R2 already-fixed identifiers absent from modules/**/*.js AND `git log -S<token>` proves a commit removed them -> resolve R3 noise fetch/abort/probe patterns -> reject R4 still-present auto report + stack + identifiers still in code -> approve (max 2/day) R5 plan / R6 user report -> never decided Writes to the same append-only decisions.jsonl with actor=auto-reviewer, note + evidence; the applier's last-wins rule means any operator click overrides an agent decision. Kill switch: data/feedback/autonomy.json {"mode":"off"} (safe default, aggressive = cap 5). Cron job e31ac58a559e, 07:40 and 19:40, no_agent, silent unless it decided something. Fixture proof (6 cases, /tmp corpus, git repo with a real removal commit): RPT-A duplicate -> resolve (duplicate of already-decided RPT-B) RPT-C already-fixed -> resolve (goneFromCode removed from modules/ in fc4eaf3) RPT-D noise -> reject RPT-E still-present -> approve RPT-F user report -> SKIP RPT-G never existed -> SKIP <- caught the first draft, which called it "already fixed" Live dry-run on the real corpus: "nothing provable (0 left for the operator, mode=safe)" and `git log -S emptyTrash -- spaces/newos4/modules` resolves to 563a9be, i.e. the report I wrongly approved by hand tonight would have been auto-resolved correctly. Dashboard: agent-decided cards carry a 🤖 badge + the reason + "Any button below overrides it", and the tab shows "🤖 feedback agent: N decided on its own in its last run (safe mode, M left for you)".
* feat(newos4): filter network-class auto reports at ingest — count, don't fileAgando11 days1-0/+6
| | | | | | | | | | | | | | | | | | | | | | The debug supervisor files an auto report for any failed fetch, so a flaky phone connection or a retired endpoint became a review card. One cluster held 14 407 + 1 031 occurrences and produced 3 of the 19 cards in the queue; 10 of 21 items reviewed on 2026-10-26 were noise for this reason. api/debug/report.php: an auto report whose *every* error is network-class (fetch failed / failed to fetch / network error / load failed / aborted / signal is aborted / ERR_INTERNET_*) now increments data/debug/network_failures.json (per day, per source path, top 40 kept) and returns 202 {filtered:"network"}. No RPT file, no card. Never filtered: any report with auto=false (user content), and any auto report carrying a stack/TypeError, i.e. a real defect. Verified on a throwaway tree and live through nginx: auto network poll.php -> 202 filtered, no file auto network /ollama/ -> 202 filtered, no file auto TypeError + stack -> 201 filed (RPT-20261026-134455-95f10612) user report w/ "fetch" -> 201 filed (RPT-20261026-134455-ab0f2cd4) Live: counter total=1 by_source {'/spaces/newos4/api/chat/poll.php': 1}, reports stayed at 19. The dashboard now shows the counter instead of silence: "🌐 1 network failure counted at ingest today, not filed as cards — /spaces/newos4/api/chat/poll.php ×1"
* feat(feedback): preview a plan or report in a modal before decidingAgando12 days1-1/+18
| | | | | | | | | | | | | | | | | | | | | | | | | The cards only carried a title, a path and buttons — approving blind was the only option. The page cannot read .hermes/plans/*.md itself (600 darkbot, php-fpm is www-data), so the collector — already running as darkbot every 10 minutes — now embeds what a decision needs: plans -> excerpt (first 60 lines, 2.4 KB cap), task headings, status/implementation lines reports -> body, page url, newOS4 version, user agent, first 3 error strings Modal: click a card title (or, on a report, read it in place) -> title, meta line with path/size/modified/task count/decision, the text in a scrollable monospace block, and the same Approve / Reject / Noise / Resolve actions. Esc, backdrop and the X close it; on a phone it is full-screen. Cards and modal share one actButtons() helper instead of duplicating markup. Also fixes a bug I introduced earlier: recent_apply() referenced APPLIED, which was never defined — the NameError was swallowed by the function's own except, so the "last decision applied" line could never render. It now shows, e.g. "last decision applied 2026-10-26 12:47:03 UTC (plan:…mobile-download-share.md → approve)". Verified: node --check on the inline script; browser harness against the real snapshot (plan modal shows Goal + 9 tasks + status, report modal shows message/errors/page/ua, Esc closes); verify-mobile 390/360 x light/dark ALL VIEWPORTS OK with the modal open; collector py_compile + run (recent_apply 8 rows).
* feat(feedback): review dashboard, public guide, terminal commands (v4.6.94)Agando12 days1-0/+147
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).