aboutsummaryrefslogtreecommitdiff
path: root/scripts/newos4-feedback-autoreview.py
Commit message (Collapse)AuthorAgeFilesLines
* fix(tooling): two checkers stopped manufacturing false audit signalsHermes SysOp11 hours1-6/+119
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Both defects are parser bugs in tooling, and both were producing a signal the operator sees on every run. Plan 2026-11-13_062052, implemented as written. 1. `help coverage` WARN was a quote-pairing artefact (every run, always 367/368). `newos4-maintain.py:238-239` captured `this._baseWhitelist = [...]` with a regex and then pulled `'([^']+)'` out of it. A JS comment inside that array literal contains the apostrophe in "don't" (terminal.js:16), which desynchronised pairing: it matched forward to the opening quote of 'ui' and the pseudo-command `t work"\n // …` joined the audited set — so a genuine undocumented command was indistinguishable from parser debris. Fix: strip `/* */` and `//` before extracting, and keep only tokens matching `^[a-z][a-z0-9_-]{0,40}$`. The same shape bug existed for `const internals = [...]` and is fixed by the same helper. The WARN list is now single-line (newlines collapsed) so one bad token cannot reflow the digest. Proven both ways: injected `'zzz-probe-cmd'` into the whitelist -> `WARN: help coverage 367/368 — undocumented: zzz-probe-cmd`; reverted (md5 verified) -> `PASS: help coverage 367/367`. 2. Auto-review "still present in shipped code" fired on generic tokens. `STEER-20261112-195037-1eed [high] cmds.indexOf is not a function` was approved because `identifiers()` kept `indexOf` and `function` (hits: 36 and 74 files) and R4 approved on `any()` present token. `isCommand` — the only name that identifies the fault — was never considered, because stack frames were not parsed at all. It does not exist anywhere in the tree. Fix: JS keywords/builtins/DOM handler names join the skip set; `stack_functions()` extracts frame names (dropping `onclick`, `anonymous`, `eval`); R4 now requires a **distinctive** token (>=6 chars, present in modules/, not generic); and a stack whose TOP frame is `<anonymous>` is classified as generated code (`js-run` / `new Function`), which can never justify "still present in shipped source". The bottom `HTMLButtonElement.onclick (…/main.html)` frame proves only that a click started it — deciding on "does any frame name a real file" got this wrong once already. Proven: `identifiers('cmds.indexOf is not a function')` -> `[]`; `distinctive(['indexOf','function'], {...})` -> `[]`; the real report replayed into a fixture reports `nothing provable (1 left for the operator)` with **no** decision row written; production dry-run `nothing provable (0 left)`. `decisions.jsonl` still carries exactly 1 row for that report (append-only history untouched). Regression cover: `python3 scripts/newos4-feedback-autoreview.py --self-test` -> 6/6. maintain: node tests 42/42, help coverage 367/367, result OK.
* feat(newos4): R5 stale-artefact rule + dashboard queues a decision onceAgando12 days1-1/+47
| | | | | | | | | | | | | | | | | | | | | | | | | | | Feedback queue triage 2026-11-02: 23 reports, 22 decided, 1 open -- and the open one (RPT-20261029-115241, "[Terminal] Error in ShellModule.test: {\"silent\":true}") was already fixed in v4.6.135 (4472c81, modules/core/terminal.js:1966) yet could never be cleared by automation. Root cause: identifiers() keeps only generic class names (Terminal, ShellModule), both of which necessarily stay in the code, so R2 (every identifier absent) cannot fire; R4 needs a stack and this report has none. A stack-less "Class.method: {json}" console.error whose emitter gets *guarded* -- rather than deleted -- therefore sits "awaiting decision" forever. - newos4-feedback-autoreview.py: new R5 stale artefact -- auto report, no stack, every error count <= 1, and nothing newer than STALE_DAYS=5 in data/debug/errors.json -> resolve with the measured quiet_days as evidence. New --errors <path> knob so the rule can be run against fixtures. RED (pristine copy): "nothing provable (1 left for the operator)" GREEN (aged fixture): "resolve ... quiet 5.3d -- reopen if it recurs" NEG (live store 4.3d, and a report with count 21): both still refuse. - admin/feedback.html: markDecided() patches the local snapshot, so a queued decision leaves the default "Awaiting only" list immediately instead of after the 10-minute sync rebuild. Measured cause of 3x approve on one plan in 3 min (10-30 16:03/16:05/16:05) and 6 items with duplicate rows. - AGENTS.md: documents R5 and the fixture knob (also carries the already-live 2026-11-02 cookie-notice paragraph that was pending in the tree).
* feat(feedback): autonomous first-pass reviewer — decide what is provable, ↵Agando2026-10-261-0/+240
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)".