From 5076803d6b8d31cf9b35cb864738ce221f60f9e8 Mon Sep 17 00:00:00 2001 From: reviewer Date: Sun, 18 Oct 2026 12:54:16 +0800 Subject: [PATCH 1/3] docs: close out the 2026-10-18 open-item cleanup (W6.2 merge SHA pending) CHANGELOG/MEMO entry for the Opus-orchestrated cleanup (#475-#478), the Daily collector 30-minute window receipt (checklist, TODO, followups), the D7 dry-run report facts, PR numbers and merge SHAs in the TODO bullets, and the two items that need owner decisions (W4.1, W4.5). The #475 merge SHA is still a placeholder until that PR merges. Claude-Session: https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v --- CHANGELOG.md | 128 ++++++++++++++++++ MEMO.md | 9 ++ docs/TODO.md | 49 +++++-- docs/followups.md | 3 +- ...7-collector-source-retirement-checklist.md | 18 ++- 5 files changed, 193 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45da9d9e..4df7d48a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,134 @@ All notable changes to this project will be documented in this file. Format based on [Keep a Changelog](https://keepachangelog.com/). +## Open-item cleanup by Opus workflows: four TODO items shipped, Daily CPU measured, two items need owner decisions (2026-10-18) + +Owner request: "继续组织opus清理开放项" (keep orchestrating Opus to clear the open +items). Two Workflow runs with Opus agents, orchestrated from this session: +a read-only scoping pass (7 agents, one per `docs/TODO.md` open item, 11 min) +and an implementation pass (15 agents: 4 implementers in isolated worktrees +off `4b84e3d5`, a spec/invariants reviewer plus an independent test executor +per item, one fix round for D7, 67 min). The orchestrator read every diff, +pushed the branches and opened the PRs; nothing was deployed and no host was +changed. + +**Shipped (PRs opened from this session; merged in the order #477, #476, #478, #475, each after its required checks passed on a branch updated to the then-current `main`):** + +- PR #475 `__SHA_475__` — W6.2 real-binary chain gate. + `.github/workflows/real-binary.yml` (weekly, `workflow_dispatch`, and PRs + touching the gate; **not** a required check, `CI Gate` contract unchanged), + `scripts/ci/run-real-binary-gate.sh` (builds Debug EngramCollector / + EngramService / EngramRemoteServer, runs `CollectorBinaryShadowIntegrationTests`, + `CollectorCLIIntegrationTests` with the env vars set, writes a receipt) and + `scripts/ci/check-real-binary-results.py`, which fails unless the exact + expected test set executed (a green run with 50 skips is a fail; proven + locally: `result=fail expected=50 passed=0 skipped=50`). Local full run: + `result=pass expected=50 passed=49 skipped=1` (browser demo skipped by + design). Hosted result on the PR: pass on the third run (run 39093667839, head eb62c039): `result=pass expected=50 passed=49 skipped=1 failed=0`, large-history test 429.6 s. The first two hosted runs failed only on that test (240 s scope deadline, then the fixture's 0.5 s replica request timeout), so the gate now scales its deadlines and fixture HTTP timeouts by `--timeout-scale 3` on hosted runners; assertions and the expected test set are unchanged. +- PR #476 `7a48d19d` — App "Open Web Reader" action in `collector`/`replica` + roles, driven by a new optional `webReaderURL` key in `settings.json` + (https only, host required, no userinfo/query/fragment), disabled with a + caption when unset; the blocked-role branch still never opens the DB or + spawns a Service. 5 new `RuntimeRoleAppTests`. The per-host settings edit is + a later operator step. +- PR #477 `9f131f25` — W4.7 HQ half: `collectorEpochDryRun` (writer-gate + read, peer-UID gated, index role only, also lists observed-but-unapproved + epochs per instance) and `collectorApproveEpoch` (writer-gate write, + capability-token protected, exact expected epoch + authority generation, + role and enabled source re-checked inside the write), reached through + `EngramCLI collector-epoch dry-run|approve`; not on any Web allowlist, not on + the client protocol or mock. Design + `docs/superpowers/specs/2026-10-18-hq-collector-epoch-approval-design.md`, + ledger entry "Collector Epoch Approval Is A Local Operator Action", repro + `testUnapprovedEpochBecomesIngestibleAfterOperatorApproval_repro`. + Finding recorded as followup `collector-epoch-producer-1`: the collector + never rotates an epoch under an existing source instance + (`CollectorInventoryStore` mints fresh instance and epoch UUIDs per root + revision), so a spool reset arrives at HQ as a new instance on a registered + root and would hit `overlappingRoot` in provisioning; the new command covers + the design's same-instance case, the producer side is an owner decision. +- PR #478 `9ef7fb4f` — D7 option (c) tooling: `LegacyLocalSessionPurge` + (candidate predicate for legacy `origin=local` grok/pi rows that are not + capture-bound, blocking user-state counts, `planToken` over the sorted IDs, + one-transaction purge that refuses on plan change or any blocking dependent, + explicit FTS cleanup, audit metadata row), IPC `legacyLocalPurgePreview` / + `legacyLocalPurgeApply` (token protected, index role only), the offline + `EngramService --legacy-local-purge-report --database-path ` for a + report from a backup copy, and `EngramCLI maintenance legacy-local-purge + preview|apply --expect-sessions --expect-token`. Design + `docs/superpowers/specs/2026-10-18-d7-legacy-local-origin-purge-design.md` + (Rollout holds the operator runbook), ledger entry "Legacy Local-Origin + Purge Is Dry-Run First And Dependent-Free". Dry-run report produced from + a read-only `VACUUM INTO` snapshot of the HQ index (02:24Z, 13.4 GB, + quick_check ok, 45,764 sessions), first with the branch's Debug binary and + again with one built from merged `main` `9ef7fb4f` (byte-identical JSON), + and cross-checked with plain SQL: 6,191 candidates (grok 5,959, newest + indexed_at 2026-10-07T11:20Z; pi 232, newest 2026-09-11), every blocking + dependent 0 (insights, outside parent/suggested links, local state, + favorites, tags, offloaded), `purgeAllowed` true, planToken + `9fa54d7d1ab87778faf42d525076f8544b322207313ed06b4bb916f9d8890b8f` + (identical to the SQL recomputation); derived rows ftsMap/sessionsFts + 51,937, session_index_jobs 11,578, session_tools 23,232, session_costs + 6,191, work beats 531; retained file_index_state 6,191; the 866 grok and + 573 pi capture-bound rows are outside the predicate. The candidate count + has not grown since 2026-10-07, so the HQ role gate holds. The owner + approved this report on 2026-10-18 ("批准"; the approval covers the report, + not the host steps). Remaining D7 steps, each separately authorized: deploy + service-index and EngramCLI to HQ from a `main` containing #478, take a + fresh rollback `.backup`, confirm `legacy-local-purge preview` on the live + socket reproduces `sessionCount` 6,191 and the approved `planToken`, then + apply and re-preview to 0. + +Verification per PR is in each PR description (implementer plus independent +re-run with the test.yml HOME isolation; verifiers also ran mutation checks, +for example removing the capture-binding exclusion or the index-role gate made +the named tests fail). All four PRs passed the required checks before merge. + +**Daily collector CPU window (plan W6 item 3), read-only, not passed.** The +scoping agent found that the TODO's lead (the every-second Cursor peer +fingerprint scan) had already been mitigated on 2026-09-12 by the 30 s hint +cache and the 10 s gate, both present in the build that measured 13.178%, so +no code was changed; the done criterion is a host measurement. Window +2026-10-17T23:49:19Z to 2026-10-18T00:19:22Z on Daily (PID 96925, binary +`b83ada40…5c01` from the 2026-10-17 deployment, `pollIntervalMilliseconds` +10000, 16 roots, process uptime 10 h): 61 samples, wall 1803 s, **CPU 5.891% +of one core (target <= 2%: FAIL)**, max RSS 81.2 MiB (target <= 150 MiB: +PASS), PID stable, all 16 roots requested_revision == completed_revision +before and after (no re-walk). Per 30 s interval: 10 below 2%, 29 at 2-5%, +21 at or above 5%; quiet floor 0.45-1.0 s CPU per 30 s (1.5-3.5%), bursts of +3-9 s. Workload: 37 publications ACKed by both replicas (46,782 -> 46,819), +35 of them from the `daily-claude` root; the host was in active use (load +average 3.6 to 13, Spotlight `mds_stores` at 47% at the end). Discriminating +diagnostics all negative: `cursor_legacy_observer_error` 0 before and after +(FIX A not indicated), modern Cursor root revision unchanged (FIX B not +indicated), `~/.cursor` dirents 963 < 2048 (discoverModern budget fine); +`sample` (D4) not run because it attaches to the process and writes on Daily. +Reading: the cost is a polling floor near the target plus bursts tied to +Claude Code transcript appends; the next measured lead is the per-change +capture cost of large appended transcripts, unprofiled. Raw samples and the +receipt are in the session scratchpad; the checklist, TODO and followups carry +the summary. The item stays open. + +**Needs owner decisions (scoped, not built):** + +- W4.1 alias reconciliation: D7 chose the purge over the alias for the only + legacy rows in the central DB, D9 accepts the history gap, and HQ's legacy + Claude Code / Codex user state lives in the separate old local DB that an + alias inside the central DB cannot reach. Options: (a) close as superseded + by D7(c)/D9; (b) build as designed (about 800-1,100 lines, schema change, + design doc first) for a future local-role host that also ingests its own + collector; (c) re-scope as an old-DB user-state import. Also unverified: + whether the archive-v2 catalog is the accepted byte proof for any legacy row. +- W4.5 old-receipt bootstrap: D9 recorded it as "a later decision"; nothing + since reopens it. Building it needs W4.1 or an explicit duplicate rule and a + provenance change to `capture_ingest_generations` (publication sha and + sequence are NOT NULL), size XL. Options: keep D9 and mark won't-do, or + reopen with a design doc. + +Not in scope of this cleanup and unchanged: `cutover-hq-local-gap-1` (needs +owner credential and root steps on HQ), `collector-epoch-change-scope-1` +(owner decision), the untracked `.grok/workflows/engram-session-status.rhai`. + ## Collector reconcile command deployed to Daily; HQ service-index moved to main with P2 (2026-10-17) Owner authorization: "同意,按顺序来" for the three-step plan (recover Daily, diff --git a/MEMO.md b/MEMO.md index 7a00f858..3a6369f2 100644 --- a/MEMO.md +++ b/MEMO.md @@ -2,6 +2,15 @@ ## Changelog Memo +### 2026-10-18 + +- [变更] 业主要求继续用 Opus 清理开放项:两轮 Workflow(7 个只读 scoping agent、15 个实现/复核 agent),4 项落地为 PR 并按序合并:#475 `__SHA_475__` W6.2 真实二进制门禁(非必需工作流 + 校验脚本,跳过即失败);#476 `7a48d19d` App 在 collector/replica 角色下的「Open Web Reader」入口(新可选键 `webReaderURL`,仅 https);#477 `9f131f25` W4.7 HQ 侧 `collectorEpochDryRun`/`collectorApproveEpoch` IPC + `EngramCLI collector-epoch`(令牌保护、不进 Web);#478 `9ef7fb4f` D7 旧 `origin=local` grok/pi 清理的 dry-run/apply 工具与离线报告模式。均未部署,未改任何主机。详见 `CHANGELOG.md`。 +- [验证] 每个 PR 由实现者与独立复核者各跑一遍测试(ServiceCore 用 CI 的 HOME 隔离),复核者另做了变异验证(去掉关键守卫后对应测试确实失败);PR 的 required CI 全绿后才合并。#475 自身触发的托管 `Real-binary chain` 结果:第三次运行通过(run 39093667839,头 eb62c039):`result=pass expected=50 passed=49 skipped=1 failed=0`,大历史测试 429.6 秒;前两次只在该测试上失败(240 秒作用域期限、夹具 0.5 秒副本请求超时),已给托管机加 `--timeout-scale 3`(只拉长期限,不改断言)。 +- [排查] Daily collector 30 分钟只读测量(10-17 23:49Z 起,PID 96925,`b83ada40…`,poll 10 s,16 根全程收敛):CPU 5.891%(目标 ≤ 2%,未达标)、最大 RSS 81.2 MiB(达标);安静段地板 1.5% 到 3.5%,峰值与 35 条 Claude Code 转写发布对应;TODO 里的 Cursor peer scan 线索 9-12 已缓解,D1 到 D3 判别诊断均为阴性。新线索:大转写文件每次追加的捕获成本,未剖析(`sample` 需业主批准)。该项保持开放。 +- [新增] followup `collector-epoch-producer-1`:collector 从不在同一 source instance 下轮换 epoch,spool 重置到 HQ 表现为新 instance,provisioning 会报 `overlappingRoot`;W4.7 新命令只覆盖设计假设的同 instance 场景,生产者侧待业主决定。 +- [验证] D7 dry-run 报告已从 HQ 库只读快照(02:24Z,`VACUUM INTO`,13.4 GB,quick_check ok)生成(合并后 main `9ef7fb4f` 的二进制重跑,JSON 逐字节一致)并经独立 SQL 交叉核对:候选 6,191 行(grok 5,959、最新 indexed_at 10-07;pi 232),阻塞依赖全 0,`purgeAllowed=true`,planToken `9fa54d7d…90b8f`;capture 绑定的 grok 866 / pi 573 行正确排除;候选数自 10-07 起未增长。业主已于 10-18 批准该报告(仅报告,不含主机步骤);HQ 部署、回滚备份、live preview 复核与 apply 另需逐项授权。 +- [未验证] W4.1 别名对账、W4.5 旧回执引导需要业主决策(关闭 / 按设计建 / 重定范围),详见 `CHANGELOG.md`。 + ### 2026-10-17 - [变更] #473 合并为 `b95d99ad` 后,用同一提交的 Release/arm64 构建打包并部署:HQ 的 service-index 从 10-02 的 `8a6cdf6c` 换到 main(启动迁移建出 P2 索引,PID 20105,stderr 0 字节,账本无积压,`origin=local` 6,191 不变);Daily 的 collector 换到带 `--reconcile-native-epoch` 的新包(PID 96925,一次启动无错误)。两处都只改 plist 的 `ProgramArguments[0]`,旧包与 plist 备份保留可回滚。详见 `CHANGELOG.md`。 diff --git a/docs/TODO.md b/docs/TODO.md index 402d1e90..41a7e5d5 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -18,11 +18,30 @@ authorizes host changes. was deferred on 2026-09-13, not passed. The checklist names a repeated Cursor peer scan as the measured lead. Done when a 30-minute Daily window meets CPU <= 2% and RSS <= 150 MiB and the receipt is summarized in the checklist. + 2026-10-18 read-only window (PID 96925, the 2026-10-17 build, poll 10 s, 16 + roots converged before and after, host in active use): 61 samples over + 1803 s, CPU 5.891% (FAIL), max RSS 81.2 MiB (PASS), no re-walk, 37 + publications ACKed (35 Claude Code). The Cursor peer-scan lead was already + mitigated on 2026-09-12 (30 s hint cache, 10 s gate) and the D1-D3 + diagnostics were negative, so no code was changed. Next measured lead: + per-change capture cost of large appended transcripts + (`docs/followups.md` `collector-publication-cost-1`). Still open; receipt in + the retirement checklist and `CHANGELOG.md`. - **Alias reconciliation (plan W4 item 1, design section 4).** Not started. The committer refuses any occupied proposed ID, so pre-cutover local rows, their insights and parent links stay in the local-ID namespace and are not visible on Web. Done when exact-provenance aliasing and mismatch quarantine are tested. + 2026-10-18: scoped (about 800-1,100 lines, schema change, design doc first) + but not built; it needs an owner decision because D7(c) and D9 removed the + current production need: close as superseded, build as designed for a future + local-role host that also ingests its own collector, or re-scope as an old-DB + user-state import. See `CHANGELOG.md` 2026-10-18. - **Old-receipt bootstrap (plan W4 item 5).** Not started; no implementing code. + 2026-10-18: scoped as XL (the ingest generation and ledger assume a collector + publication envelope; receipt provenance needs a schema change) and dependent + on W4.1 or an explicit duplicate rule. D9 ("accept the history gap, W4.5 is a + later decision") still stands; needs an owner decision to reopen or to mark + won't-do. See `CHANGELOG.md` 2026-10-18. - **Operator epoch reconcile command (plan W4 item 7).** `dryRunEpoch` and `approveEpoch` exist in `CaptureIngestSourceRegistry.swift` without a non-test caller. Done when a local authenticated IPC/CLI action and its test exist. @@ -32,8 +51,8 @@ authorizes host changes. (`docs/superpowers/specs/2026-10-17-collector-native-epoch-reconcile-design.md`, invariant "Native Epoch Reconciliation Is An Explicit Operator Action"), deployed to Daily the same day as `collector-native-epoch-reconcile-20261017` - (real-host dry run: 0 affected roots). 2026-10-18: the HQ half is done in - code on branch `feat/w47-hq-approve-epoch-20261018` + (real-host dry run: 0 affected roots). 2026-10-18: the HQ half merged as + PR #477 (`9f131f25`) (`docs/superpowers/specs/2026-10-18-hq-collector-epoch-approval-design.md`, invariant "Collector Epoch Approval Is A Local Operator Action"): the token-protected Service command `collectorApproveEpoch` and the read-only @@ -71,7 +90,7 @@ authorizes host changes. - **App "open Web reader" entry (design section 1).** In `collector`/`replica` roles the App shows only the unavailable message; it has no action that opens the Web reader as the design states. - 2026-10-18: shipped on `feat/app-open-web-reader-20261018`. The unavailable + 2026-10-18: shipped in PR #476 (`7a48d19d`). The unavailable window and Settings fallback now show "Open Web Reader" for collector/replica, driven by an optional top-level `webReaderURL` in the owner-only `settings.json` (https only, host required, no userinfo/query/fragment, @@ -96,8 +115,7 @@ authorizes host changes. tooling has still never run against a real host; that remains under `docs/followups.md` `cutover-install-tooling-1`. - **D7 purge of legacy `origin=local` grok/pi rows, dry-run first (added - 2026-10-07).** Tooling implemented 2026-10-18 on branch - `feat/d7-legacy-local-purge-20261018` + 2026-10-07).** Tooling merged 2026-10-18 as PR #478 (`9ef7fb4f`) (`docs/superpowers/specs/2026-10-18-d7-legacy-local-origin-purge-design.md`): a SELECT-only report and a plan-bound purge in `LegacyLocalSessionPurge`, the index-role-only, capability-protected @@ -105,13 +123,20 @@ authorizes host changes. (one `ServiceWriterGate` transaction, refused on any user-state dependent, metadata audit row), `EngramCLI maintenance legacy-local-purge preview|apply`, and the offline read-only - `EngramService --legacy-local-purge-report --database-path ABS`. Still - open: run the read-only backup-copy report (design doc Rollout step 2), - owner approval of its `sessionCount` and `planToken`, the owner-run HQ - service-index and EngramCLI deploy, and the apply. The HQ central index - held 6,191 such rows on 2026-10-17 (grok 5,959, pi 232), unchanged since - the role gate. Done when a dry-run report exists, the owner approves it, - and the purge clears the rows plus their derived rows. + `EngramService --legacy-local-purge-report --database-path ABS`. The + dry-run report exists (2026-10-18, read-only `VACUUM INTO` snapshot of the + HQ index at 02:24Z, binary built from merged `main`, cross-checked with + plain SQL): `sessionCount` 6,191 (grok 5,959, pi 232, unchanged since the + role gate), every blocking dependent 0, `purgeAllowed` true, `planToken` + `9fa54d7d1ab87778faf42d525076f8544b322207313ed06b4bb916f9d8890b8f`; see + `CHANGELOG.md` 2026-10-18. The owner approved that report on 2026-10-18 + ("批准": `sessionCount` 6,191, `planToken` `9fa54d7d…90b8f`). Still open, + each separately authorized: the HQ service-index and EngramCLI deploy from + a `main` that contains #478, a fresh rollback `.backup` of the live index, + `EngramCLI maintenance legacy-local-purge preview` on the live socket + reproducing the approved count and token, then `apply --expect-sessions + 6191 --expect-token `. Done when the purge clears the rows plus + their derived rows and a re-run preview reports 0. Earlier status: no implementation-ready engineering task is selected as of 2026-08-16. diff --git a/docs/followups.md b/docs/followups.md index ad49c4fe..fafd54c5 100644 --- a/docs/followups.md +++ b/docs/followups.md @@ -16,9 +16,10 @@ decisions are in `docs/roadmap.md`, engineering gaps in `docs/TODO.md`. | `codex-resume-window-1` | medium | `macos/Shared/EngramCore/Adapters/SessionAdapterFactory.swift` `recentActiveAdapters` | Found while checking the item above. The periodic cycle sees Codex rollouts only in the today/yesterday date directories, so a rollout resumed and appended after its start-date directory leaves that window is not re-indexed until the Service restarts and runs a full scan. On HQ 17 rollouts (about 530 MB of unindexed content) were under-indexed on 2026-10-02. Other file-backed sources use an mtime cutoff. Fixed in source on 2026-10-02 (`CodexAdapter(modifiedSince:)`, two `_repro` tests); rollouts already behind and last modified more than two days ago still need one Service restart or full sweep, and the fix is not deployed. | | `collector-stuck-dirty-locators-1` | medium | `macos/EngramCollectorCore/CollectorInventoryOwner.swift`; capture worker | On the collector host 414 locators stay dirty and are retried about every 60 seconds with `unavailable`: 153 Codex paths are deleted recovery temp files (Codex event paths are not filtered to selected files and nothing finishes a vanished, never-captured path); 255 Copilot and 6 Kimi members exist but their group capture defers (cause inferred, not verified). | | `collector-blocked-root-backoff-1` | medium | `macos/EngramCollectorCore/CollectorRuntime.swift`; `CollectorEventCoordinator.swift` | A root whose bootstrap is blocked is restarted every turn and each blocked walk counts as a loss, so it cycles at turn rate. It is now reported on stderr after five consecutive blocked steps, but there is no back-off. | -| `collector-start-cost-1` | medium/perf | `macos/EngramCollectorCore/CollectorEventCoordinator.swift` | Every process start forces a full walk of every root, and a new process tries each stale event checkpoint once before falling back to a walk. A busy root can also repeat walks if its event queue overflows during recovery. Likely contributors to the missed CPU target; not measured after the 2026-10-02 fixes. | +| `collector-start-cost-1` | medium/perf | `macos/EngramCollectorCore/CollectorEventCoordinator.swift` | Every process start forces a full walk of every root, and a new process tries each stale event checkpoint once before falling back to a walk. A busy root can also repeat walks if its event queue overflows during recovery. Likely contributors to the missed CPU target; not measured after the 2026-10-02 fixes. 2026-10-18: the 30-minute Daily window excluded startup walks (process up 10 h, no re-walk during the window); the start cost remains unmeasured. | | `collector-epoch-change-scope-1` | low | `macos/EngramCollectorCore/CollectorRuntime.swift` | A changed FSEvents epoch for one root stops the whole runtime, including uploads for other roots. Decide whether it should suspend only that root, as an identity change does. | | `collector-epoch-producer-1` | medium, owner decision | `macos/EngramCollectorCore/CollectorInventoryStore.swift` `collector_streams`; `macos/EngramCoreWrite/CaptureIngest/CaptureIngestSourceRegistry.swift` `provision` | **Open, needs an owner decision (2026-10-18).** The collector never rotates an epoch under an existing source instance: a `collector_streams` row is created once per root, root revision and source with fresh UUIDs for both `source_instance_id` and `collector_epoch`, and later writes only advance `last_sequence`. A spool reset or a root re-enrollment that bumps the revision therefore reaches HQ as a new, unregistered source instance on an already registered root: its publications stay pending and are never claimed, and adding it to the source-authority file makes `CaptureIngestSourceRegistry.provision` throw `overlappingRoot` (UNIQUE machine/source/root), which aborts service-index startup. The new `collectorApproveEpoch` command keeps the source instance, so it cannot recover this case. Owner to decide: (a) the collector keeps the source instance and rotates only the epoch, making `collectorApproveEpoch` the recovery path, or (b) HQ gets a source-instance retire/rebind design. Until then the command covers only a same-instance epoch change that no current producer emits. | +| `collector-publication-cost-1` | medium/perf | `macos/EngramCollectorCore` capture and publication path | 2026-10-18 Daily window (CHANGELOG.md 2026-10-18): CPU bursts of 3-9 s per 30 s coincided with 35 Claude Code transcript publications while the quiet floor was 1.5-3.5%, so the <= 2% target fails on activity, not on polling. Hypothesis: each append re-reads and hashes the whole transcript. Unprofiled; a `sample` attach on Daily needs owner approval. | | `cutover-install-tooling-1` | medium | `scripts/plan-headless-install.mjs`; `macos/*/Packaging/` templates | A new Mac cannot be set up as a collector from the repo alone: there is no settings-block template, identity initialization step, credentials provisioning, or apply/upgrade/rollback mode, and no repo script creates the HQ index-role job. The dry-run plan also reports every role's job as disabled with RunAtLoad/KeepAlive off, while the remote-server plist template sets RunAtLoad and KeepAlive to true. | | `cutover-web-editor-hardening-1` | medium/security, needs triage | `macos/EngramRemoteServer/Core/WebAuthSessionStore.swift`; `WebWriteRoutes.swift` | Web login throttling is one global five-attempts window with no per-client partition, so anyone who can reach the origin can delay the editor's login. Unverified risk: an editor can change AI/embedding base URLs while stored keys stay in place. Project moves from Web are audited with actor `mcp`. `docs/invariants.md` now records Web authority; these behaviors are not guarantees there. Since 2026-10-08 (`docs/superpowers/specs/2026-10-08-web-tailscale-identity-auth-design.md`) a deployment can set `ENGRAM_REMOTE_WEB_AUTH=tailscale-serve`, where no credential or throttle exists and the session records the tailnet login; the audit actor stays `mcp` until that design's phase 2 lands. | | `cutover-role-surface-1` | low | `macos/EngramMCP/Core/MCPToolRegistry.swift` | In `collector`/`replica`/invalid roles MCP still advertises the full tool catalog while every call returns the unavailable message. | diff --git a/docs/reviews/2026-09-07-collector-source-retirement-checklist.md b/docs/reviews/2026-09-07-collector-source-retirement-checklist.md index 9b014125..40abff78 100644 --- a/docs/reviews/2026-09-07-collector-source-retirement-checklist.md +++ b/docs/reviews/2026-09-07-collector-source-retirement-checklist.md @@ -18,10 +18,21 @@ - The real-binary chain tests that cover every source skip unless `ENGRAM_COLLECTOR_BINARY`, `ENGRAM_SERVICE_BINARY` and `ENGRAM_REMOTE_SERVER_BINARY` are set; no CI workflow sets them. + 2026-10-18: PR #475 adds `.github/workflows/real-binary.yml`, a non-required + weekly / dispatch / PR gate that builds the three Debug binaries, sets the + variables and fails unless the expected test set executed; its hosted run + passed 49 of 50 with only the browser demo skipped by design. - Daily resource acceptance is still open. The last recorded full Daily window (observer 49875, Daily build 92844) measured 13.178% CPU against the 2% target; observer 7119 for the later capture-schedule build has no recorded result. The 2026-09-13 handoff deferred resource work; it did not pass. + 2026-10-18 read-only window (PID 96925, binary `b83ada40…5c01` from the + 2026-10-17 deployment, `pollIntervalMilliseconds` 10000, 16 roots converged + before and after, host in active use): 61 samples over 1803 s, CPU 5.891% + (FAIL), max RSS 81.2 MiB (PASS), PID stable, no re-walk; 37 publications + ACKed by both replicas, 35 from `daily-claude`. Quiet floor 1.5-3.5%, bursts + to 29% during transcript appends. Diagnostics D1-D3 negative (details in + `CHANGELOG.md` 2026-10-18). - **Resolved by owner decision D3 (2026-10-02, recorded here 2026-10-07):** the "Registered sources" rule says the old ingestion path must remain enabled wherever a source is enabled, and the verifier says not to change jobs. The @@ -201,7 +212,12 @@ and same-snapshot HTTP walks passed all17 streams; see This supersedes the earlier undifferentiated overview503 note for the observed paged flow, without claiming cold/p95 acceptance. Daily resource acceptance remains open: current backfill measured24.492% of one core /75.172MiB over60s. -The repeated Cursor peer scan is the next measured optimization lead. Neither a +The repeated Cursor peer scan is the next measured optimization lead. +(2026-10-18: that lead was mitigated on 2026-09-12 by the 30 s hint cache and +the 10 s gate before the 13.178% window; the 2026-10-18 window above shows a +polling floor near the target plus bursts tied to Claude Code transcript +appends, so the next lead is the per-change capture cost of large appended +transcripts, unprofiled; `sample` on Daily needs owner approval.) Neither a zero historical queue nor reboot was added as a new retirement prerequisite. Daily cutover update (2026-09-12): the old com.engram.service job is now disabled From 120bc7f24780ddd06cb6d7e1f9eb7ea9b6d03cee Mon Sep 17 00:00:00 2001 From: reviewer Date: Sun, 18 Oct 2026 13:18:52 +0800 Subject: [PATCH 2/3] docs: record the D7 purge apply and the HQ service-index move to 9ef7fb4f Claude-Session: https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v --- CHANGELOG.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++----- MEMO.md | 4 +++- docs/TODO.md | 14 ++++++------ 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4df7d48a..922df6d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,61 @@ All notable changes to this project will be documented in this file. Format based on [Keep a Changelog](https://keepachangelog.com/). +## D7 legacy grok/pi purge applied on HQ; service-index moved to main `9ef7fb4f` (2026-10-18) + +Owner authorization, in order: "批准" for the D7 dry-run report, then +"如果 dry-run 没问题,就批准部署和 apply" (deploy and apply if the dry run is +clean). The offline report and the live preview were both clean, so both steps +ran. + +**Deploy.** Release/arm64 built from a detached worktree at `9ef7fb4f` +(`main` with #476-#478; no schema migration since `b95d99ad`), packaged with +`macos/scripts/package-service.sh` after `--dry-run`; `--verify-only` PASS in +scratch and again at the destination, `codesign --verify --deep --strict` ok. +`bin/EngramService` sha256 +`2714e296484802ddda31f732a7e1ecade325239a2e63a7e21b5c2b3d86c114a2`, +BUILD-METADATA sourceRevision `9ef7fb4f01c60e40406bfcd864add09127a7170e`. +Package `hq/service-index-main-9ef7fb4f-20261018`; plist backup +`state/service-index/persistent/main-9ef7fb4f-20261018-job-before.plist`; only +`ProgramArguments[0]` changed; bootout 05:13:31Z, bootstrap 05:13:34Z, new +PID 625 logged the listening line, stderr stayed at 0 bytes, receiver +`127.0.0.1:18787` and tailnet Web `/v1/health` 200. Rollback: restore the +backed-up plist and bootstrap it; `service-index-main-b95d99ad-20261017` is +kept. The operator CLI is `EngramCLI` Release from the same build (sha256 +`6670a54ee4b5892eaea8703dc9fe5511b33e36cb204b1cfed2c400e51b59d094`), run from +DerivedData, not installed anywhere. + +**Pre-apply checks.** Live `EngramCLI maintenance legacy-local-purge preview` +through the new service (16 s) reproduced the approved values exactly: +`sessionCount` 6,191, `planToken` +`9fa54d7d1ab87778faf42d525076f8544b322207313ed06b4bb916f9d8890b8f`, every +blocking dependent 0. Rollback copy taken right before the apply with +`sqlite3 -readonly SRC "VACUUM INTO ..."` (05:14:31-05:16:16Z, 12.8 GB, +quick_check ok, 45,815 sessions, 6,191 candidates) at +`state/service-index/persistent/d7-rollback-20261018/index.sqlite`. Restore +path: bootout, replace the database file and remove its `-wal`/`-shm`, +bootstrap; anything ingested after 05:14Z would have to be re-delivered. + +**Apply.** `apply --expect-sessions 6191 --expect-token 9fa54d7d…` ran +05:17:15-05:17:45Z (30 s, inside the token-protected 10-minute client +budget): `sessionsDeleted` 6,191; derived rows deleted sessionsFts 51,937, +ftsMap 51,937, session_index_jobs 11,578, session_tools 23,232, +session_costs 6,191, session_work_beats 531, everything else 0; audit row +`legacy_local_purge.v1.2026-10-18T05:17:15Z` in `metadata`. + +**Verified independently.** Re-preview: `sessionCount` 0. Read-only SQL on +the live index: candidate predicate 0, `origin=local` rows of any source 0, +capture-bound grok 866 and pi 573 unchanged, no orphan `fts_map` or +`session_index_jobs` rows, 39,626 sessions, ledger pending 0, audit row +present. Service PID 625 still up, stderr 0 bytes, receiver and Web 200. +Freed pages stay in the file until an owner-scheduled vacuum; that is +outside D7. This closes the D7 TODO item. + +Note: a pre-apply check suspected the CLI's IPC timeout (30 s default) was +too short for a 13 GB index; a throwaway repro test showed token-protected +commands already get the 10-minute `mutatingCommandTimeout`, so no change +was made. + ## Open-item cleanup by Opus workflows: four TODO items shipped, Daily CPU measured, two items need owner decisions (2026-10-18) Owner request: "继续组织opus清理开放项" (keep orchestrating Opus to clear the open @@ -74,12 +129,8 @@ changed. 6,191, work beats 531; retained file_index_state 6,191; the 866 grok and 573 pi capture-bound rows are outside the predicate. The candidate count has not grown since 2026-10-07, so the HQ role gate holds. The owner - approved this report on 2026-10-18 ("批准"; the approval covers the report, - not the host steps). Remaining D7 steps, each separately authorized: deploy - service-index and EngramCLI to HQ from a `main` containing #478, take a - fresh rollback `.backup`, confirm `legacy-local-purge preview` on the live - socket reproduces `sessionCount` 6,191 and the approved `planToken`, then - apply and re-preview to 0. + approved this report on 2026-10-18 and then authorized the deploy and apply; + both are recorded in the entry above. Verification per PR is in each PR description (implementer plus independent re-run with the test.yml HOME isolation; verifiers also ran mutation checks, diff --git a/MEMO.md b/MEMO.md index 3a6369f2..06398f4c 100644 --- a/MEMO.md +++ b/MEMO.md @@ -4,11 +4,13 @@ ### 2026-10-18 +- [变更] 业主授权(「批准」报告,随后「如果 dry-run 没问题,就批准部署和 apply」)后:HQ service-index 从 `b95d99ad` 换到 main `9ef7fb4f`(PID 625,stderr 0 字节,receiver/Web 200,plist 备份与旧包保留可回滚);live preview 复现 6,191 / `9fa54d7d…`,`VACUUM INTO` 做了 12.8 GB 回滚副本,然后 apply:删除 6,191 个旧 grok/pi 会话及派生行(FTS 51,937、index jobs 11,578、tools 23,232 等),审计键 `legacy_local_purge.v1.2026-10-18T05:17:15Z`。详见 `CHANGELOG.md`。 +- [验证] re-preview 为 0;只读 SQL:候选 0、全库 `origin=local` 0、capture 绑定的 grok 866 / pi 573 未动、无孤儿派生行、账本 pending 0。D7 关闭。 - [变更] 业主要求继续用 Opus 清理开放项:两轮 Workflow(7 个只读 scoping agent、15 个实现/复核 agent),4 项落地为 PR 并按序合并:#475 `__SHA_475__` W6.2 真实二进制门禁(非必需工作流 + 校验脚本,跳过即失败);#476 `7a48d19d` App 在 collector/replica 角色下的「Open Web Reader」入口(新可选键 `webReaderURL`,仅 https);#477 `9f131f25` W4.7 HQ 侧 `collectorEpochDryRun`/`collectorApproveEpoch` IPC + `EngramCLI collector-epoch`(令牌保护、不进 Web);#478 `9ef7fb4f` D7 旧 `origin=local` grok/pi 清理的 dry-run/apply 工具与离线报告模式。均未部署,未改任何主机。详见 `CHANGELOG.md`。 - [验证] 每个 PR 由实现者与独立复核者各跑一遍测试(ServiceCore 用 CI 的 HOME 隔离),复核者另做了变异验证(去掉关键守卫后对应测试确实失败);PR 的 required CI 全绿后才合并。#475 自身触发的托管 `Real-binary chain` 结果:第三次运行通过(run 39093667839,头 eb62c039):`result=pass expected=50 passed=49 skipped=1 failed=0`,大历史测试 429.6 秒;前两次只在该测试上失败(240 秒作用域期限、夹具 0.5 秒副本请求超时),已给托管机加 `--timeout-scale 3`(只拉长期限,不改断言)。 - [排查] Daily collector 30 分钟只读测量(10-17 23:49Z 起,PID 96925,`b83ada40…`,poll 10 s,16 根全程收敛):CPU 5.891%(目标 ≤ 2%,未达标)、最大 RSS 81.2 MiB(达标);安静段地板 1.5% 到 3.5%,峰值与 35 条 Claude Code 转写发布对应;TODO 里的 Cursor peer scan 线索 9-12 已缓解,D1 到 D3 判别诊断均为阴性。新线索:大转写文件每次追加的捕获成本,未剖析(`sample` 需业主批准)。该项保持开放。 - [新增] followup `collector-epoch-producer-1`:collector 从不在同一 source instance 下轮换 epoch,spool 重置到 HQ 表现为新 instance,provisioning 会报 `overlappingRoot`;W4.7 新命令只覆盖设计假设的同 instance 场景,生产者侧待业主决定。 -- [验证] D7 dry-run 报告已从 HQ 库只读快照(02:24Z,`VACUUM INTO`,13.4 GB,quick_check ok)生成(合并后 main `9ef7fb4f` 的二进制重跑,JSON 逐字节一致)并经独立 SQL 交叉核对:候选 6,191 行(grok 5,959、最新 indexed_at 10-07;pi 232),阻塞依赖全 0,`purgeAllowed=true`,planToken `9fa54d7d…90b8f`;capture 绑定的 grok 866 / pi 573 行正确排除;候选数自 10-07 起未增长。业主已于 10-18 批准该报告(仅报告,不含主机步骤);HQ 部署、回滚备份、live preview 复核与 apply 另需逐项授权。 +- [验证] D7 dry-run 报告已从 HQ 库只读快照(02:24Z,`VACUUM INTO`,13.4 GB,quick_check ok)生成(合并后 main `9ef7fb4f` 的二进制重跑,JSON 逐字节一致)并经独立 SQL 交叉核对:候选 6,191 行(grok 5,959、最新 indexed_at 10-07;pi 232),阻塞依赖全 0,`purgeAllowed=true`,planToken `9fa54d7d…90b8f`;capture 绑定的 grok 866 / pi 573 行正确排除;候选数自 10-07 起未增长。业主已于 10-18 批准该报告并授权部署与 apply(见本节首条)。 - [未验证] W4.1 别名对账、W4.5 旧回执引导需要业主决策(关闭 / 按设计建 / 重定范围),详见 `CHANGELOG.md`。 ### 2026-10-17 diff --git a/docs/TODO.md b/docs/TODO.md index 41a7e5d5..425323f5 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -130,13 +130,13 @@ authorizes host changes. role gate), every blocking dependent 0, `purgeAllowed` true, `planToken` `9fa54d7d1ab87778faf42d525076f8544b322207313ed06b4bb916f9d8890b8f`; see `CHANGELOG.md` 2026-10-18. The owner approved that report on 2026-10-18 - ("批准": `sessionCount` 6,191, `planToken` `9fa54d7d…90b8f`). Still open, - each separately authorized: the HQ service-index and EngramCLI deploy from - a `main` that contains #478, a fresh rollback `.backup` of the live index, - `EngramCLI maintenance legacy-local-purge preview` on the live socket - reproducing the approved count and token, then `apply --expect-sessions - 6191 --expect-token `. Done when the purge clears the rows plus - their derived rows and a re-run preview reports 0. + ("批准": `sessionCount` 6,191, `planToken` `9fa54d7d…90b8f`). Done + 2026-10-18: HQ service-index deployed from `9ef7fb4f`, the live preview + reproduced the approved values, a `VACUUM INTO` rollback copy was taken, + and the apply deleted the 6,191 rows plus their derived rows (audit + `legacy_local_purge.v1.2026-10-18T05:17:15Z`); re-preview 0, no + `origin=local` rows left, capture-bound grok/pi rows untouched. See + `CHANGELOG.md` 2026-10-18. Earlier status: no implementation-ready engineering task is selected as of 2026-08-16. From c19ac1cafdb24a83bdf747ec0b7ae1b1572fe0bd Mon Sep 17 00:00:00 2001 From: reviewer Date: Sun, 18 Oct 2026 13:42:02 +0800 Subject: [PATCH 3/3] docs: fill the #475 merge SHA and final hosted gate result Claude-Session: https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v --- CHANGELOG.md | 12 ++++++++++-- MEMO.md | 4 ++-- docs/TODO.md | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 922df6d5..ff25285e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,7 +71,7 @@ changed. **Shipped (PRs opened from this session; merged in the order #477, #476, #478, #475, each after its required checks passed on a branch updated to the then-current `main`):** -- PR #475 `__SHA_475__` — W6.2 real-binary chain gate. +- PR #475 `5b5b09af` — W6.2 real-binary chain gate. `.github/workflows/real-binary.yml` (weekly, `workflow_dispatch`, and PRs touching the gate; **not** a required check, `CI Gate` contract unchanged), `scripts/ci/run-real-binary-gate.sh` (builds Debug EngramCollector / @@ -81,7 +81,15 @@ changed. expected test set executed (a green run with 50 skips is a fail; proven locally: `result=fail expected=50 passed=0 skipped=50`). Local full run: `result=pass expected=50 passed=49 skipped=1` (browser demo skipped by - design). Hosted result on the PR: pass on the third run (run 39093667839, head eb62c039): `result=pass expected=50 passed=49 skipped=1 failed=0`, large-history test 429.6 s. The first two hosted runs failed only on that test (240 s scope deadline, then the fixture's 0.5 s replica request timeout), so the gate now scales its deadlines and fixture HTTP timeouts by `--timeout-scale 3` on hosted runners; assertions and the expected test set are unchanged. + design). Hosted runs on the PR: every run executed all 50 tests and only + the 114 MB large-history test ever failed. Run 1 hit its fixed 240 s scope + deadline, run 2 the fixture's 0.5 s replica request timeout, run 3 + (39093667839) passed with that test at 429.6 s, run 4 (39097383289) hit the + 3x deadline with HQ ingest still running after 12 min. The runner's speed + varies about 2x between runs, so the merged gate scales the scope deadlines + and the fixture's replica HTTP timeouts by `--timeout-scale 6` with a + 60-minute job budget; assertions and the expected test set are unchanged. + Final run on the merged head (39098816343, 10f5ab21): success. - PR #476 `7a48d19d` — App "Open Web Reader" action in `collector`/`replica` roles, driven by a new optional `webReaderURL` key in `settings.json` (https only, host required, no userinfo/query/fragment), disabled with a diff --git a/MEMO.md b/MEMO.md index 06398f4c..27e503dc 100644 --- a/MEMO.md +++ b/MEMO.md @@ -6,8 +6,8 @@ - [变更] 业主授权(「批准」报告,随后「如果 dry-run 没问题,就批准部署和 apply」)后:HQ service-index 从 `b95d99ad` 换到 main `9ef7fb4f`(PID 625,stderr 0 字节,receiver/Web 200,plist 备份与旧包保留可回滚);live preview 复现 6,191 / `9fa54d7d…`,`VACUUM INTO` 做了 12.8 GB 回滚副本,然后 apply:删除 6,191 个旧 grok/pi 会话及派生行(FTS 51,937、index jobs 11,578、tools 23,232 等),审计键 `legacy_local_purge.v1.2026-10-18T05:17:15Z`。详见 `CHANGELOG.md`。 - [验证] re-preview 为 0;只读 SQL:候选 0、全库 `origin=local` 0、capture 绑定的 grok 866 / pi 573 未动、无孤儿派生行、账本 pending 0。D7 关闭。 -- [变更] 业主要求继续用 Opus 清理开放项:两轮 Workflow(7 个只读 scoping agent、15 个实现/复核 agent),4 项落地为 PR 并按序合并:#475 `__SHA_475__` W6.2 真实二进制门禁(非必需工作流 + 校验脚本,跳过即失败);#476 `7a48d19d` App 在 collector/replica 角色下的「Open Web Reader」入口(新可选键 `webReaderURL`,仅 https);#477 `9f131f25` W4.7 HQ 侧 `collectorEpochDryRun`/`collectorApproveEpoch` IPC + `EngramCLI collector-epoch`(令牌保护、不进 Web);#478 `9ef7fb4f` D7 旧 `origin=local` grok/pi 清理的 dry-run/apply 工具与离线报告模式。均未部署,未改任何主机。详见 `CHANGELOG.md`。 -- [验证] 每个 PR 由实现者与独立复核者各跑一遍测试(ServiceCore 用 CI 的 HOME 隔离),复核者另做了变异验证(去掉关键守卫后对应测试确实失败);PR 的 required CI 全绿后才合并。#475 自身触发的托管 `Real-binary chain` 结果:第三次运行通过(run 39093667839,头 eb62c039):`result=pass expected=50 passed=49 skipped=1 failed=0`,大历史测试 429.6 秒;前两次只在该测试上失败(240 秒作用域期限、夹具 0.5 秒副本请求超时),已给托管机加 `--timeout-scale 3`(只拉长期限,不改断言)。 +- [变更] 业主要求继续用 Opus 清理开放项:两轮 Workflow(7 个只读 scoping agent、15 个实现/复核 agent),4 项落地为 PR 并按序合并:#475 `5b5b09af` W6.2 真实二进制门禁(非必需工作流 + 校验脚本,跳过即失败);#476 `7a48d19d` App 在 collector/replica 角色下的「Open Web Reader」入口(新可选键 `webReaderURL`,仅 https);#477 `9f131f25` W4.7 HQ 侧 `collectorEpochDryRun`/`collectorApproveEpoch` IPC + `EngramCLI collector-epoch`(令牌保护、不进 Web);#478 `9ef7fb4f` D7 旧 `origin=local` grok/pi 清理的 dry-run/apply 工具与离线报告模式。均未部署,未改任何主机。详见 `CHANGELOG.md`。 +- [验证] 每个 PR 由实现者与独立复核者各跑一遍测试(ServiceCore 用 CI 的 HOME 隔离),复核者另做了变异验证(去掉关键守卫后对应测试确实失败);PR 的 required CI 全绿后才合并。#475 自身触发的托管 `Real-binary chain` 结果:第三次运行通过(run 39093667839,头 eb62c039):`result=pass expected=50 passed=49 skipped=1 failed=0`,大历史测试 429.6 秒;四次运行都只在该测试上失败过(240 秒期限、0.5 秒副本请求超时、3 倍期限),托管机速度两次之间差约 2 倍,合并版用 `--timeout-scale 6` 与 60 分钟作业预算(只拉长期限,不改断言)。 - [排查] Daily collector 30 分钟只读测量(10-17 23:49Z 起,PID 96925,`b83ada40…`,poll 10 s,16 根全程收敛):CPU 5.891%(目标 ≤ 2%,未达标)、最大 RSS 81.2 MiB(达标);安静段地板 1.5% 到 3.5%,峰值与 35 条 Claude Code 转写发布对应;TODO 里的 Cursor peer scan 线索 9-12 已缓解,D1 到 D3 判别诊断均为阴性。新线索:大转写文件每次追加的捕获成本,未剖析(`sample` 需业主批准)。该项保持开放。 - [新增] followup `collector-epoch-producer-1`:collector 从不在同一 source instance 下轮换 epoch,spool 重置到 HQ 表现为新 instance,provisioning 会报 `overlappingRoot`;W4.7 新命令只覆盖设计假设的同 instance 场景,生产者侧待业主决定。 - [验证] D7 dry-run 报告已从 HQ 库只读快照(02:24Z,`VACUUM INTO`,13.4 GB,quick_check ok)生成(合并后 main `9ef7fb4f` 的二进制重跑,JSON 逐字节一致)并经独立 SQL 交叉核对:候选 6,191 行(grok 5,959、最新 indexed_at 10-07;pi 232),阻塞依赖全 0,`purgeAllowed=true`,planToken `9fa54d7d…90b8f`;capture 绑定的 grok 866 / pi 573 行正确排除;候选数自 10-07 起未增长。业主已于 10-18 批准该报告并授权部署与 apply(见本节首条)。 diff --git a/docs/TODO.md b/docs/TODO.md index 425323f5..5215b7c3 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -68,7 +68,7 @@ authorizes host changes. `CollectorBinaryShadowIntegrationTests.swift` skips unless three binary-path environment variables are set, and no CI workflow sets them. Done when CI sets them or a documented manual gate with a receipt exists. - Update 2026-10-18 (branch `ci/real-binary-gate-20261018`): shipped the + Done 2026-10-18: merged as PR #475 (`5b5b09af`), hosted run 39098816343 passed with `--timeout-scale 6`. Shipped the non-required `.github/workflows/real-binary.yml` (weekly Sunday 20:17 UTC, `workflow_dispatch`, and pull requests that touch its own five gate paths; not in `test.yml` or `ci-gate`) and `scripts/ci/run-real-binary-gate.sh`,