Summary
Small code-hygiene items from the 2026-05-17 full-repo review. Each is one-line-to-one-block in size. Bundled because they're cleanup that's most efficiently done in one pass.
Magic numbers to name
packages/engine/src/api/server.ts:576, 611, 657 — chunkBytes: 1024 * 1024 magic three times. Extract const COPY_CHUNK_BYTES = 1024 * 1024; at module top.
packages/engine/src/api/server.ts:318 — 'cache-control': 'max-age=300' magic. Named constant.
packages/engine/src/api/preview-cache.ts:14-15, 107 — MAX_CACHE_BYTES and EVICT_INTERVAL are named (good); the eviction fraction 0.2 at line 107 is bare. Extract EVICT_FRACTION = 0.2.
packages/engine/src/scan/orchestrator.ts:63-64 — PROGRESS_INTERVAL_MS = 1000 and PROGRESS_FILE_CADENCE = 50 are named but live inside the function body; hoist to module level (also called out in M19).
packages/engine/src/organize/collision.ts:10 — MAX_SUFFIX_ATTEMPTS = 1000 magic; named but warrants a one-line comment.
Single-letter / cryptic names
packages/engine/src/rules/matcher.ts:5 — m for rule.match. Rename to match (or inline).
packages/engine/src/rules/template.ts:33 — f parameter in dateOf, yearOf, monthOf, dayOf. Rename to file.
packages/engine/src/scan/walker.ts:136 — let s for stat result; rename to fileStat.
packages/engine/src/scan/walker.ts:53, 78 — let entries; and let targetStat; without explicit types — works via inference but a one-line annotation clarifies for grep.
Logging consistency
packages/engine/src/organize/undo.ts:213-218 — console.error('undo-catalog-update-failed', { ... }) uses raw console.error while reconcile.ts:8 builds a structured logger. Use the same logger.
packages/engine/src/log.ts:31 — JSON.stringify({ ts, level, msg, ...base, ...fields }) — if fields contains a ts/level/msg key it silently overrides the canonical fields. Re-spread fields first, then the canonical keys; or document the precedence with a comment.
Dead code
packages/engine/src/scan/orchestrator.ts:99 — entry.path.slice(0, entry.path.length - entry.name.length) reinvents path.dirname. (Also called out in M19.)
packages/engine/src/rules/defaults.ts:14 — return 6 is a magic number that has to stay in sync with the array length; return defaultRules(cutoff).length (compute once and reuse).
Other
packages/engine/src/rules/defaults.ts:4 — TWO_YEARS_MS = 365 * 2 * 24 * 60 * 60 * 1000 ignores leap years; the actual UX-facing setting lives in Settings.recentArchiveCutoffYears. Flag the disconnect — either honor that setting or annotate why this seeder ignores it.
packages/engine/src/roles/defaults.ts:10 — DEFAULT_FILL_THRESHOLD_PERCENT = 90 is duplicated as a literal 90 across multiple test files and the RoleDefinition schema docs. Export from @fileorganizer/shared so tests reference the same constant.
Background
From the 2026-05-17 multi-agent full-repo review.
Acceptance criteria
Files affected (likely)
Each item names its file; most are 1-3 line changes.
Suggested approach
Group by file, work file-by-file. The whole issue is mechanical — likely a 30-minute PR.
Out of scope
- Larger refactors (M19 covers
orchestrator.ts; this issue scopes to the line-level magic items)
- Type-narrowing improvements not flagged here
References
- Standards:
standards/coding-standards.md
Summary
Small code-hygiene items from the 2026-05-17 full-repo review. Each is one-line-to-one-block in size. Bundled because they're cleanup that's most efficiently done in one pass.
Magic numbers to name
packages/engine/src/api/server.ts:576, 611, 657—chunkBytes: 1024 * 1024magic three times. Extractconst COPY_CHUNK_BYTES = 1024 * 1024;at module top.packages/engine/src/api/server.ts:318—'cache-control': 'max-age=300'magic. Named constant.packages/engine/src/api/preview-cache.ts:14-15, 107—MAX_CACHE_BYTESandEVICT_INTERVALare named (good); the eviction fraction0.2at line 107 is bare. ExtractEVICT_FRACTION = 0.2.packages/engine/src/scan/orchestrator.ts:63-64—PROGRESS_INTERVAL_MS = 1000andPROGRESS_FILE_CADENCE = 50are named but live inside the function body; hoist to module level (also called out in M19).packages/engine/src/organize/collision.ts:10—MAX_SUFFIX_ATTEMPTS = 1000magic; named but warrants a one-line comment.Single-letter / cryptic names
packages/engine/src/rules/matcher.ts:5—mforrule.match. Rename tomatch(or inline).packages/engine/src/rules/template.ts:33—fparameter indateOf,yearOf,monthOf,dayOf. Rename tofile.packages/engine/src/scan/walker.ts:136—let sfor stat result; rename tofileStat.packages/engine/src/scan/walker.ts:53, 78—let entries;andlet targetStat;without explicit types — works via inference but a one-line annotation clarifies for grep.Logging consistency
packages/engine/src/organize/undo.ts:213-218—console.error('undo-catalog-update-failed', { ... })uses rawconsole.errorwhilereconcile.ts:8builds a structured logger. Use the same logger.packages/engine/src/log.ts:31—JSON.stringify({ ts, level, msg, ...base, ...fields })— iffieldscontains ats/level/msgkey it silently overrides the canonical fields. Re-spreadfieldsfirst, then the canonical keys; or document the precedence with a comment.Dead code
packages/engine/src/scan/orchestrator.ts:99—entry.path.slice(0, entry.path.length - entry.name.length)reinventspath.dirname. (Also called out in M19.)packages/engine/src/rules/defaults.ts:14—return 6is a magic number that has to stay in sync with the array length; returndefaultRules(cutoff).length(compute once and reuse).Other
packages/engine/src/rules/defaults.ts:4—TWO_YEARS_MS = 365 * 2 * 24 * 60 * 60 * 1000ignores leap years; the actual UX-facing setting lives inSettings.recentArchiveCutoffYears. Flag the disconnect — either honor that setting or annotate why this seeder ignores it.packages/engine/src/roles/defaults.ts:10—DEFAULT_FILL_THRESHOLD_PERCENT = 90is duplicated as a literal90across multiple test files and theRoleDefinitionschema docs. Export from@fileorganizer/sharedso tests reference the same constant.Background
From the 2026-05-17 multi-agent full-repo review.
Acceptance criteria
console.errorinundo.ts:213-218replaced with the threaded structured logger (the logger needs to be available onUndoOptionsor threaded; if not, settle for aconsole.errorconsistent withlog.tsshape).log.ts:31field-spread reordered or commented.orchestrator.ts:99usespath.dirname.defaults.ts:14returnsdefaultRules(cutoff).length.DEFAULT_FILL_THRESHOLD_PERCENTexported from@fileorganizer/sharedand used in tests.TWO_YEARS_MSeither honorsrecentArchiveCutoffYearsor has a one-line comment explaining the seeder's deliberate independence from settings.Files affected (likely)
Each item names its file; most are 1-3 line changes.
Suggested approach
Group by file, work file-by-file. The whole issue is mechanical — likely a 30-minute PR.
Out of scope
orchestrator.ts; this issue scopes to the line-level magic items)References
standards/coding-standards.md