Catalyst / admin/Apex 14.8 GB / 57.8 GB 40.0 GB free
Help Sign in

admin / Apex

public

Bid Management and Orchestration Tool with AI Capability

Code Issues Pull requests Pipelines Packages Security Insights Wiki Settings
Apex / Synapse-Apexv2 / DECISIONS.md 13349 B · main
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# Build decisions (v1)

Where the blueprint left a judgement call, the simplest option consistent with the
acceptance criteria was chosen. Notable decisions:

- **Schema management:** v1 creates tables via `Base.metadata.create_all` on startup
  plus a seed routine, rather than Alembic migrations. This keeps `docker compose up`
  a one-command boot. **Follow-up:** add Alembic and generate an initial migration
  before any production use / schema change.
- **Async work:** document parsing and all AI calls run on Celery (Redis broker), as
  specified. The UI dispatches jobs and polls by refreshing; a dedicated progress
  endpoint / SSE is a follow-up (blueprint §7 batching note).
- **AI graceful degradation:** with no `ANTHROPIC_API_KEY`, extraction/generation
  return labelled placeholders so the full workflow is demoable offline (blueprint §10).
- **AI model usage:** default `claude-opus-4-8`, adaptive thinking + `effort: high`,
  streaming for long-form generation, no `budget_tokens`/sampling params. Structured
  extraction currently uses a strict-JSON prompt + parse rather than `messages.parse()`
  with Pydantic tool schemas — a straightforward hardening follow-up.
- **Document input to the model:** v1 extracts text server-side (pypdf/python-docx/
  openpyxl) and passes text. Native PDF document blocks / Files API upload is a
  follow-up for higher-fidelity extraction on complex PDFs.
- **Capability grounding in Module 2:** responses are grounded by passing approved
  capabilities into the prompt (first 12 by simple selection). A keyword/embedding
  retrieval step is a follow-up for large libraries.
- **Cost-of-bid rate:** production cost on the dashboard uses a blended internal rate
  (£45/hr) for v1; wiring it to each allocated resource's cost rate is a follow-up.
- **User deletion:** soft delete (deactivate); anonymisation-on-request is a follow-up.
  Audit entries are retained.
- **Rate versioning:** rate changes are stored on the resource type; per-bid rate
  snapshots exist on cost lines (`rate_snapshot`) and team members. A full
  effective-dated `rate_versions` child table is a follow-up.
- **Money:** all cost/pricing maths use `Decimal`; DB columns are `Numeric`. Unit
  tested in `backend/tests/test_costing.py`.
- **Exports:** DOCX (main response), XLSX (cost + pricing), PDF (summary). The
  internal bid-production-cost page is intentionally excluded from the client-facing
  DOCX.

## v1.1 feature additions (2026-07-07)

- **Opportunity fields:** `opportunity_value`, `contract_duration_months`, `web_link`
  added to the bid (create form + editable Overview; web link is click-through).
- **Frameworks:** full add/amend/delete in the admin panel.
- **Resources:** add/amend/delete plus an **hourly⇄daily rate basis toggle** —
  editing one basis rederives the other (×/÷8); both are stored so the cost engine and
  displays stay consistent. Delete is a soft-delete (hidden from selection; existing
  bid snapshots unaffected).
- **Non-people resource costs:** user-entered cost lines (`group="non_people"`) held in
  `cost_sheet.inputs.non_people` and re-materialised on every recalculation, so engine
  rebuilds never wipe them.
- **Gantt chart:** auto-rendered from plan tasks (inline SVG component), milestones as
  diamonds, tasks as bars, today marker, colour by status. Uses the product's
  indigo/gold design system rather than a generic charting palette for visual
  consistency.
- **Response editing & word limits:** responses remain editable inline; a per-requirement
  `word_limit` shows a live word count that flags over-limit, and the limit is passed to
  the AI as a hard constraint during generation.
- **Per-bid audit trail:** added `audit_log.bid_id`; bid-scoped actions now stamp it, and
  each bid's **Activity** tab shows exactly which login did what and when.
- **Clickable workflow bar:** the lifecycle is rendered as coloured rounded boxes
  (completed=green, current=indigo, actionable=gold-outlined) that advance the bid on
  click, gated to Bid Manager/Approver; terminal outcomes (won/lost/withdrawn) appear at
  submission.
- **Guides:** `docs/USER_GUIDE.md` and `docs/ADMIN_GUIDE.md` added.

> **Schema note:** these additions introduce new columns (`bids.opportunity_value/…`,
> `bid_requirements.word_limit`, `audit_log.bid_id`). Because v1 still uses
> `create_all` rather than Alembic, an **existing** database won't gain the columns
> automatically — run `docker compose down -v` (destroys data) then `up` on an already
> deployed instance, or apply the columns manually. A fresh deployment is unaffected.
> Alembic remains the planned follow-up.

## v1.2 feature additions (2026-07-07)

- **Licence cost CRUD:** full add/amend/delete in the admin Resources panel (backend
  endpoints already existed; this wired the UI). Deletes are soft (hidden from
  selection).
- **AI Integration (Assistant) toggle at admin level:** a `SystemSetting`
  (`ai_assistant`) gates a new **advisory** tool, kept entirely separate from the
  existing extraction/generation pipeline (which is unchanged and still gated only by
  the API key). Exposed to clients via `/api/config.assistant_admin_enabled`.
- **Per-bid Assistant:** `bids.assistant_enabled` toggled from the workspace Assistant
  tab (Bid Manager). Turning it on requires the admin toggle to be on first
  (enforced server-side). The Assistant:
  - gives **bid-level advice** and **per-response enhancements**, grounded only in
    in-app data (approved capabilities, requirements, win themes, word limits);
  - runs a **hallucination self-check** — the model drafts, then audits its own draft
    against the supplied evidence and removes unsupported claims; the removed claims and
    a `guardrail` object (`checked`, `removed`, `clean`, `claims`) are surfaced as a
    guard-rail badge in the UI;
  - is **advisory only** — an enhancement is written to the response **exclusively via a
    human "Approve & apply"** action (`assistant_suggestion_applied`); suggestions can be
    dismissed; the whole lifecycle is persisted (`assistant_suggestions` table) and
    every step is written to the per-bid **audit trail** with the acting login.
  - **Graceful degradation:** with no API key the Assistant still creates suggestions but
    marks `guardrail.checked = false` and returns a labelled placeholder, so the flow is
    demoable offline (consistent with the rest of the app).

> **Schema note:** adds `bids.assistant_enabled` and a new `assistant_suggestions`
> table. As with earlier versions (no Alembic yet), an **existing** database needs
> `docker compose down -v` then `up` to pick up the new column; the new table is created
> automatically. Fresh deployments are unaffected.

## v1.3 feature additions (2026-07-07)

- **Framework active toggle:** frameworks can be switched on/off (existing `active`
  column + PATCH). Inactive frameworks are hidden from bid selection and from the
  Assistant's alignment, without deletion.
- **Assistant framework alignment:** a new `framework_align` assistant action that
  advises how to better map a response to the bid's *active* frameworks (control
  references, terminology, evidence), self-checked for hallucinations and applied only
  on human approval — same lifecycle as response enhancement. Rejected (400) when the
  bid has no active frameworks.
- **Dynamic thought cloud:** the Assistant surfaces its latest proposed suggestion in a
  floating, animated thought-cloud (`components/AssistantCloud.tsx`) anchored to a ✦
  floating button. It polls per-bid suggestions while the Assistant is active.
- **Ping + mute:** a short two-tone ping (Web Audio oscillator — no asset file, avoids
  CSP/bundle concerns) plays when the cloud appears. A user-level mute toggle on the
  cloud persists to `localStorage` (`apex_assistant_sound`).
- **Acknowledge / reappear / summon:** the cloud disappears when acknowledged (*Got
  it*), with acknowledged suggestion ids persisted per-bid in `localStorage`
  (`apex_ack_<bidId>`) so the same idea doesn't re-pop. It reappears only when a **new**
  proposed suggestion arrives or when the user **summons** it via the ✦ button
  (summoning an empty queue triggers fresh bid-level advice).
- **Verified live in-browser** (Vite dev + uvicorn/SQLite): cloud auto-pops on entering
  a bid with a pending suggestion, guard-rail badge renders ("✓ Hallucination
  self-check — N removed"), acknowledge hides + persists, summon re-shows, mute toggles
  + persists, and Approve & apply writes the enhancement to the response and audits it —
  no console errors.

## v1.4 feature additions (2026-07-07)

- **Effort rules — full CRUD UI + access:** effort-rule add/amend/delete is available to
  **Administrator, Bid Manager and Finance** (Bid Manager added this version; Finance
  retained). The admin Effort-rules panel, previously read-only, gained a full editor:
  add form (trigger / endpoint type / per-qty / resource / recurring & one-off hours),
  inline amend, and delete. The tab is shown to those three roles. All create/amend/delete
  actions are audited against the acting login. The CRUD + RBAC pattern was verified E2E
  (a non-admin role performs full CRUD, an excluded role gets 403, actions audited).

## v1.5 fixes (2026-07-08)

- **Root-cause fix — AI SDK version:** `anthropic` was pinned to `0.42.0`, which predates
  adaptive thinking and `output_config`. With a real key, every AI call passed
  `thinking={"type":"adaptive"}` / `output_config={"effort":...}` that the old SDK
  rejected with `TypeError`, and the error was swallowed → "the Assistant does nothing."
  Bumped to **`anthropic==0.116.0`** (verified: it accepts the streaming + adaptive
  thinking + effort call shape; a fake key now yields an `AuthenticationError`, not a
  `TypeError`). **Requires an image rebuild:** `docker compose build backend worker &&
  docker compose up -d`.
- **Live AI status endpoint:** `GET /api/ai/status` performs a minimal real call
  (cached ~60s) and returns `connected` / `disabled` / `error` with a classified detail
  (invalid key, model not found, cannot reach API, rate limited, …).
- **Obvious dashboard indicator:** a colour-coded pill in the dashboard header —
  green "AI connected & working", grey "AI not configured", red "AI error" — with the
  model name and detail on hover; click to re-check.
- **No more silent failures:** the Assistant thought-cloud now shows a "Thinking…" state
  while working and surfaces errors (previously `catch {}` swallowed them); the
  Responses-tab ✦ actions show an immediate "working…" message and report errors.
- **Snappier Assistant:** assistant advisory calls now run at `medium` effort (was
  `high`) for lower latency; extraction/generation stay at `high`.

## v2.0 — Answer Library MVP (2026-07-08, Synapse-Apexv2)

New module: a searchable catalogue of tender questions & responses (blueprint:
`docs/ANSWER_LIBRARY_BLUEPRINT.md`). Implemented the MVP:

- **Model:** `answer_entries` (question/answer/summary/category/tags/frameworks,
  provenance source_type/source_bid_id/source_response_id, client, outcome, status,
  is_master, reuse_count, word_count) + `answer_reuse_log`.
- **Fills itself:** `update_response` harvests on **approval** (upsert keyed by
  `source_response_id`); `change_state` propagates **won/lost** outcome onto that bid's
  entries. Admin/BM **Harvest approved** backfills existing approved responses (idempotent).
- **Search (MVP):** DB-agnostic ILIKE + Python filter/rank (master → won → reuse →
  recency), filters by category/client/outcome/framework, `/facets` for dropdowns.
  **Deliberately not** Postgres FTS/pgvector yet — keeps it portable and testable on
  SQLite; semantic search is the documented Phase-2 step (Anthropic has no embeddings API).
- **Curation:** manual add, edit, mark master, archive; reuse logging + full audit.
- **Frontend:** left-nav **Answer Library** page (search/filters/Q&A cards/detail modal/
  add/master/archive/copy) + **"Find in Answer Library"** on the Responses tab that
  inserts a proven answer into a draft and logs the reuse.
- **RBAC:** all roles search/view/copy; Bid Manager + Contributor curate; Admin + Bid
  Manager backfill.
- **Verified:** frontend build clean; E2E green (auto-harvest, keyword/framework search,
  won propagation, reuse+audit, master ranking, manual add, archive, idempotent backfill);
  unit tests 7/7. Guides updated + PDFs regenerated.

> **Schema note:** new tables `answer_entries` + `answer_reuse_log` are created
> automatically by `create_all`. A fresh v2 deployment needs nothing special.

## Build phase coverage vs blueprint §11

- Phase 1 (foundation, auth, RBAC, MFA, audit, shell): **complete**
- Phase 2 (Module 5 + admin data, frameworks, effort rules, workflow view): **complete**
- Phase 3 (Module 1 capability library): **complete**
- Phase 4 (bids + Module 2, requirement gate, plan, responses): **complete**
- Phase 5 (Modules 3 & 4, cost + pricing waterfall + AI justification): **complete**
- Phase 6 (Module 6 package assembly, approve/request-changes, exports, state machine): **complete**
- Phase 7 (polish: dashboard tiles/filters, seed demo data, AI usage reporting): **partial** — tiles and seed are in; richer AI-usage reporting and notifications are follow-ups.