Skip to content

fix(privacy,policy): многострочный Redactor, порядок событий frontmost-veto, перепроверка после await - #68

Open
froggychips wants to merge 1 commit into
mainfrom
fix/veto-order-redactor
Open

froggychips wants to merge 1 commit into
mainfrom
fix/veto-order-redactor

Conversation

@froggychips

Copy link
Copy Markdown
Owner

Ревью 2026-09-19, поток «privacy & policy».

Что не так было

  • Redactor.redact(_ lines:) = lines.map(redact), а Vision отдаёт OCR построчно: многострочный PEM и password: со значением на следующей строке не редактировались никогда. Тест testRedactsPEMBlock проверял одну многострочную строку, а не массив.
  • WorkspaceEventSource при активации шёл .appActivated.frontmostChanged: координатор запускал freezeTier со старым frontmostPid, замораживал только что активированное приложение, а следующим событием размораживал. Это штатный порядок, не corner-case.
  • В freezeTier после await vortex.freezeProcess не перепроверялись frontmost / freezingEnabled / sleep — Off из меню не останавливал идущий обход.
  • config.vadEnabled / vadRmsThreshold не пробрасывались в координатор.

Что сделано

  • Redactor работает по склеенному блоку (\n), правила с .anchorsMatchLines (пользовательские ^…$ не ломаются), значения в кавычках берутся целиком, карточный паттерн принимает NBSP/U+202F/U+2009. Тесты на массивы строк.
  • Порядок событий: frontmostChanged раньше appActivated; тест на реальном NSWorkspace-источнике с фильтром по pid теста.
  • Координатор: policyGeneration на весь обработчик (оба tier'а), inFlightFreezes, перепроверка после каждого await с откатом и audit reverted:<причина>. Тесты с детерминированными «воротами» вместо sleep.
  • VAD-параметры проброшены из конфига. SECURITY.md/README: границы Redactor (e-mail/IBAN/телефоны не режутся; транскрипты SessionStore через Redactor не проходят).

Проверка. Собрано локально (swift build --product FroggyDaemon / froggy / FroggyAudioWorker, только CommandLineTools) без ошибок и предупреждений в изменённых файлах. Тесты не компилировались и не запускались: на машине нет XCTest (нет Xcode), self-hosted раннер jabbook-air-m3 offline, ci.yml на macos-latest давно startup_failure. Diff прошёл ревью Codex, замечания учтены. Перед мержем нужен make test на машине с Xcode.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Wt32A3w8X6bMZAXKSVmsCv

…r, recheck after await, VAD wiring (review 2026-09-19)

Redactor: OCR-строки склеиваются и редактируются одним блоком — PEM из
нескольких строк и `password:` со значением на следующей строке теперь
матчатся (раньше `redact(_ lines:)` шёл `map`-ом и оба утекали в
state.json/ContextStore). Значения в кавычках берутся целиком; card-pattern
принимает NBSP/thin-space разделители.

WorkspaceEventSource: при activate сначала `.frontmostChanged`, потом
`.appActivated` — иначе `freezeTier` на `.appActivated` видел старый
frontmostPid и морозил только что активированное приложение, а следующее
событие его сразу размораживало (SIGSTOP+pageout+SIGCONT на каждую
активацию tier-1 под давлением).

VortexCoordinator: `policyGeneration` (инкремент на thawAll/Off/willSleep/
stopMonitoring); `freezeTier` перепроверяет условия перед каждым SIGSTOP и
после `await freezeProcess` — если pid стал frontmost, freeze выключен,
система уснула или поколение сменилось, SIGCONT сразу и pid не попадает в
tier-set (audit outcome `reverted:<причина>`).

main.swift: `config.vadEnabled`/`vadRmsThreshold` пробрасываются в
координатор (раньше использовались дефолты, поля конфига были мёртвыми).

README/SECURITY: честные границы Redactor (e-mail/IBAN не редактируются,
транскрипты SessionStore через Redactor не проходят).

Тесты добавлены, локально НЕ компилировались (на машине нет XCTest).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wt32A3w8X6bMZAXKSVmsCv

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 523f273c03

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Одно поколение на весь обработчик: thawAll во время обхода tier-1
// должен прервать и tier-2, а не только текущий tier (иначе tier-2
// взял бы уже новое поколение и доморозил после Off/willSleep).
let generation = policyGeneration

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Snapshot the generation before invoking the pacer

When pacerAdjuster suspends, thawAll() or stopMonitoring() can increment policyGeneration before execution reaches this line. The resumed handler then captures the already-incremented value, so every stale-policy check passes and it can freeze processes after the thaw/stop call has returned; cancellation alone does not prevent an async Swift task from continuing. Capture the generation before the pacer await, as the method comment requires, or explicitly revalidate cancellation and lifecycle state afterward.

Useful? React with 👍 / 👎.

Comment on lines 528 to +529
if tier1Frozen.contains(pid) || tier2Frozen.contains(pid) { continue }
if inFlightFreezes.contains(pid) { continue }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Revisit PIDs skipped behind stale in-flight freezes

If an old freeze is in flight when the policy generation changes, a newly valid traversal—for example after stopping and restarting monitoring under sustained pressure—skips that PID here. The old traversal subsequently observes its stale generation, thaws the PID, and returns, while the new traversal has already moved on; because pressure processing is event-driven, the target can remain unfrozen indefinitely despite the current policy. The new traversal needs to wait/retry, or stale completion must trigger reevaluation, rather than permanently skipping an in-flight PID.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant