For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Isolate AP-specific code into ap/ sub-packages and rename AP database tables with ap_ prefix, preparing the codebase for AR introduction.
Architecture: Two-phase refactoring: (A) database table renames with code reference updates, (B) namespace reorganization moving AP worker, HTTP, and integration files under ap/ sub-packages. Each phase is an independent branch/PR.
Tech Stack: Clojure, PostgreSQL, HoneySQL, Malli, Integrant
Design doc: docs/plans/2026-03-13-ap-ar-isolation-design.md
Table renames affect code in two forms:
:doc-source in :from, :join, :insert-into (HoneySQL auto-converts kebab→snake):doc-source/id, {:doc-source/keys [...]} (produced by as-kebab-maps row builder from table name)Both forms derive from the table name, so renaming doc_source → ap_doc_source means:
:doc-source → :ap-doc-source:doc-source/column → :ap-doc-source/column{:doc-source/keys [...]} → {:ap-doc-source/keys [...]}Malli schemas in schema/ that use table-derived key namespaces (e.g., :ingestion/id in schema/ingestion.clj) must also be updated to match the new table names.
Migration files (init.sql, squashed migrations) are historical — never edit them. Only create new migrations.
Documentation files (.md) should be updated where they reference table names, but only if the reference is prescriptive (e.g., code examples, query patterns). Descriptive historical references can stay.
Files:
resources/migrations/YYYYMMDDHHMMSS-rename-ap-tables.up.sqlresources/migrations/YYYYMMDDHHMMSS-rename-ap-tables.down.sqlStep 1: Write the up migration
-- Rename AP-specific tables with ap_ prefix
ALTER TABLE doc_source RENAME TO ap_doc_source;
ALTER TABLE doc_source_email RENAME TO ap_doc_source_email;
ALTER TABLE doc_source_email_pending_sync RENAME TO ap_doc_source_email_pending_sync;
ALTER TABLE doc_source_email_processed_messages RENAME TO ap_doc_source_email_processed_messages;
ALTER TABLE doc_source_webhook RENAME TO ap_doc_source_webhook;
ALTER TABLE doc_source_ses RENAME TO ap_doc_source_ses;
ALTER TABLE doc_source_ses_processed RENAME TO ap_doc_source_ses_processed;
ALTER TABLE ingestion RENAME TO ap_ingestion;
ALTER TABLE ingestion_post_process_stat RENAME TO ap_ingestion_post_process_stat;
ALTER TABLE document_cluster RENAME TO ap_document_cluster;
ALTER TABLE document_match RENAME TO ap_document_match;
ALTER TABLE datev_export_audit RENAME TO ap_datev_export_audit;
ALTER TABLE supplier_verification RENAME TO ap_supplier_verification;
ALTER TABLE supplier_verification_document RENAME TO ap_supplier_verification_document;
ALTER TABLE acquisition_llm_stat RENAME TO ap_acquisition_llm_stat;
ALTER TABLE qa_dataset_item RENAME TO ap_qa_dataset_item;
-- Add domain column to document table
ALTER TABLE document ADD COLUMN domain TEXT NOT NULL DEFAULT 'ap';
-- Rename enum types
ALTER TYPE document_match_status RENAME TO ap_document_match_status;
Note: PostgreSQL automatically updates FK constraints, indexes, and triggers when renaming tables. Sequence and constraint names keep their old names — this is cosmetic and harmless.
Step 2: Write the down migration
ALTER TABLE document DROP COLUMN domain;
ALTER TYPE ap_document_match_status RENAME TO document_match_status;
ALTER TABLE ap_doc_source RENAME TO doc_source;
ALTER TABLE ap_doc_source_email RENAME TO doc_source_email;
ALTER TABLE ap_doc_source_email_pending_sync RENAME TO doc_source_email_pending_sync;
ALTER TABLE ap_doc_source_email_processed_messages RENAME TO doc_source_email_processed_messages;
ALTER TABLE ap_doc_source_webhook RENAME TO doc_source_webhook;
ALTER TABLE ap_doc_source_ses RENAME TO doc_source_ses;
ALTER TABLE ap_doc_source_ses_processed RENAME TO doc_source_ses_processed;
ALTER TABLE ap_ingestion RENAME TO ingestion;
ALTER TABLE ap_ingestion_post_process_stat RENAME TO ingestion_post_process_stat;
ALTER TABLE ap_document_cluster RENAME TO document_cluster;
ALTER TABLE ap_document_match RENAME TO document_match;
ALTER TABLE ap_datev_export_audit RENAME TO datev_export_audit;
ALTER TABLE ap_supplier_verification RENAME TO supplier_verification;
ALTER TABLE ap_supplier_verification_document RENAME TO supplier_verification_document;
ALTER TABLE ap_acquisition_llm_stat RENAME TO acquisition_llm_stat;
ALTER TABLE ap_qa_dataset_item RENAME TO qa_dataset_item;
Step 3: Verify the migration compiles
psql -h localhost -U postgres -d orcha -c "\dt" | head -30
Step 4: Commit the migration files only (code updates come next)
The doc_source family has 7 tables and is the most widely referenced (~1,400 occurrences across ~50 files). Use find-and-replace, processing longest names first to avoid partial replacements.
Replacement order (critical — longest first):
| # | Old (kebab) | New (kebab) |
|---|---|---|
| 1 | doc-source-email-processed-messages |
ap-doc-source-email-processed-messages |
| 2 | doc-source-email-pending-sync |
ap-doc-source-email-pending-sync |
| 3 | doc-source-email |
ap-doc-source-email |
| 4 | doc-source-webhook |
ap-doc-source-webhook |
| 5 | doc-source-ses-processed |
ap-doc-source-ses-processed |
| 6 | doc-source-ses |
ap-doc-source-ses |
| 7 | doc-source |
ap-doc-source |
And the same order for snake_case forms (doc_source_email_processed_messages → ap_doc_source_email_processed_messages, etc.) in raw SQL strings.
Scope: All .clj files under src/ and test/, plus repl/ and scripts/.
Exclusions: Do NOT modify files under resources/migrations/ (historical). Do NOT modify CHANGELOG.md.
Step 1: Apply all 7 kebab-case replacements (longest first) across .clj files
For each replacement, use global find-and-replace across the codebase. The kebab form appears in:
:doc-source/id, {:doc-source/keys [...]}[:doc-source ...], :doc-source.columnStep 2: Apply snake_case replacements in .clj files
The snake_case form appears in raw SQL strings (e.g., "INSERT INTO doc_source ..."). Same longest-first order.
Step 3: Update Malli schemas in src/com/getorcha/schema/doc_source/
schema/doc_source/email.clj — update key namespaces from :doc-source-email/ to :ap-doc-source-email/schema/doc_source/ses.clj — update key namespaces from :doc-source-ses/ to :ap-doc-source-ses/Step 4: Run linter and fix any issues
clj-kondo --lint src test dev
Key files with highest reference counts (verify these manually):
src/com/getorcha/workers/acquisition/email/oauth.clj (~95 refs)test/com/getorcha/workers/acquisition/email_test.clj (~233 refs)src/com/getorcha/admin/db/queries.clj (~40 refs)src/com/getorcha/admin/http/ses_sources.clj (~49 refs)src/com/getorcha/app/http/oauth.clj (~37 refs)Two tables: ingestion and ingestion_post_process_stat.
Critical distinction: The word "ingestion" appears in:
:ingestion/id, :ingestion in HoneySQL, {:ingestion/keys [...]}com.getorcha.workers.ingestion, :com.getorcha.workers.ingestion/orchestratorOnly change table references in this task.
Replacement patterns:
| Old | New | Context |
|---|---|---|
:ingestion-post-process-stat |
:ap-ingestion-post-process-stat |
HoneySQL + qualified keys |
ingestion_post_process_stat |
ap_ingestion_post_process_stat |
Raw SQL strings |
:ingestion/ |
:ap-ingestion/ |
Qualified result keys (:ingestion/id, :ingestion/status, etc.) |
{:ingestion/keys |
{:ap-ingestion/keys |
Destructuring |
:ingestion (bare, in HoneySQL position) |
:ap-ingestion |
Table ref in :from, :join, :insert-into, :update |
"ingestion" or ingestion. in SQL strings |
"ap_ingestion" / ap_ingestion. |
Raw SQL |
Do NOT replace:
com.getorcha.workers.ingestion (namespace — Phase B):com.getorcha.workers.ingestion/ (Integrant key — Phase B)ingestion as a require alias (e.g., :as ingestion)ingestion in comments, docstrings, log messages (optional, low priority)ingestion as part of other words like app.ingestion (the app/ingestion.clj module):ingestion in config maps as queue name keys (e.g., {:queues {:ingestion "..."}}})Step 1: Replace ingestion_post_process_stat references first (longest match)
Affects ~5 files:
src/com/getorcha/workers/ingestion.cljsrc/com/getorcha/admin/db/queries.cljsrc/com/getorcha/admin/http/costs.cljsrc/com/getorcha/admin/http/performance.cljStep 2: Replace :ingestion/ qualified keys
This is the most impactful change. Affects 30+ files including:
src/com/getorcha/schema/ingestion.clj (Malli schema — all keys change)src/com/getorcha/workers/ingestion.clj (main orchestrator)src/com/getorcha/app/http/documents/ (view layer)src/com/getorcha/link/api/handlers/documents.cljsrc/com/getorcha/link/mcp/tools/docs/src/com/getorcha/app/ingestion.cljtest/com/getorcha/workers/ingestion_test.cljtest/com/getorcha/app/http/documents_test.cljStep 3: Replace bare :ingestion in HoneySQL positions
Search for :ingestion as a table keyword in HoneySQL maps. Common patterns:
{:from [:ingestion]} or {:from [[:ingestion :alias]]}{:insert-into :ingestion}{:join [:ingestion [...]]} or {:left-join [:ingestion [...]]}Carefully distinguish from :ingestion as a config/queue key (which should NOT change).
Step 4: Run linter
clj-kondo --lint src test dev
Five table groups with moderate impact.
| Old | New |
|---|---|
:document-cluster |
:ap-document-cluster |
:document-cluster/ |
:ap-document-cluster/ |
document_cluster |
ap_document_cluster |
:document-match |
:ap-document-match |
:document-match/ |
:ap-document-match/ |
document_match |
ap_document_match |
Key files:
src/com/getorcha/db/document_matching.cljsrc/com/getorcha/workers/matching/core.cljsrc/com/getorcha/workers/matching/reconciliation.cljtest/com/getorcha/db/document_matching_test.cljtest/com/getorcha/workers/matching/ (multiple test files)scripts/debug_fetch_match_cluster.cljAlso update document_match_status references if this enum type is referenced in code (it was renamed to ap_document_match_status in the migration).
| Old | New |
|---|---|
:datev-export-audit |
:ap-datev-export-audit |
:datev-export-audit/ |
:ap-datev-export-audit/ |
datev_export_audit |
ap_datev_export_audit |
Key files:
src/com/getorcha/integrations/maesn.clj (~14 kebab refs)src/com/getorcha/app/http/documents/view/invoice.cljsrc/com/getorcha/app/http/documents/view/shared.cljsrc/com/getorcha/app/http/documents/shared.cljsrc/com/getorcha/app/ingestion.cljsrc/com/getorcha/link/api/handlers/documents.cljsrc/com/getorcha/link/queries/documents.clj| Old | New |
|---|---|
:supplier-verification-document |
:ap-supplier-verification-document |
:supplier-verification-document/ |
:ap-supplier-verification-document/ |
:supplier-verification |
:ap-supplier-verification |
:supplier-verification/ |
:ap-supplier-verification/ |
supplier_verification_document |
ap_supplier_verification_document |
supplier_verification |
ap_supplier_verification |
Replace supplier-verification-document BEFORE supplier-verification (longest first).
Key files:
src/com/getorcha/workers/supplier_verification.cljsrc/com/getorcha/app/ui/components.cljsrc/com/getorcha/app/http/documents/view/shared.cljsrc/com/getorcha/app/http/documents/view/invoice.cljsrc/com/getorcha/app/http/documents/view.cljsrc/com/getorcha/app/http/documents/shared.clj| Old | New |
|---|---|
:acquisition-llm-stat |
:ap-acquisition-llm-stat |
acquisition_llm_stat |
ap_acquisition_llm_stat |
Key files:
src/com/getorcha/workers/acquisition/email/ses.cljsrc/com/getorcha/workers/acquisition/email/oauth.cljsrc/com/getorcha/admin/db/queries.cljsrc/com/getorcha/admin/http/costs.clj| Old | New |
|---|---|
:qa-dataset-item |
:ap-qa-dataset-item |
:qa-dataset-item/ |
:ap-qa-dataset-item/ |
qa_dataset_item |
ap_qa_dataset_item |
Key files:
src/com/getorcha/admin/db/queries.cljsrc/com/getorcha/admin/http/qa_dataset.cljsrc/com/getorcha/app/http/documents/view/invoice.cljsrc/com/getorcha/app/http/documents/view.cljStep (final): Run linter
clj-kondo --lint src test dev
Step 1: Run the migration against local database
psql -h localhost -U postgres -d orcha -c "\i resources/migrations/YYYYMMDDHHMMSS-rename-ap-tables.up.sql"
Or if using migratus from REPL:
(reset) ;; will run pending migrations
Step 2: Run all tests
clj -X:test:silent 2>&1 | grep -A 5 -E "(FAIL in|ERROR in|Execution error|failed because|Ran .* tests)"
Step 3: Fix any failures
Common failure causes:
.clj files)Step 4: Commit all Phase A changes
git add resources/migrations/YYYYMMDDHHMMSS-rename-ap-tables.up.sql resources/migrations/YYYYMMDDHHMMSS-rename-ap-tables.down.sql
git add -p # stage .clj file changes
git commit -m "refactor: rename AP-specific database tables with ap_ prefix"
Namespace rename pattern: Insert .ap after workers:
com.getorcha.workers.ingestion → com.getorcha.workers.ap.ingestioncom.getorcha.workers.acquisition → com.getorcha.workers.ap.acquisitioncom.getorcha.workers.matching → com.getorcha.workers.ap.matchingcom.getorcha.workers.supplier-verification → com.getorcha.workers.ap.supplier-verificationStep 1: Create target directory structure
mkdir -p src/com/getorcha/workers/ap/ingestion/post_process
mkdir -p src/com/getorcha/workers/ap/ingestion/transcription
mkdir -p src/com/getorcha/workers/ap/acquisition/email
mkdir -p src/com/getorcha/workers/ap/matching
Step 2: Move source files with git mv
# Ingestion (19 files)
git mv src/com/getorcha/workers/ingestion.clj src/com/getorcha/workers/ap/ingestion.clj
git mv src/com/getorcha/workers/ingestion/classification.clj src/com/getorcha/workers/ap/ingestion/classification.clj
git mv src/com/getorcha/workers/ingestion/extraction.clj src/com/getorcha/workers/ap/ingestion/extraction.clj
git mv src/com/getorcha/workers/ingestion/fraud_detection.clj src/com/getorcha/workers/ap/ingestion/fraud_detection.clj
git mv src/com/getorcha/workers/ingestion/transcription.clj src/com/getorcha/workers/ap/ingestion/transcription.clj
git mv src/com/getorcha/workers/ingestion/transcription/layout.clj src/com/getorcha/workers/ap/ingestion/transcription/layout.clj
git mv src/com/getorcha/workers/ingestion/transcription/ocr_layout.clj src/com/getorcha/workers/ap/ingestion/transcription/ocr_layout.clj
git mv src/com/getorcha/workers/ingestion/transcription/pdfbox_layout.clj src/com/getorcha/workers/ap/ingestion/transcription/pdfbox_layout.clj
git mv src/com/getorcha/workers/ingestion/validation.clj src/com/getorcha/workers/ap/ingestion/validation.clj
git mv src/com/getorcha/workers/ingestion/vat_rules.clj src/com/getorcha/workers/ap/ingestion/vat_rules.clj
git mv src/com/getorcha/workers/ingestion/post_process.clj src/com/getorcha/workers/ap/ingestion/post_process.clj
git mv src/com/getorcha/workers/ingestion/post_process/accounts.clj src/com/getorcha/workers/ap/ingestion/post_process/accounts.clj
git mv src/com/getorcha/workers/ingestion/post_process/accruals.clj src/com/getorcha/workers/ap/ingestion/post_process/accruals.clj
git mv src/com/getorcha/workers/ingestion/post_process/common.clj src/com/getorcha/workers/ap/ingestion/post_process/common.clj
git mv src/com/getorcha/workers/ingestion/post_process/cost_center.clj src/com/getorcha/workers/ap/ingestion/post_process/cost_center.clj
git mv src/com/getorcha/workers/ingestion/post_process/financial_validation.clj src/com/getorcha/workers/ap/ingestion/post_process/financial_validation.clj
git mv src/com/getorcha/workers/ingestion/post_process/protocol.clj src/com/getorcha/workers/ap/ingestion/post_process/protocol.clj
git mv src/com/getorcha/workers/ingestion/post_process/supplier.clj src/com/getorcha/workers/ap/ingestion/post_process/supplier.clj
git mv src/com/getorcha/workers/ingestion/post_process/tax_compliance.clj src/com/getorcha/workers/ap/ingestion/post_process/tax_compliance.clj
git mv src/com/getorcha/workers/ingestion/post_process/uncertain_validations.clj src/com/getorcha/workers/ap/ingestion/post_process/uncertain_validations.clj
# Acquisition (11 files)
git mv src/com/getorcha/workers/acquisition.clj src/com/getorcha/workers/ap/acquisition.clj
git mv src/com/getorcha/workers/acquisition/email.clj src/com/getorcha/workers/ap/acquisition/email.clj
git mv src/com/getorcha/workers/acquisition/email/gmail.clj src/com/getorcha/workers/ap/acquisition/email/gmail.clj
git mv src/com/getorcha/workers/acquisition/email/oauth.clj src/com/getorcha/workers/ap/acquisition/email/oauth.clj
git mv src/com/getorcha/workers/acquisition/email/outlook.clj src/com/getorcha/workers/ap/acquisition/email/outlook.clj
git mv src/com/getorcha/workers/acquisition/email/protocol.clj src/com/getorcha/workers/ap/acquisition/email/protocol.clj
git mv src/com/getorcha/workers/acquisition/email/ses.clj src/com/getorcha/workers/ap/acquisition/email/ses.clj
git mv src/com/getorcha/workers/acquisition/email/subscription.clj src/com/getorcha/workers/ap/acquisition/email/subscription.clj
git mv src/com/getorcha/workers/acquisition/email/triage.clj src/com/getorcha/workers/ap/acquisition/email/triage.clj
git mv src/com/getorcha/workers/acquisition/html.clj src/com/getorcha/workers/ap/acquisition/html.clj
git mv src/com/getorcha/workers/acquisition/multi.clj src/com/getorcha/workers/ap/acquisition/multi.clj
# Matching (8 files)
git mv src/com/getorcha/workers/matching/worker.clj src/com/getorcha/workers/ap/matching/worker.clj
git mv src/com/getorcha/workers/matching/core.clj src/com/getorcha/workers/ap/matching/core.clj
git mv src/com/getorcha/workers/matching/candidates.clj src/com/getorcha/workers/ap/matching/candidates.clj
git mv src/com/getorcha/workers/matching/evidence.clj src/com/getorcha/workers/ap/matching/evidence.clj
git mv src/com/getorcha/workers/matching/llm_decision.clj src/com/getorcha/workers/ap/matching/llm_decision.clj
git mv src/com/getorcha/workers/matching/normalize.clj src/com/getorcha/workers/ap/matching/normalize.clj
git mv src/com/getorcha/workers/matching/reconciliation.clj src/com/getorcha/workers/ap/matching/reconciliation.clj
git mv src/com/getorcha/workers/matching/searchable_text.clj src/com/getorcha/workers/ap/matching/searchable_text.clj
# Supplier verification (1 file)
git mv src/com/getorcha/workers/supplier_verification.clj src/com/getorcha/workers/ap/supplier_verification.clj
Step 3: Update namespace declarations in ALL moved files
Global find-and-replace in moved files only:
com.getorcha.workers.ingestion → com.getorcha.workers.ap.ingestion (and all sub-namespaces)com.getorcha.workers.acquisition → com.getorcha.workers.ap.acquisition (and all sub-namespaces)com.getorcha.workers.matching → com.getorcha.workers.ap.matching (and all sub-namespaces)com.getorcha.workers.supplier-verification → com.getorcha.workers.ap.supplier-verificationThis applies to both ns declarations and internal require references within moved files (since they reference each other).
Step 4: Update require statements in files that were NOT moved
These files reference the moved namespaces and need require updates:
src/com/getorcha/workers.clj — may require ingestion/acquisitionsrc/com/getorcha/app/ingestion.clj — may reference ingestion pipelinesrc/com/getorcha/app/http/documents/ — references ingestion view/sharedsrc/com/getorcha/notifications.clj — may reference worker namespacessrc/com/getorcha/admin/http/ — references acquisition, ingestion for dashboardssrc/com/getorcha/logging/mdc.clj — references doc-source keysdev/user.clj and repl/ filesSearch for any remaining com.getorcha.workers.ingestion (without .ap.) in .clj files and update.
Files that stay at workers/ root (do NOT move):
src/com/getorcha/workers.clj — shared prompt templatingsrc/com/getorcha/workers/llm.clj — shared LLM utilitiesStep 1: Move the file
git mv src/com/getorcha/app/http/documents/accounts_payable.clj src/com/getorcha/app/http/ap.clj
Step 2: Update namespace declaration
;; Old:
(ns com.getorcha.app.http.documents.accounts-payable ...)
;; New:
(ns com.getorcha.app.http.ap ...)
Step 3: Update route names
In ap.clj, all ::route-name keywords now resolve to :com.getorcha.app.http.ap/route-name instead of :com.getorcha.app.http.documents.accounts-payable/route-name. This happens automatically via :: resolution.
Update all files that reference the old fully-qualified route names:
| Old | New |
|---|---|
:com.getorcha.app.http.documents.accounts-payable/list |
:com.getorcha.app.http.ap/list |
| (and any other route names from this namespace) |
Key files to update:
src/com/getorcha/app/http/login.clj — redirect after loginsrc/com/getorcha/app/http/profile.clj — navigationsrc/com/getorcha/app/ui/layout.clj — navigation menusrc/com/getorcha/app/http/documents/view/shared.clj — back linksrc/com/getorcha/app/http/documents/documents.clj — route assembly (update require)Step 4: Update the require in documents.clj route assembly
;; Old:
[com.getorcha.app.http.documents.accounts-payable :as accounts-payable]
;; New:
[com.getorcha.app.http.ap :as ap]
And update all references from accounts-payable/ to ap/ in route definitions.
Step 1: Move files
mkdir -p src/com/getorcha/integrations/ap
git mv src/com/getorcha/integrations/maesn.clj src/com/getorcha/integrations/ap/maesn.clj
git mv src/com/getorcha/integrations/cover_page.clj src/com/getorcha/integrations/ap/cover_page.clj
Step 2: Update namespace declarations
com.getorcha.integrations.maesn → com.getorcha.integrations.ap.maesncom.getorcha.integrations.cover-page → com.getorcha.integrations.ap.cover-pageStep 3: Update requires in files that reference these namespaces
Key files:
src/com/getorcha/workers/ap/ingestion.clj (was workers/ingestion.clj)src/com/getorcha/app/http/documents/accounts_payable.clj (now app/http/ap.clj)src/com/getorcha/app/http/settings/integrations.cljsrc/com/getorcha/app/http/documents/view.cljsrc/com/getorcha/app/http/documents/view/invoice.cljsrc/com/getorcha/app/http/documents/view/shared.cljsrc/com/getorcha/app/http/connect/datev_rewe.cljStep 1: Update config.edn
In resources/com/getorcha/config.edn, rename all worker keys:
| Old Key | New Key |
|---|---|
:com.getorcha.workers.ingestion/worker-pools |
:com.getorcha.workers.ap.ingestion/worker-pools |
:com.getorcha.workers.ingestion/orchestrator |
:com.getorcha.workers.ap.ingestion/orchestrator |
:com.getorcha.workers.acquisition/worker-pools |
:com.getorcha.workers.ap.acquisition/worker-pools |
:com.getorcha.workers.acquisition/orchestrator |
:com.getorcha.workers.ap.acquisition/orchestrator |
:com.getorcha.workers.acquisition.email.subscription/renewal |
:com.getorcha.workers.ap.acquisition.email.subscription/renewal |
:com.getorcha.workers.matching.worker/worker-pools |
:com.getorcha.workers.ap.matching.worker/worker-pools |
:com.getorcha.workers.matching.worker/orchestrator |
:com.getorcha.workers.ap.matching.worker/orchestrator |
Also update all #integrant/ref values that point to the old keys.
Step 2: Update ig/init-key and ig/halt-key! in moved files
These use ::keyword which resolves based on the current namespace — since the namespaces were updated in Task 6, these should already be correct. Verify by searching for ig/init-key and ig/halt-key! in moved files.
Step 3: Update remaining cross-references
Search the entire codebase for any remaining references to the old namespace names:
# Search for old namespace patterns that should have been updated
grep -r "com.getorcha.workers.ingestion[^.]" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn" | grep -v ".ap."
grep -r "com.getorcha.workers.acquisition[^.]" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn" | grep -v ".ap."
grep -r "com.getorcha.workers.matching" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn" | grep -v ".ap."
grep -r "com.getorcha.integrations.maesn" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn" | grep -v ".ap."
grep -r "com.getorcha.integrations.cover-page" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn" | grep -v ".ap."
grep -r "documents.accounts-payable" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn"
Fix any remaining references found.
Step 4: Update test fixture/helper references
test/com/getorcha/test/fixtures.clj — may reference Integrant keystest/com/getorcha/test/notification_helpers.clj — references :com.getorcha.workers.ingestion/orchestratorStep 1: Create target test directories
mkdir -p test/com/getorcha/workers/ap/ingestion/transcription
mkdir -p test/com/getorcha/workers/ap/acquisition/email
mkdir -p test/com/getorcha/workers/ap/matching
mkdir -p test/com/getorcha/integrations/ap
Step 2: Move test files with git mv
Mirror the source file moves:
# Ingestion tests
git mv test/com/getorcha/workers/ingestion_test.clj test/com/getorcha/workers/ap/ingestion_test.clj
git mv test/com/getorcha/workers/ingestion_notifications_test.clj test/com/getorcha/workers/ap/ingestion_notifications_test.clj
git mv test/com/getorcha/workers/ingestion/classification_test.clj test/com/getorcha/workers/ap/ingestion/classification_test.clj
git mv test/com/getorcha/workers/ingestion/extraction_test.clj test/com/getorcha/workers/ap/ingestion/extraction_test.clj
git mv test/com/getorcha/workers/ingestion/fraud_detection_test.clj test/com/getorcha/workers/ap/ingestion/fraud_detection_test.clj
git mv test/com/getorcha/workers/ingestion/transcription_test.clj test/com/getorcha/workers/ap/ingestion/transcription_test.clj
git mv test/com/getorcha/workers/ingestion/transcription/layout_test.clj test/com/getorcha/workers/ap/ingestion/transcription/layout_test.clj
git mv test/com/getorcha/workers/ingestion/transcription/ocr_layout_test.clj test/com/getorcha/workers/ap/ingestion/transcription/ocr_layout_test.clj
git mv test/com/getorcha/workers/ingestion/transcription/pdfbox_layout_test.clj test/com/getorcha/workers/ap/ingestion/transcription/pdfbox_layout_test.clj
git mv test/com/getorcha/workers/ingestion/validation_test.clj test/com/getorcha/workers/ap/ingestion/validation_test.clj
git mv test/com/getorcha/workers/ingestion/vat_rules_test.clj test/com/getorcha/workers/ap/ingestion/vat_rules_test.clj
# Acquisition tests
git mv test/com/getorcha/workers/acquisition_test.clj test/com/getorcha/workers/ap/acquisition_test.clj
git mv test/com/getorcha/workers/acquisition_notifications_test.clj test/com/getorcha/workers/ap/acquisition_notifications_test.clj
git mv test/com/getorcha/workers/acquisition/email_test.clj test/com/getorcha/workers/ap/acquisition/email_test.clj
git mv test/com/getorcha/workers/acquisition/email_notifications_test.clj test/com/getorcha/workers/ap/acquisition/email_notifications_test.clj
git mv test/com/getorcha/workers/acquisition/email/ses_test.clj test/com/getorcha/workers/ap/acquisition/email/ses_test.clj
git mv test/com/getorcha/workers/acquisition/email/outlook_test.clj test/com/getorcha/workers/ap/acquisition/email/outlook_test.clj
git mv test/com/getorcha/workers/acquisition/email/subscription_test.clj test/com/getorcha/workers/ap/acquisition/email/subscription_test.clj
git mv test/com/getorcha/workers/acquisition/html_test.clj test/com/getorcha/workers/ap/acquisition/html_test.clj
git mv test/com/getorcha/workers/acquisition/triage_test.clj test/com/getorcha/workers/ap/acquisition/triage_test.clj
# Matching tests
git mv test/com/getorcha/workers/matching/worker_test.clj test/com/getorcha/workers/ap/matching/worker_test.clj
git mv test/com/getorcha/workers/matching/core_test.clj test/com/getorcha/workers/ap/matching/core_test.clj
git mv test/com/getorcha/workers/matching/candidates_test.clj test/com/getorcha/workers/ap/matching/candidates_test.clj
git mv test/com/getorcha/workers/matching/evidence_test.clj test/com/getorcha/workers/ap/matching/evidence_test.clj
git mv test/com/getorcha/workers/matching/integration_test.clj test/com/getorcha/workers/ap/matching/integration_test.clj
git mv test/com/getorcha/workers/matching/llm_decision_test.clj test/com/getorcha/workers/ap/matching/llm_decision_test.clj
git mv test/com/getorcha/workers/matching/normalize_test.clj test/com/getorcha/workers/ap/matching/normalize_test.clj
git mv test/com/getorcha/workers/matching/reconciliation_test.clj test/com/getorcha/workers/ap/matching/reconciliation_test.clj
git mv test/com/getorcha/workers/matching/searchable_text_test.clj test/com/getorcha/workers/ap/matching/searchable_text_test.clj
# Supplier verification test
git mv test/com/getorcha/workers/supplier_verification_test.clj test/com/getorcha/workers/ap/supplier_verification_test.clj
# Integration tests
git mv test/com/getorcha/integrations/maesn_test.clj test/com/getorcha/integrations/ap/maesn_test.clj
git mv test/com/getorcha/integrations/maesn_notifications_test.clj test/com/getorcha/integrations/ap/maesn_notifications_test.clj
Step 3: Update namespace declarations in all moved test files
Same pattern as source files — insert .ap after workers or integrations:
com.getorcha.workers.ingestion-test → com.getorcha.workers.ap.ingestion-testStep 4: Update require statements in test files
Both the source namespace references (now under .ap.) and any cross-test references.
Step 1: Update prescriptive documentation
Files that contain code examples, query patterns, or architectural descriptions referencing old table/namespace names:
docs/db/schema.mddocs/db/code-patterns.mddocs/ingestion/email.mddocs/ingestion/sources.mddocs/architecture/email-acquisition.mddocs/architecture/ses-email-acquisition.mddocs/acquisition/email/README.mddocs/glossary.mdCLAUDE.md (if it references specific table names).claude/skills/debug-acquisition/SKILL.md.claude/skills/debug-match/SKILL.mdinfra/runbooks/ses-troubleshooting.mddocs/plans/2026-03-13-ap-ar-isolation-design.md (update to reflect completed state)Step 2: Do NOT modify
CHANGELOG.md — historicalresources/migrations/*.sql — historicaldocs/plans/ — historical (except the design doc for this work)Step 1: Run linter
clj-kondo --lint src test dev
Fix all warnings/errors.
Step 2: Verify no stale references remain
# Old worker namespaces (should return nothing in .clj/.edn files)
grep -r "workers\.ingestion" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn" | grep -v "workers\.ap\.ingestion" | grep -v "workers\.llm"
grep -r "workers\.acquisition" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn" | grep -v "workers\.ap\.acquisition"
grep -r "workers\.matching" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn" | grep -v "workers\.ap\.matching"
# Old integration namespaces
grep -r "integrations\.maesn" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn" | grep -v "integrations\.ap\.maesn"
# Old route names
grep -r "documents\.accounts-payable" src/ test/ dev/ repl/ resources/ --include="*.clj" --include="*.edn"
Step 3: Run full test suite
clj -X:test:silent 2>&1 | grep -A 5 -E "(FAIL in|ERROR in|Execution error|failed because|Ran .* tests)"
Step 4: Commit Phase B
git add src/ test/ dev/ repl/ scripts/ resources/com/getorcha/config.edn
git commit -m "refactor: move AP workers, HTTP, and integrations under ap/ sub-packages"
After moving files, git may leave behind empty directories.
find src/com/getorcha/workers/ingestion -empty -type d -delete 2>/dev/null
find src/com/getorcha/workers/acquisition -empty -type d -delete 2>/dev/null
find src/com/getorcha/workers/matching -empty -type d -delete 2>/dev/null
find test/com/getorcha/workers/ingestion -empty -type d -delete 2>/dev/null
find test/com/getorcha/workers/acquisition -empty -type d -delete 2>/dev/null
find test/com/getorcha/workers/matching -empty -type d -delete 2>/dev/null
find src/com/getorcha/integrations -maxdepth 0 -empty -type d -delete 2>/dev/null