Skip to content

Say what the core/ and scripts/ deprecations actually mean - #3749

Open
dbernstein wants to merge 3 commits into
mainfrom
chore/correct-deprecated-package-guidance
Open

dbernstein wants to merge 3 commits into
mainfrom
chore/correct-deprecated-package-guidance

Conversation

@dbernstein

Copy link
Copy Markdown
Contributor

Description

Replaces the bare deprecated - no new code markers on /core and /scripts in CLAUDE.md with what the deprecations actually mean.

   - `/core` - Legacy miscellaneous components (**deprecated - no new code**)
+    - Exception: `/core/classifier` is the active home of classification logic (the BISAC
+      rulesets and code table, keyword matching, `WorkClassifier`). It has no replacement
+      elsewhere in the tree, so classification changes belong here.
...
-  - `/scripts` - Legacy CLI utilities (**deprecated - no new code**)
+  - `/scripts` - Legacy CLI utilities (**deprecated - put new logic in `/celery/tasks`**)
+    - The package is deprecated for *logic*, not for entry points. A thin `Script` subclass
+      here plus a `bin/` wrapper is still the only supported way to run something on demand,
+      and is still the expected pattern for dispatching a Celery task by hand. There is no
+      replacement framework: `palace-startup-task` is the only console script the project
+      ships, and it resolves into this package.

Documentation only. No code changes.

Motivation and Context

Both markers arrived together in 21df3c5d9 (2026-03-16), the commit that created the Claude Code config files. They were written as scaffolding rather than as separately-argued policy, and read literally neither is accurate. AI reviewers act on the literal reading and ask for moves that have nowhere to go — this has now fired on three consecutive PRs (#3726, #3736, #3737), each time citing CLAUDE.md as the authority and each time asking to "move this to the supported framework."

/scripts — there is no replacement framework

[project.scripts] entries one: palace-startup-task = "palace.manager.scripts.startup:create_startup_task" — it resolves into the deprecated package
cli/ package, click/typer app, palace command none exist
bin/ wrappers importing palace.manager.scripts directly 50 of ~74
...reaching it by subclassing Script / CollectionInputScript / InputScript 16 more, via the integration packages
the only exception palace.manager.customlists, a purpose-built argparse CLI for custom-list import/export

scripts/base.py also imports TimestampData from palace.manager.core.monitor, so the deprecated CLI framework is built on the deprecated core package.

The rule is not being followed either, which is the clearest evidence it is mis-stated. Since 2026-03-16 five new Script subclasses have landed — UpdateExpiredLicensesScript, OverdriveReaperScript, ReclassifyNullAudienceWorksScript, CustomListEntriesSweepScript, ResetNonBisacNonfictionSubjectsScript — along with five new bin/ wrappers.

The startup-task framework is not a substitute: it runs once per deployment and has no on-demand path. The repo treats the two as complementary and ships them together — 9c626b229 added a startup task, a Script and a bin/ wrapper in one commit for the null-audience repair.

What the deprecation is really protecting is business logic, and that convention is being followed: the logic lives in /celery/tasks, and the class here is a few lines that call .delay(). The wording now says that.

/core — true in general, false for the classifier

core/ excluding the classifier is net −2,001 lines over the last 12 months. It is actively being drained:

commit what came out
7a3274ea1 core/coverage.py, −1,364 (CoverageProvider machinery, PP-4468)
963b651b2 core/monitor.py, −230
49bc00071 core/equivalents_coverage.py −201, core/query/coverage.py −58
17b873e4d core/facets.py, −168

core/classifier/ over the same period is net +131, and is the only part of core/ still receiving behaviour changes (7d5b8a06a, ff2432b7e, and the PP-4849 work). There is no candidate home for it: packages/ contains only palace-opds and palace-util, neither with any classification code, and palace/manager/service/ is dependency-injection wiring. 23 modules across the tree import from palace.manager.core.classifier; all are consumers.

So the general rule stands and the exception is now stated, rather than left for each reviewer to rediscover.

How Has This Been Tested?

Documentation only — no code paths touched. pre-commit run --files CLAUDE.md passes, including PyMarkdown.

Checklist

  • I have updated the documentation accordingly.
  • All new and existing tests passed.

🤖 Generated with Claude Code

@claude

claude Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @dbernstein's task in 1m 37s —— View job


Summary

I checked each factual claim against the tree and they all hold. [project.scripts] has only palace-startup-task, and it points to palace.manager.scripts.startup. The classifier code tables (bisac.csv, dewey_1000.json, lcc_one_level.json) are in src/palace/manager/resources/classifier and are loaded through classifier_resources_dir(). The five Script subclasses named in the description each just call .delay() on a Celery task. There are also Script subclasses that live next to their integration (integration/license/{overdrive,bibliotheca,boundless,opds}/…). The head commit fixes Greptile's "only supported way" point. One wording gap is left in the /scripts bullet.

Details

Minor: CLAUDE.md:71-75

The new text says "put new logic in /celery/tasks" and that the package is "deprecated for logic", which covers every kind of script. But about 20 of the bin/ wrappers (bin/informational/*, bin/configuration/*) run synchronous commands whose output goes to the operator's terminal. scripts/informational.py and scripts/configuration.py write to output directly and never dispatch a task. A Celery task can't do that job, because its output would end up in the worker logs. Read literally, the new wording would lead a reviewer to ask a new Show…Script or Configure…Script to move its logic into /celery/tasks, which is the same kind of impossible move this PR is trying to stop. I suggest limiting the rule to background work, for example:

  - `/scripts` - Legacy CLI utilities (**deprecated - put new background work in `/celery/tasks`**)
    - The package is deprecated for *logic*, not for entry points. ... Commands that must
      report back to the operator's terminal (see `informational.py`, `configuration.py`)
      can still do their work synchronously.

circulation/CLAUDE.md

Lines 71 to 75 in 35e3f3f

- `/scripts` - Legacy CLI utilities (**deprecated - put new logic in `/celery/tasks`**)
- The package is deprecated for *logic*, not for entry points. A thin `Script` subclass
(here, or alongside its integration under `/integration`) plus a `bin/` wrapper is
still a supported way to run something on demand, and is still the expected pattern
for dispatching a Celery task by hand. There is no replacement framework:

@greptile-apps

greptile-apps Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Low risk] Clarifies deprecation policies in developer documentation.

The PR appears safe to merge.

Summary

The PR clarifies that classifier code remains under core/classifier and that thin on-demand CLI entry points remain supported under scripts. The PR itself changes documentation only; no new issues were identified.

Reviews (5) · Last reviewed commit: "Point both exceptions at the right direc..."

Comment thread CLAUDE.md Outdated
@dbernstein
dbernstein force-pushed the chore/correct-deprecated-package-guidance branch from 57897c5 to df2bf6e Compare September 23, 2026 23:48
@codecov

codecov Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.72%. Comparing base (a87d4c7) to head (35e3f3f).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3749   +/-   ##
=======================================
  Coverage   93.72%   93.72%           
=======================================
  Files         510      510           
  Lines       46510    46510           
  Branches     6313     6313           
=======================================
  Hits        43590    43590           
  Misses       1886     1886           
  Partials     1034     1034           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dbernstein
dbernstein requested a review from a team September 25, 2026 19:32
dbernstein added a commit that referenced this pull request Sep 25, 2026
Review on #3749 caught two places where the new wording sends a reader
somewhere the thing is not.

"A thin Script subclass *here*" reads as /scripts only, but nine modules
define integration-local Script subclasses next to the integration they
drive -- bibliotheca, boundless, overdrive, the five opds variants, and
discovery/registration_script. Left as written it makes those look
misplaced and would push a new vendor script into /scripts, which is the
opposite of what this change is for.

The BISAC code table is not in /core/classifier either. bisac.py:261
loads it from /resources/classifier via classifier_resources_dir(),
alongside dewey_1000.json and lcc_one_level.json.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
dbernstein and others added 3 commits September 28, 2026 09:11
Both markers were written as "deprecated - no new code" when CLAUDE.md
was first added in 21df3c5. Read literally, neither is true, and
reviewers acting on the literal reading keep asking for moves that have
nowhere to go.

`scripts/` has no replacement. `[project.scripts]` holds exactly one
entry and it resolves into that package; there is no cli/ package, click
app or `palace` command; and of the ~74 wrappers in bin/, 50 import
palace.manager.scripts directly and 16 more subclass Script through the
integration packages. Five new Script subclasses and five new bin/
wrappers have landed since the marker was written. What the deprecation
is actually protecting is business logic, which now goes in
celery/tasks/ with a thin dispatcher here.

`core/` is genuinely being drained -- net -2,001 lines over the last
year, as coverage providers, monitors and facets came out. But
`core/classifier/` is net +131 over the same period and is the only part
still taking behaviour changes. Nothing outside it defines classification
logic, and there is no candidate home: packages/ holds only palace-opds
and palace-util, and service/ is DI wiring.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Review on #3749 caught two places where the new wording sends a reader
somewhere the thing is not.

"A thin Script subclass *here*" reads as /scripts only, but nine modules
define integration-local Script subclasses next to the integration they
drive -- bibliotheca, boundless, overdrive, the five opds variants, and
discovery/registration_script. Left as written it makes those look
misplaced and would push a new vendor script into /scripts, which is the
opposite of what this change is for.

The BISAC code table is not in /core/classifier either. bisac.py:261
loads it from /resources/classifier via classifier_resources_dir(),
alongside dewey_1000.json and lcc_one_level.json.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dbernstein
dbernstein force-pushed the chore/correct-deprecated-package-guidance branch from 4e9fba6 to 35e3f3f Compare September 28, 2026 16:12
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