Commit Graph

332 Commits

Author SHA1 Message Date
Ubuntu bb80ec115a docs(spec): fix F2-A graph isolation — ReportAgent queries graph_id_simulation only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 20:38:20 +00:00
Ubuntu a1862c1c86 docs(spec): update F2-A spec — add agent creation/deletion and graph isolation (ex F2-D)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 20:32:33 +00:00
Ubuntu 26f0b72b3c docs(spec): add F2-A design spec for agent edit, regen and clone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 20:12:10 +00:00
Ubuntu 607a2640e1 feat(history): use listProjects API for project recovery in home page
Replace getSimulationHistory (simulation API) with listProjects (graph API)
and adapt all template references from simulation_id/report_id fields to
project_id/graph_id fields matching the new project data model.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:31:53 +00:00
Ubuntu 1eae54346f feat(frontend-api): add listProjects() to graph API client 2026-05-03 01:30:11 +00:00
Ubuntu 17a547e9f0 test(graph-api): add integration tests for project CRUD endpoints
8 tests covering list, get, create, delete, and reset endpoints via
Flask test client with in-memory SQLite and mocked storage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:29:12 +00:00
Ubuntu 83b69dfd87 fix(graph-api): fix build_graph endpoint for dict-based ProjectManager
Convert all project.attribute accesses to project["key"]/project.get("key"),
use save_project({...}) dict calls, and wire save_graph_record/complete_graph_record
helpers for proper graph persistence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:24:56 +00:00
Ubuntu 5d6d4d787a fix(graph-api): cleanup orphan project on ontology generation failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:23:15 +00:00
Ubuntu 284f962e17 fix(graph-api): rewrite generate_ontology/import_ontology to use dict ProjectManager
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:20:32 +00:00
Ubuntu ea9ac6a1cd fix(graph-api): fix project/task dict access after ProjectManager refactor
Replace .to_dict() calls and attribute access with direct dict usage,
add get_storage() import for delete_project, and rewrite reset_project
to use save_project() with a partial dict instead of mutating an ORM object.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:17:21 +00:00
Ubuntu 8a6d00b26e refactor(project): clean up _to_dict delegation and remove unused import
- Remove unused `import io`
- Avoid double-encoding in save_extracted_text by caching encoded bytes
- Delegate _to_dict queries to get_ontology/get_latest_graph_external_id
- Add comment to save_ontology noting full versioning is planned for F2-3

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:16:03 +00:00
Ubuntu 949921344b feat(project): add ontology/graph persistence helpers to ProjectManager
- Add `from ..config import Config` import
- Convert `_to_dict` from @staticmethod to @classmethod; it now opens a
  fresh session to populate `ontology` and `graph_id` from OntologyModel
  and GraphModel respectively
- Use `db.expunge(proj)` before closing sessions in create_project,
  get_project and list_projects so `_to_dict` can open its own session
  without nesting conflicts (SQLite StaticPool safe)
- Add five new classmethods: save_ontology, get_ontology,
  save_graph_record, get_latest_graph_external_id, complete_graph_record

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:13:26 +00:00
Ubuntu 9ed2412745 test(conftest): add in_memory_db and task manager singleton reset fixtures; fix broken tests
- Replace conftest.py with two autouse fixtures: reset_graph_factory_singleton
  and reset_task_manager_singleton, plus in_memory_db fixture for tests
  requiring a real DB
- Rewrite test_project_task_recovery.py to use ProjectManager + SQLite in-memory
  DB instead of the removed Project dataclass (same guarantee: active_task_id
  persists and defaults to None)
- Fix db.py init_db() to import db_models before Base.metadata.create_all() so
  all ORM tables are registered and created on first startup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 00:15:42 +00:00
Ubuntu 0b760eed0b fix(task): rename loop var t→task_row to avoid shadowing locale.t import 2026-05-03 00:13:12 +00:00
Ubuntu 2478beb9ea feat(project): refactor ProjectManager to persist via SQLAlchemy + StorageService
Replace file-based JSON persistence with SQLAlchemy DB (ProjectModel/ProjectFileModel)
and StorageService for file content; remove Project dataclass; add 7 passing tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 00:11:12 +00:00
Ubuntu 1f43d35d59 feat(task): refactor TaskManager to persist tasks in SQLAlchemy DB
Replace in-memory dict-based TaskManager with a SQLAlchemy-backed implementation
using TaskModel. Tasks now survive process restarts. 6 new tests added and passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 00:10:16 +00:00
Ubuntu 479ae0b712 feat(app): inject SQLAlchemy DB and StorageService into Flask app factory
Initializes the database (via init_db) and registers the StorageService
instance in app.extensions['storage'] inside create_app(). Adds get_storage()
helper for convenient access from any Flask context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 00:08:13 +00:00
Ubuntu 868ce39577 fix(storage,db): path traversal fix, delete_prefix validation, remove dead import, factory uses Config
- local.py: use relative_to() for path traversal guard (fixes prefix-collision false negative)
- local.py: validate delete_prefix rejects empty/root prefix to prevent full-storage wipe
- local.py: remove unused `import os`
- db_models.py: remove dead UniqueConstraint import
- db_models.py: replace deprecated datetime.utcnow() with datetime.now(timezone.utc)
- factory.py: read STORAGE_TYPE and related settings from Config instead of os.environ directly; remove `import os`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 00:06:58 +00:00
Ubuntu aab0cd355a feat(alembic): add initial schema migration for all SQLAlchemy models
Initializes Alembic with autogenerated migration covering all 11 tables
(tasks, users, projects, project_files, ontologies, graphs, simulations,
reports, system_config, invitation_tokens, password_reset_tokens).
Adds *.db to .gitignore to exclude local SQLite dev database.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 00:04:18 +00:00
Ubuntu 999f6efa4f test(db): enable SQLite PRAGMA foreign_keys=ON in fixture for strict FK assertions 2026-05-02 23:56:58 +00:00
Ubuntu 773cc250c9 feat(db): add SQLAlchemy Base, session factory, and all ORM models
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 23:54:05 +00:00
Ubuntu 9e33f823d9 feat(storage): add StorageService protocol, LocalFSStorage, AzureBlobStorage, factory 2026-05-02 23:53:19 +00:00
Ubuntu ca2f9e2a8f feat(config): add DATABASE_URL, STORAGE_TYPE, AZURE_STORAGE_*, JWT config vars 2026-05-02 23:53:16 +00:00
Ubuntu dd1f713e42 chore(deps): add SQLAlchemy, Alembic, Azure Blob, bcrypt, flask-jwt-extended 2026-05-02 23:48:02 +00:00
Ubuntu d69d1976d8 docs(plan): add Fase 1 implementation plan for persistence infrastructure
Covers 9 tasks with TDD approach:
- Task 1: Dependencies (SQLAlchemy, Alembic, Azure Blob, bcrypt, flask-jwt-extended)
- Task 2: Config vars (DATABASE_URL, STORAGE_TYPE, AZURE_STORAGE_*, JWT_*)
- Task 3: SQLAlchemy models (all 11 entities)
- Task 4: Alembic migrations
- Task 5: StorageService (Protocol + LocalFS + AzureBlob + factory)
- Task 6: Flask app factory injection
- Task 7: TaskManager refactor → DB
- Task 8: ProjectManager refactor → DB + Storage
- Task 9: Test suite + e2e verification

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:40:18 +00:00
Ubuntu 6ec363add4 docs(persistencia): aclarir RBAC, auth provisional, forgot-password i look&feel
- Admin és també user: accés a tots els projectes + admin en pantalles separades
- Documentar auth provisional (DEMO_PASSWORD) a eliminar
- Afegir flux forgot-password amb resposta genèrica (no revela validesa email)
- Principi de seguretat: cap endpoint d'auth revela si un email existeix
- Look & feel: Sistema de Disseny Gencat, consistent amb AgentCAT

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:31:23 +00:00
Ubuntu 36107c2c69 docs(persistencia): afegir especificació completa de la capa de persistència
Disseny validat durant sessió de brainstorming. Cobreix:
- Model de dades SQLAlchemy 2.x (User, Project, Ontology, Graph, Simulation, Report, Task, SystemConfig)
- StorageService amb adaptadors LocalFS / Azure Blob (S3 preparat però diferit)
- Autenticació JWT + RBAC (user/admin) amb flux d'invitació
- SystemConfig per a configuració dinàmica (LLM keys, límits, features)
- 4 fases d'implementació amb criteris de verificació

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:03:47 +00:00
Ubuntu 49f4da51b1 fix(report): strip fabricated tool_result blocks to prevent LLM hallucination loop 2026-04-26 15:06:24 +00:00
Ubuntu 866ed421e2 fix(ontology): handle string attributes from LLM response to prevent TypeError crash
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 14:59:10 +00:00
Ubuntu 182a9525e7 fix(frontend): persist upload requirement to sessionStorage; friendly error when files lost on refresh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 14:57:20 +00:00
Ubuntu 75533e9319 fix(simulation): guarantee SQLite connection close with finally block 2026-04-26 14:56:52 +00:00
Ubuntu 117eabf607 feat(recovery): persist active_task_id to project.json for browser-refresh reconnection
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 14:54:44 +00:00
Ubuntu 656a3d7d5c fix(graph): cap get_all_edges to 5000 edges to prevent unbounded RAM growth 2026-04-26 14:50:21 +00:00
Ubuntu d09ee23cd3 feat: ontology import, project recovery, graphiti improvements, and docs
- Add ontology import from file (Step 1)
- Persist active task_id to project.json for browser-refresh recovery
- Add project list endpoint and frontend recovery UI
- Improve Graphiti backend stability and oasis profile generation
- Add TechnicalDesign.md and enterprise roadmap spec
- Update .gitignore to exclude secrets and local-only docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 14:28:14 +00:00
Ubuntu f854a0de12 chore(report): remove unused getReportDownloadUrl helper 2026-04-26 00:29:08 +00:00
Ubuntu b78c3721f2 fix(report): use Axios blob for authenticated downloads; remove dead closeDownloadMenu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 00:26:19 +00:00
Ubuntu 0235bd51e8 feat(report): add MD/PDF download dropdown button
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 00:14:09 +00:00
Ubuntu 7cd876bfbe feat(report): add getReportDownloadUrl helper
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 00:14:04 +00:00
Ubuntu 7daf8566ed fix(report): eliminate temp file leak in MD fallback; simplify invalid-format test 2026-04-26 00:11:40 +00:00
Ubuntu 8efedb55e5 feat(report): add PDF download endpoint via PyMuPDF
Adds ?format=md|pdf query param to GET /api/report/<id>/download.
PDF is generated from Markdown via fitz.Story (PyMuPDF). Also fixes
create_app() to support dict config and skip JWT auth in TESTING mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 00:07:09 +00:00
Ubuntu 0c732db90f chore(deps): add markdown>=3.6 for PDF generation 2026-04-25 23:57:46 +00:00
Ubuntu 364b6078e2 fix(deps): pin graphiti-core==0.28.2, override neo4j>=5.26.0
graphiti-core 0.28.2 has _extract_entity_attributes required by the
monkey-patch in GraphitiBackend. Override neo4j to resolve conflict
with camel-oasis==0.2.5 which pins neo4j==5.23.0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 23:20:25 +00:00
Ubuntu fb280011b7 fix(azure): add GRAPH_BACKEND, NEO4J, LLM_EMBED, LLM_SMALL to config and bicep
All variables now flow from config.sh through 2-build-deploy.sh to the
container env, so GRAPH_BACKEND=graphiti is honoured at runtime.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 22:42:58 +00:00
Ubuntu a209330b0b debug: log GRAPH_BACKEND and key presence at graph build start
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 22:18:26 +00:00
Ubuntu 058d260552 fix(azure): restore config.sh sourcing in deploy scripts; add --no-cache support
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 21:54:57 +00:00
Ubuntu 6e4e5c40dd chore: resolve .env.example merge conflict; keep feat/pluggable-graph-backend version
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 21:11:06 +00:00
Ubuntu 09935e53a0 refactor(graph): remove hardcoded ZEP checks, use get_graph_config_errors; add embed/small LLM env docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 21:10:40 +00:00
Ubuntu c074136a87 fix(llm): centralise Azure URL normalisation in parse_azure_url utility
Extract parse_azure_url from graphiti_backend into utils/llm_client so all
services (oasis_profile_generator, simulation_config_generator, graphiti_backend,
LLMClient) strip the /chat/completions suffix and api-version before passing
base_url to the OpenAI SDK, fixing 404 errors when the full Azure endpoint URL
is set in LLM_BASE_URL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 21:09:48 +00:00
Ubuntu e7ebcdff75 fix(graphiti): patch _extract_entity_attributes to flatten nested attr dicts
The previous fix applied _flatten_attributes too broadly, breaking graphiti's
internal ExtractedEntities validation (lists were converted to strings).

Instead, monkey-patch only _extract_entity_attributes — the exact function
that returns entity attribute dicts to node.attributes before Neo4j write.
Lists of primitives are preserved; only dict-valued attributes are flattened.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 20:24:08 +00:00
Ubuntu 6bce05dca2 fix(graphiti): flatten nested attribute dicts before Neo4j write; hide summary from properties panel
Graphiti's attribute extraction LLM sometimes returns values wrapped in
nested dicts ({"value": "CTTI"}) instead of plain strings. Neo4j rejects
these with TypeError: "Property values can only be of primitive types".

Fix: after _AzureGenericClient gets the LLM response, validate it through
the Pydantic response_model and call _flatten_attributes() so every value
reaching Neo4j is a scalar. Also add _flatten_attributes() helper.

UI: exclude 'summary' from the Properties section of the node detail panel
since it already appears in the dedicated Summary section below.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 20:08:39 +00:00