FAIR-band: in-band [1/30] — operator-empirical friction during post-#11485 verification; quick-win MX-friction reduction completing the post-#11480 substrate's full operator-visibility win across INFO + WARN tiers.
Evidence: L2 (8/8 IssueSyncer specs pass including new #11486 case; 1.0s runtime) → L4 required (operator re-runs npm run ai:sync-github-workflow; WARN volume bounded to genuine vX.Y.Z → vX.Y.Z shifts, single-emit per issue).
Summary
Filter the line-377 ARCHIVE ANOMALY WARN to fire only when both oldVersion and version parse as valid semver tags via semver.valid(semver.clean(s)). Demote migration-state mismatches (one or both sides not valid semver) to a [ARCHIVE MIGRATION] DEBUG channel. Add a #warnedAnomalies instance Set (cleared at top of pullFromGitHub) to dedupe across the three #planBuckets call sites within a single sync cycle.
Empirical motivation
Operator 2026-05-16T19:33Z npm run ai:sync-github-workflow paste (SIGINT after thousands of lines):
[WARN] 🚨 [ARCHIVE ANOMALY] Issue #3285 closedAt shift detected: moving from bucket 'vneo.d.ts - Typescript definitions for all neo framework classes' to 'v8.1.0'. Dry-run review required.
[WARN] 🚨 [ARCHIVE ANOMALY] Issue #3286 closedAt shift detected: moving from bucket 'vneo.d.ts - Typescript definitions for all neo framework classes' to 'v8.1.0'. Dry-run review required.
[WARN] 🚨 [ARCHIVE ANOMALY] Issue #3287 closedAt shift detected: moving from bucket 'vNeo-Material Component Library v0.1' to 'v8.1.0'. Dry-run review required.
[WARN] 🚨 [ARCHIVE ANOMALY] Issue #7910 closedAt shift detected: moving from bucket 'v11.12.0' to 'v11.13.0'. Dry-run review required.
... (each issue line appears TWICE; thousands of lines total)
Two compounding root causes:
- Migration-state false positives:
oldVersion is derived from the cached path's directory name (IssueSyncer.mjs:310-317). During ADR 0004's clean-cut, every historically-archived closed issue has an oldVersion from the pre-cut naming scheme (title-derived strings prefixed with v), while the new time-based resolution returns a vX.Y.Z release tag. Sealed-chunk enforcement at L569/L575 already prevents these from causing any actual move — pure noise.
- Double emission:
#planBuckets is called from lines 547 (main sync), 783 (re-fetch path), and 982 (reconcile step). Each call walks the merged-issue set; same issue WARN'd at every call site.
What changed
| File |
Change |
ai/services/github-workflow/sync/IssueSyncer.mjs |
import semver from 'semver'; + #warnedAnomalies = new Set() field + filtered+deduped WARN at line ~387 + clear() at top of pullFromGitHub |
test/playwright/unit/ai/services/github-workflow/IssueSyncer.spec.mjs |
New test: ARCHIVE ANOMALY WARN fires only when both buckets parse as valid semver tags (#11486) — exercises migration-shape vs valid-semver-shift scenarios in one fixture |
Total: 2 files, +169 / -1 lines.
What's preserved
- Real release-boundary WARN signal remains intact at default CLI level. Genuine
vX.Y.Z → vX.Y.Z shifts (e.g. #7910 v11.12.0 → v11.13.0) still emit WARN — operator visibility into actionable anomalies preserved.
error level untouched — failures still print.
- Sealed-chunk enforcement (L569 + L575) — untouched; the WARN filter just stops emitting WARN for moves that sealed-chunk semantics already prevent.
Test plan
Authority anchors
- Direct parent: PR #11485 (per-item INFO→DEBUG, merged 2026-05-16T19:21Z) — this is the natural FAIR follow-up completing the post-#11480 substrate's full operator-visibility win
- Substrate parent: PR #11480 (logger filtering substrate, merged) — provides the level discipline this PR builds on
- Substrate library:
semver@^7.7.4 already in package.json; precedent at ai/services/github-workflow/HealthService.mjs:416
- Operator hint: 2026-05-16T19:43Z
"semver" : "^7.7.4" package.json reference — challenged my original hand-rolled regex prescription; adopted in Avoided Traps section of #11486 ticket
- Empirical anchor: operator paste 2026-05-16T19:33Z showing thousands of WARN lines + SIGINT exit
Avoided traps
- Hand-rolled regex like
/^v\d+\.\d+\.\d+$/: rejected per operator hint — semver library handles pre-release tags (v8.1.0-rc.1) + build metadata (v8.1.0+build.123) + future tag-format evolution correctly; regex would miss these.
- Removing the WARN entirely: rejected — real
vX.Y.Z → vX.Y.Z shifts ARE actionable; only false positives during migration are quieted.
- Suppressing all
[ARCHIVE ANOMALY] via a CLI flag: rejected — operator visibility into genuine anomalies must remain default-on.
- One-time migration script to rewrite cached
oldVersion strings: rejected per ADR 0004's "no migration scripts. clean cut" mandate — cached metadata refreshes naturally as the sync runs; noise self-resolves after one clean-cut cycle.
- Demoting WARN to INFO: rejected — WARN level is correct for the genuine-anomaly case; demoting loses signal entirely.
- Suppressing across entire daemon lifetime: rejected — dedupe set is reset per sync cycle so issue-shifts across separate sync runs still surface; we only suppress within a single sync.
Related
- Parent context: PR #11485 (per-item INFO→DEBUG sweep, merged)
- Substrate parent: PR #11480 (logger filtering substrate, merged)
- Adjacent: GPT investigating orchestrator boot-time cadence (parallel substrate concern —
Orchestrator.start() → poll() fires summary + KB sync simultaneously, root-cause of the 19:27Z wedge). Complementary lane to this WARN-tier fix.
Resolves #11486
FAIR-band: in-band [1/30] — operator-empirical friction during post-#11485 verification; quick-win MX-friction reduction completing the post-#11480 substrate's full operator-visibility win across INFO + WARN tiers.
Evidence: L2 (8/8 IssueSyncer specs pass including new #11486 case; 1.0s runtime) → L4 required (operator re-runs
npm run ai:sync-github-workflow; WARN volume bounded to genuinevX.Y.Z → vX.Y.Zshifts, single-emit per issue).Summary
Filter the line-377
ARCHIVE ANOMALYWARN to fire only when botholdVersionandversionparse as valid semver tags viasemver.valid(semver.clean(s)). Demote migration-state mismatches (one or both sides not valid semver) to a[ARCHIVE MIGRATION]DEBUG channel. Add a#warnedAnomaliesinstance Set (cleared at top ofpullFromGitHub) to dedupe across the three#planBucketscall sites within a single sync cycle.Empirical motivation
Operator 2026-05-16T19:33Z
npm run ai:sync-github-workflowpaste (SIGINT after thousands of lines):Two compounding root causes:
oldVersionis derived from the cached path's directory name (IssueSyncer.mjs:310-317). During ADR 0004's clean-cut, every historically-archived closed issue has anoldVersionfrom the pre-cut naming scheme (title-derived strings prefixed withv), while the new time-based resolution returns avX.Y.Zrelease tag. Sealed-chunk enforcement at L569/L575 already prevents these from causing any actual move — pure noise.#planBucketsis called from lines 547 (main sync), 783 (re-fetch path), and 982 (reconcile step). Each call walks the merged-issue set; same issue WARN'd at every call site.What changed
ai/services/github-workflow/sync/IssueSyncer.mjsimport semver from 'semver';+#warnedAnomalies = new Set()field + filtered+deduped WARN at line ~387 +clear()at top ofpullFromGitHubtest/playwright/unit/ai/services/github-workflow/IssueSyncer.spec.mjsTotal: 2 files, +169 / -1 lines.
What's preserved
vX.Y.Z → vX.Y.Zshifts (e.g. #7910 v11.12.0 → v11.13.0) still emit WARN — operator visibility into actionable anomalies preserved.errorlevel untouched — failures still print.Test plan
npm run test-unit -- test/playwright/unit/ai/services/github-workflow/IssueSyncer.spec.mjs, 1.0s).vneo.d.ts - typescript definitions..., milestone=v8.1.0) emits 0 WARN + ≥1 DEBUG; valid-semver-shift issue (oldVersion=v11.12.0, milestone=v11.13.0) emits exactly 1 WARN containing both version strings + 0 migration DEBUG.origin/dev-tip freshness verified.@tobiumerge.npm run ai:sync-github-workflowpost-merge; WARN volume bounded to genuinevX.Y.Z → vX.Y.Zshifts (operator's prior paste showed only 1 such case: #7910).--verboseexposes the[ARCHIVE MIGRATION]DEBUG events for diagnostic use.Authority anchors
semver@^7.7.4already inpackage.json; precedent atai/services/github-workflow/HealthService.mjs:416"semver" : "^7.7.4"package.json reference — challenged my original hand-rolled regex prescription; adopted in Avoided Traps section of #11486 ticketAvoided traps
/^v\d+\.\d+\.\d+$/: rejected per operator hint —semverlibrary handles pre-release tags (v8.1.0-rc.1) + build metadata (v8.1.0+build.123) + future tag-format evolution correctly; regex would miss these.vX.Y.Z → vX.Y.Zshifts ARE actionable; only false positives during migration are quieted.[ARCHIVE ANOMALY]via a CLI flag: rejected — operator visibility into genuine anomalies must remain default-on.oldVersionstrings: rejected per ADR 0004's "no migration scripts. clean cut" mandate — cached metadata refreshes naturally as the sync runs; noise self-resolves after one clean-cut cycle.Related
Orchestrator.start()→poll()fires summary + KB sync simultaneously, root-cause of the 19:27Z wedge). Complementary lane to this WARN-tier fix.Resolves #11486