M8: GUI polish, n8n workflow-3 fixes, RAGcore retrieval root-cause and fix
GUI: dashboard Attention Queue presents a curated severity mix instead of pure severity-sort (grouped Now/Today/Later headers); Today's Movements seed data curated so a fresh reset shows a credible day (2+ departures, 2+ returns), with a new seed-integrity test; About Demo restructured into a compact grid with progressive disclosure for technical sections; Duplicate Merge shows match/conflict counts, hides matching fields by default, and previews the final merged record before confirmation. Repo hygiene: removed a stray empty `backend;C` directory and an untracked 31MB zip export; `.gitignore` now excludes future archive exports. n8n: fixed invalid JSON (a missing `},` between two node objects) in the committed `fleet-ops-vehicle-return.json` -- the file could not be parsed. Live-validated workflow 3 (RAGcore Procedure Sync): found and fixed a real defect (three body parameters had a stray trailing `}}`) and a missing Error Workflow wiring, both via the safe `n8n import:workflow` CLI path; exported the corrected, still- inactive workflow as the new source of truth and updated MANIFEST.md/check_drift.py. Publishing it (starts real daily unattended runs) remains a separate decision. RAGcore: root-caused and fixed (live, approved) the "zero retrieval candidates" bug -- a filesystem permission bug (`embedding_profiles.json` unreadable by the app's own runtime user) that broke every retrieval call before it reached Qdrant. Every other suspect (grants, scope resolution, Qdrant filters, embeddings) was verified healthy first. Found a second, deeper gap: the reranker adapter calls an Ollama HTTP route that does not exist on the deployed Ollama version, so `/v1/answers` still returns `not_answerable`. `KNOWLEDGE_PROVIDER` stays `demo` until that is resolved on the RAGcore side. Evidence-based MCP Hub integration status (real tool-call audit history, not just a boolean flag) replaces the old `configured`/`not_configured` guess. Full findings in `docs/final-integrations/current-state-audit.md`. Backend: 172 tests passing, ruff clean, mypy clean (50 files). Frontend: tsc clean, production build clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
3ebca9e9b7
commit
34df66d28c
+28
-22
@@ -18,7 +18,7 @@ credential values are never embedded; nodes reference named n8n credentials inst
|
||||
| Active status (as of 2026-08-04) | Active / Published |
|
||||
| Error Workflow | `Fleet Ops — Workflow Error Handler` (wired) |
|
||||
| Timeouts / bounded retries | `Record follow-up` HTTP node: 15s timeout, retry on fail (3 tries, 1000ms wait) |
|
||||
| Checksum (sha256) | `a6f399dd77a7203dec7c0ac95e8540abf55f2703da519e06f1c37f2e1220f609` |
|
||||
| Checksum (sha256) | `e5b6ba02a7824867620ceaf214224521d52de76337604b947f26f1b0b5432358` (updated 2026-08-05 — the committed file had invalid JSON, a missing `},` between two node objects; fixed, no live workflow change) |
|
||||
|
||||
## 2. Fleet Ops — Scheduled Data Quality Scan
|
||||
|
||||
@@ -37,33 +37,39 @@ credential values are never embedded; nodes reference named n8n credentials inst
|
||||
|
||||
## 3. Fleet Ops — RAGcore Procedure Sync
|
||||
|
||||
Not yet built, but no longer blocked. Credential issuance for the `fleet-ops` application
|
||||
previously failed 100% of the time with an opaque rejection ("authoritative service-account
|
||||
state rejected issuance" via the raw API; a generic error via the admin UI). Root-caused to
|
||||
a genuine bug in RAGcore itself — a cross-transaction race in
|
||||
`src/ragcore/api/v1/control/dependencies.py` where `get_control_application` and
|
||||
`get_credential_service` each opened their own independent database transaction, so a
|
||||
freshly-created service account was invisible to the immediately-following credential-issue
|
||||
read. Fixed in RAGcore (with explicit owner approval) by sharing one request-scoped
|
||||
transaction between both dependencies; verified against RAGcore's own test suite (64
|
||||
passing) and deployed to the live instance. A working credential now exists: n8n credential
|
||||
**"RAGcore Sync Token"** (Header Auth, `Authorization: Bearer <token>`), scope
|
||||
`sources:sync` for `fleet-ops`. Will build
|
||||
`n8n/workflows/fleet-ops-ragcore-procedure-sync.json` against the real RAGcore contract
|
||||
(`POST /v1/uploads`, `GET /v1/knowledge-spaces`, etc. — see
|
||||
`contracts/ragcore-contract-assumptions.md` and the live inspection notes in
|
||||
`docs/live-ai-integration/n8n-current-state.md`) next.
|
||||
Fully built and saved live (6 real nodes: Schedule Trigger → List procedures → Prepare
|
||||
uploads → Upload to RAGcore → Summarize sync result → Report sync result to Fleet Ops),
|
||||
but **deliberately not published/active** — the Schedule Trigger runs daily at midnight,
|
||||
so activating it starts real, unattended runs against production RAGcore and Fleet Ops;
|
||||
that is a separate, explicit go-live decision, not something to flip silently.
|
||||
|
||||
While validating this workflow (2026-08-05), found and fixed a real defect: the "Report
|
||||
sync result to Fleet Ops" node's three body-parameter expressions each had a stray
|
||||
trailing `}}` (e.g. `={{ $json.execution_id }} }}` instead of `={{ $json.execution_id
|
||||
}}`), which would have sent malformed values on every real run. Fixed via `n8n
|
||||
import:workflow` (the safe CLI path — not the REST API, which caused a prior wipe
|
||||
incident in this environment) against the same live workflow ID, keeping it inactive;
|
||||
re-exported and verified the fix applied with no other change (still 6 real nodes,
|
||||
`active: false`). Also found and fixed a second gap: `settings.errorWorkflow` was unset
|
||||
(workflows 1-2 wire `"errorWorkflow": "Xppn2rAEqUuyiCJF"`, workflow 3 did not) — wired it
|
||||
the same way via the same CLI import path, re-verified.
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| File | `fleet-ops-ragcore-procedure-sync.json` (not yet created) |
|
||||
| Live workflow ID | — |
|
||||
| Active status | Not built |
|
||||
| File | `fleet-ops-ragcore-procedure-sync.json` |
|
||||
| Purpose | Sync the trilingual procedure documents from Fleet Ops into RAGcore as source documents, keeping stable per-document IDs and skipping unchanged content. |
|
||||
| Trigger | Schedule Trigger (daily at midnight) |
|
||||
| Event contract | N/A — HTTP-triggered sync. Reads `GET /api/v1/integrations/n8n/procedures`, uploads via RAGcore's `POST /v1/uploads`, reports via `POST /api/v1/integrations/n8n/procedures-sync-result`. |
|
||||
| Required credentials | `Fleet Ops Service Token` (Header Auth, on the procedures-list and result-report calls); `RAGcore Sync Token` (Header Auth, `sources:sync` scope, on the upload call) |
|
||||
| Live workflow ID | `6wbkc4d1AouGpmWT` |
|
||||
| Active status (as of 2026-08-05) | Built / Saved / **Inactive** (not published — daily unattended runs require a separate explicit go-live decision) |
|
||||
| Error Workflow | `Fleet Ops — Workflow Error Handler` (wired) |
|
||||
| Checksum (sha256) | `643c0515a50fed3d35e28f0b8cb17841f6f8d91699944980b5c56e619d5bf2a6` |
|
||||
|
||||
## 4. Fleet Ops — Workflow Error Handler
|
||||
|
||||
Central technical workflow attached to workflows 1-2 via n8n's per-workflow "Error
|
||||
Workflow" setting (workflow 3 will be wired the same way once it exists). Receives n8n's
|
||||
Central technical workflow attached to all three other Fleet Ops workflows (1, 2, 3) via
|
||||
n8n's per-workflow "Error Workflow" setting. Receives n8n's
|
||||
standard Error Trigger payload, derives a bounded/secret-free failure report (safe error
|
||||
category, truncated summary, no stack trace, no headers/tokens), and POSTs it to Fleet
|
||||
Ops, which registers an audit event idempotently keyed on `execution_id`.
|
||||
|
||||
@@ -33,6 +33,7 @@ KNOWN_WORKFLOWS = [
|
||||
("fleet-ops-vehicle-return.json", "mobilityops-return-processing"),
|
||||
("fleet-ops-data-quality-scan.json", "mobilityops-scheduled-quality-scan"),
|
||||
("fleet-ops-error-handler.json", "Xppn2rAEqUuyiCJF"),
|
||||
("fleet-ops-ragcore-procedure-sync.json", "6wbkc4d1AouGpmWT"),
|
||||
]
|
||||
|
||||
# Fields that legitimately differ between a committed definition and the live instance
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
{
|
||||
"id": "6wbkc4d1AouGpmWT",
|
||||
"name": "Fleet Ops — RAGcore Procedure Sync",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
128,
|
||||
-144
|
||||
],
|
||||
"id": "08f41c46-d5a9-4cb9-beec-0f074a9eb7bc",
|
||||
"name": "Sticky Note"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"rule": {
|
||||
"interval": [
|
||||
{}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "n8n-nodes-base.scheduleTrigger",
|
||||
"typeVersion": 1.3,
|
||||
"position": [
|
||||
-144,
|
||||
-144
|
||||
],
|
||||
"id": "6edcd359-08eb-4d88-98e9-5ca0625047cc",
|
||||
"name": "Schedule Trigger"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "http://192.168.10.150:1236/api/v1/integrations/n8n/procedures",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth",
|
||||
"options": {
|
||||
"timeout": 15000
|
||||
}
|
||||
},
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
80,
|
||||
-144
|
||||
],
|
||||
"id": "b66d3ee4-6264-48ab-89fc-aeb4d1597435",
|
||||
"name": "List procedures",
|
||||
"retryOnFail": true,
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"name": "Fleet Ops Service Token"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const documents = $input.first().json.documents;\nconst results = [];\nfor (const doc of documents) {\n const binary = await this.helpers.prepareBinaryData(Buffer.from(doc.content, 'utf-8'), doc.document_id + '.md', 'text/markdown');\n results.push({json: {id: doc.id, language: doc.language, document_id: doc.document_id, title: doc.title, version: doc.version, content_hash: doc.content_hash}, binary: {file: binary}});\n}\nreturn results;"
|
||||
},
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
304,
|
||||
-144
|
||||
],
|
||||
"id": "e9699a7a-87ff-4603-b89b-553dc7f2f29d",
|
||||
"name": "Prepare uploads"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "POST",
|
||||
"url": "https://rag.itworx.tech/v1/uploads",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth",
|
||||
"sendHeaders": true,
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Idempotency-Key",
|
||||
"value": "={{ $json.id + '-' + $json.content_hash }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sendBody": true,
|
||||
"contentType": "multipart-form-data",
|
||||
"bodyParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "space_id",
|
||||
"value": "f4c91e49-5cf9-48ba-b3d6-e0e9854ebccc"
|
||||
},
|
||||
{
|
||||
"name": "source_id",
|
||||
"value": "={{ $json.id }}"
|
||||
},
|
||||
{
|
||||
"parameterType": "formBinaryData",
|
||||
"name": "file",
|
||||
"inputDataFieldName": "file"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"timeout": 20000
|
||||
}
|
||||
},
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
528,
|
||||
-144
|
||||
],
|
||||
"id": "6d38f228-ed82-44a7-bc59-c785767d4f35",
|
||||
"name": "Upload to RAGcore",
|
||||
"retryOnFail": true,
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"name": "RAGcore Sync Token"
|
||||
}
|
||||
},
|
||||
"onError": "continueRegularOutput"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const items = $input.all();\nlet synced = 0;\nlet failed = 0;\nfor (const item of items) {\n if (item.json && item.json.error) {\n failed += 1;\n } else {\n synced += 1;\n }\n}\nreturn [{ json: { execution_id: String($execution.id), synced, failed } }];"
|
||||
},
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
640,
|
||||
-144
|
||||
],
|
||||
"id": "4b90056e-29f8-4df0-b7b4-695f4b9e0004",
|
||||
"name": "Summarize sync result"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "POST",
|
||||
"url": "http://192.168.10.150:1236/api/v1/integrations/n8n/procedures-sync-result",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth",
|
||||
"sendBody": true,
|
||||
"bodyParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "execution_id",
|
||||
"value": "={{ $json.execution_id }}"
|
||||
},
|
||||
{
|
||||
"name": "synced",
|
||||
"value": "={{ $json.synced }}"
|
||||
},
|
||||
{
|
||||
"name": "failed",
|
||||
"value": "={{ $json.failed }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
848,
|
||||
-144
|
||||
],
|
||||
"id": "953cd587-3d3e-44b5-907c-92b8355b00e3",
|
||||
"name": "Report sync result to Fleet Ops",
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"name": "Fleet Ops Service Token"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Schedule Trigger": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "List procedures",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"List procedures": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Prepare uploads",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Prepare uploads": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Upload to RAGcore",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Upload to RAGcore": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Summarize sync result",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Summarize sync result": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Report sync result to Fleet Ops",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"executionOrder": "v1",
|
||||
"binaryMode": "separate",
|
||||
"availableInMCP": false,
|
||||
"errorWorkflow": "Xppn2rAEqUuyiCJF",
|
||||
"callerPolicy": "workflowsFromSameOwner"
|
||||
},
|
||||
"active": false,
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": false
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
@@ -68,6 +68,7 @@
|
||||
"retryOnFail": true,
|
||||
"maxTries": 3,
|
||||
"waitBetweenTries": 1000
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
|
||||
Reference in New Issue
Block a user