Financially Active Contracts Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Expand contract sub-types (loan, rental, insurance, subscription, purchase) and add a "financially active" concept with UI badges and filtering.

Architecture: The contract-type enum lives in JSONB structured_data, not a DB enum — so expansion requires schema + prompt changes only. The financially-active flag is derived from contract-type in code, not stored. UI gets a new badge and filter.

Tech Stack: Clojure, Malli schemas, Hiccup/HTMX, CSS, clj-kondo, cognitect test-runner


Task 1: Expand Contract-Type Schema

Files:

Step 1: Update the ContractType enum

Change lines 5-6 from:

(def ^:private ContractType
  [:enum "service" "supply" "lease" "nda" "framework" "other"])

to:

(def ^:private ContractType
  [:enum "loan" "lease" "rental" "insurance" "subscription" "purchase"
         "service" "supply" "nda" "framework" "other"])

Step 2: Add financially-active? helper

After the ContractType def (after line 6), add:


(def financially-active-types
  "Contract types with recurring financial obligations."
  #{"loan" "lease" "rental" "insurance" "subscription"})

(defn financially-active?
  "Returns true if the given contract-type carries recurring financial obligations."
  [contract-type]
  (contains? financially-active-types contract-type))

Note: Remove ^:private from ContractType so it can be referenced by the UI layer, OR keep it private and just expose financially-active? + financially-active-types. The latter is cleaner — keep ContractType private.

Step 3: Run lint

Run: cd orcha && clj-kondo --lint src/com/getorcha/schema/contract/structured_data.clj Expected: 0 errors

Step 4: Commit

git add orcha/src/com/getorcha/schema/contract/structured_data.clj
git commit -m "feat: Expand contract-type enum and add financially-active? helper"

Task 2: Update Classification Prompt

Files:

Step 1: Update the contract line in the classification prompt

In the defmethod workers/-prompt :classification (line 81), change line 88 from:

- contract: Legal agreements, service contracts, lease/rent agreements (Mietvertrag), NDAs, terms of service, framework agreements (Rahmenvertrag)

to:

- contract: Legal agreements including loan agreements (Darlehensvertrag, Kreditvertrag), lease contracts (Leasingvertrag), rental agreements (Mietvertrag, Pachtvertrag), insurance policies (Versicherungsvertrag), subscription/SaaS contracts, purchase agreements (Kaufvertrag), service contracts (Dienstleistungsvertrag), supply agreements (Liefervertrag), NDAs, framework agreements (Rahmenvertrag)

Also update rule 10 (line 146-148) from:

10. Rent/lease agreements (Mietvertrag, Nachtrag, Pachtvertrag) are "contract", NOT invoices -
   even if they contain amounts, payment schedules, or recurring fees. Key signals: signing parties,
   contract duration/term, notice period (Kündigungsfrist), landlord/tenant (Vermieter/Mieter).

to:

10. Contracts (Mietvertrag, Leasingvertrag, Darlehensvertrag, Versicherungsvertrag, Kaufvertrag,
   Dienstleistungsvertrag, Liefervertrag, Pachtvertrag, Nachtrag) are "contract", NOT invoices -
   even if they contain amounts, payment schedules, or recurring fees. Key signals: signing parties,
   contract duration/term, notice period (Kündigungsfrist), landlord/tenant (Vermieter/Mieter),
   loan terms (Zinssatz, Tilgung), insurance premiums (Prämie, Versicherungssumme).

Step 2: Run lint

Run: cd orcha && clj-kondo --lint src/com/getorcha/workers/ingestion/classification.clj Expected: 0 errors

Step 3: Commit

git add orcha/src/com/getorcha/workers/ingestion/classification.clj
git commit -m "feat: Update classification prompt with expanded contract types"

Task 3: Update Extraction Prompt

Files:

Step 1: Update contract type definitions in extraction prompt

Change lines 801-807 from:

8. Contract type classification:
   - "service": Service agreements, consulting contracts, maintenance agreements
   - "supply": Supply agreements, procurement contracts, material delivery
   - "lease": Rental or leasing contracts for equipment, property, vehicles
   - "nda": Non-disclosure agreements, confidentiality agreements
   - "framework": Framework agreements, master agreements, blanket contracts
   - "other": Any contract type not fitting the above categories

to:

8. Contract type classification:
   - "loan": Loan agreements (Darlehensvertrag), credit agreements (Kreditvertrag), financing contracts
   - "lease": Leasing contracts for equipment, vehicles, machinery (Leasingvertrag)
   - "rental": Rental agreements for real estate, office space, property (Mietvertrag, Pachtvertrag)
   - "insurance": Insurance contracts, policies (Versicherungsvertrag, Versicherungspolice)
   - "subscription": SaaS agreements, recurring license agreements, maintenance contracts with periodic fees (Wartungsvertrag)
   - "purchase": Purchase agreements, sale contracts (Kaufvertrag, Erwerbsvertrag)
   - "service": One-off service agreements, consulting contracts (Dienstleistungsvertrag, Beratungsvertrag)
   - "supply": Supply agreements, procurement contracts, material delivery (Liefervertrag)
   - "nda": Non-disclosure agreements, confidentiality agreements
   - "framework": Framework agreements, master agreements, blanket contracts (Rahmenvertrag)
   - "other": Any contract type not fitting the above categories

Step 2: Update the JSON schema in the extraction prompt

Change line 837 from:

  "contract-type": "service" | "supply" | "lease" | "nda" | "framework" | "other" | null,

to:

  "contract-type": "loan" | "lease" | "rental" | "insurance" | "subscription" | "purchase" | "service" | "supply" | "nda" | "framework" | "other" | null,

Step 3: Run lint

Run: cd orcha && clj-kondo --lint src/com/getorcha/workers/ingestion/extraction.clj Expected: 0 errors

Step 4: Commit

git add orcha/src/com/getorcha/workers/ingestion/extraction.clj
git commit -m "feat: Update extraction prompt with expanded contract-type enum"

Task 4: Add Contract-Type Labels and Financial Badge to UI

Files:

Step 1: Add require for contract schema

In the ns form (line 1-24), add to the :require vector:

[com.getorcha.schema.contract.structured-data :as contract.schema]

Step 2: Add contract-type-labels map

After the type-labels def (after line 37), add:

(def ^:private contract-type-labels
  "Human-readable labels for contract sub-types."
  {"loan"         "Loan"
   "lease"        "Lease"
   "rental"       "Rental"
   "insurance"    "Insurance"
   "subscription" "Subscription"
   "purchase"     "Purchase"
   "service"      "Service"
   "supply"       "Supply"
   "nda"          "NDA"
   "framework"    "Framework"
   "other"        "Other"})

Step 3: Add badges in the document-row function

In document-row (lines 141-174), update the last [:td ...] cell (lines 165-173). Change from:

[:td (or (erp.ui.components/format-date renewal-date) "\u2014")
 (when-let [cs (contract-status type structured-data)]
   [:span {:class (str "badge badge-contract-" (name cs))
           :style "margin-left: 8px;"}
    (case cs
      :active        "Active"
      :expiring-soon "Expiring"
      :expired       "Expired"
      :pending       "Pending")])]

to:

[:td (or (erp.ui.components/format-date renewal-date) "\u2014")
 (when (= "contract" (some-> type name))
   (let [ct (:contract-type structured-data)]
     (list
      (when ct
        [:span.badge.badge-contract-subtype {:style "margin-left: 8px;"} (get contract-type-labels ct ct)])
      (when (contract.schema/financially-active? ct)
        [:span.badge.badge-financial {:style "margin-left: 4px;"} "Financial"]))))
 (when-let [cs (contract-status type structured-data)]
   [:span {:class (str "badge badge-contract-" (name cs))
           :style "margin-left: 4px;"}
    (case cs
      :active        "Active"
      :expiring-soon "Expiring"
      :expired       "Expired"
      :pending       "Pending")])]

Step 4: Run lint

Run: cd orcha && clj-kondo --lint src/com/getorcha/erp/http/document_management.clj Expected: 0 errors

Step 5: Commit

git add orcha/src/com/getorcha/erp/http/document_management.clj
git commit -m "feat: Add contract-type and financial badges to document list"

Task 5: Add CSS for New Badges

Files:

Step 1: Add new badge styles

After line 5246 (.badge-contract-pending), add:


/* Contract sub-type badge */
.badge-contract-subtype { background: rgba(56, 139, 253, 0.15); color: #58a6ff; }

/* Financially active badge */
.badge-financial { background: rgba(31, 111, 139, 0.2); color: #3bc9db; }

Step 2: Commit

git add orcha/resources/erp/public/css/style.css
git commit -m "feat: Add CSS for contract-type and financial badges"

Task 6: Add Financially Active Filter

Files:

Step 1: Add "Financially Active" filter tab

In the status filter tabs section (lines 253-257), add a new tab after "Processing":

[:a.filter-tab {:href (tab-url "financially-active") :class (when (= status-filter "financially-active") "active")} "Financially Active"]

The full block (lines 253-257) becomes:

[:div.status-filter-tabs
 [:a.filter-tab {:href (tab-url "all") :class (when (= status-filter "all") "active")} "All"]
 [:a.filter-tab {:href (tab-url "completed") :class (when (= status-filter "completed") "active")} "Completed"]
 [:a.filter-tab {:href (tab-url "needs-review") :class (when (= status-filter "needs-review") "active")} "Needs Review"]
 [:a.filter-tab {:href (tab-url "processing") :class (when (= status-filter "processing") "active")} "Processing"]
 [:a.filter-tab {:href (tab-url "financially-active") :class (when (= status-filter "financially-active") "active")} "Financial"]]

Step 2: Add filter logic in build-where

In build-where (lines 366-385), add a new clause for financially-active status. After the (= status-filter "processing") clause (line 384-385), add:

(= status-filter "financially-active")
(conj [:= [:cast :document.type :text] "contract"]
      [:in [:raw "document.structured_data->>'contract-type'"]
       ["loan" "lease" "rental" "insurance" "subscription"]])

Step 3: Run lint

Run: cd orcha && clj-kondo --lint src/com/getorcha/erp/http/document_management.clj Expected: 0 errors

Step 4: Commit

git add orcha/src/com/getorcha/erp/http/document_management.clj
git commit -m "feat: Add Financially Active filter tab to Document Management"

Task 7: Write Tests

Files:

Step 1: Add financially-active? unit tests

Create orcha/test/com/getorcha/schema/contract/structured_data_test.clj:

(ns com.getorcha.schema.contract.structured-data-test
  (:require [clojure.test :refer [deftest is testing]]
            [com.getorcha.schema.contract.structured-data :as contract.schema]))


(deftest test-financially-active?
  (testing "financially active types return true"
    (doseq [t ["loan" "lease" "rental" "insurance" "subscription"]]
      (is (true? (contract.schema/financially-active? t))
          (str t " should be financially active"))))

  (testing "non-financial types return false"
    (doseq [t ["purchase" "service" "supply" "nda" "framework" "other"]]
      (is (false? (contract.schema/financially-active? t))
          (str t " should NOT be financially active"))))

  (testing "nil returns false"
    (is (false? (contract.schema/financially-active? nil)))))


(deftest test-financially-active-types
  (testing "contains exactly the expected types"
    (is (= #{"loan" "lease" "rental" "insurance" "subscription"}
           contract.schema/financially-active-types))))

Step 2: Run the new test to verify it passes

Run: cd orcha && clojure -X:test :includes '["com.getorcha.schema.contract.structured-data-test"]'

If that syntax doesn't work with the test runner, run the full suite: Run: cd orcha && clojure -X:test Expected: All tests pass, 0 failures, 0 errors

Step 3: Commit

git add orcha/test/com/getorcha/schema/contract/structured_data_test.clj
git commit -m "test: Add unit tests for financially-active? helper"

Task 8: Run Full Test Suite and Lint

Step 1: Run lint

Run: cd orcha && clj-kondo --lint src:dev:test Expected: 0 errors (warnings OK if pre-existing)

Step 2: Run full test suite

Run: cd orcha && clojure -X:test Expected: All tests pass, 0 failures, 0 errors

Step 3: Final commit (if any fixes needed)

Only if lint/tests required fixes.


Task 9: Create Feature Branch and PR

Step 1: Create branch from master

git checkout -b financially-active-contracts master

Note: If you've been committing on master, cherry-pick or rebase the commits onto the new branch instead.

Step 2: Push and create PR

git push -u origin financially-active-contracts
gh pr create --title "feat: Support financially active contracts (#278)" --body "..."

Link PR to issue #278.