Compare commits
3 Commits
f0682eea38
...
85249a3d23
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85249a3d23 | ||
|
|
b11dc7b771 | ||
|
|
5cbd8f1e94 |
@@ -15,7 +15,7 @@
|
||||
| WeChat roster attachment | Strict transport envelope plus one structured `payload.attachments[]` entry | Existing `awaiting_attachment` task | Explicit conversation ID wins; otherwise strict `Conversation:` supplies the fallback. Placeholder text alone never creates a task. |
|
||||
| Internal attachment download | Credential-free HTTPS URL | Bounded in-memory workbook bytes | Internal/private DNS answers are allowed; the selected address is pinned, every redirect is revalidated, and URL/host/IP/bytes are omitted from logs. |
|
||||
| Operational diagnostics | Service, request, task, parser, AgentBus, attachment, database, and cleanup stages | Structured stdout/stderr and bounded Docker logs | Correlation identifiers, codes, outcomes, and durations only; no secrets or business payloads. |
|
||||
| Platform operations oversight | Durably assigned manual/AgentBus task, encrypted instruction history, and readable outcome | Team-lead-only leadership projection | Immutable assignee is the employee dimension; unassigned historical AgentBus rows are excluded. Display-only summaries plus explicit filters drive an aggregate-first task/person/input/output/time/type/completion view, with bounded list reads and page-only detail hydration. |
|
||||
| Platform operations oversight | Durably assigned manual/AgentBus task, encrypted instruction history, and readable outcome | Team-lead-only leadership projection | Immutable assignee is the employee dimension; unassigned historical AgentBus rows are excluded. Display-only summaries plus explicit filters drive an aggregate-first task/person/input/output/time/type/completion view. Range-wide candidate reads exclude complete operation JSON; only unresolved legacy classification receives compact action/kind/mode fields, while complete payload hydration stays limited to keyword search and the current 20-row page. |
|
||||
| Leader task summary | Future stable manual/AgentBus task outcome for a durably assigned non-admin employee | Privacy projection → encrypted organization/revision outbox → fixed external Webhook → leader group | Independent from AgentBus task replies and ERP execution; strict success means accepted, not delivered, and rejected/uncertain attempts terminate without automatic retry. |
|
||||
| Shared-child batch creation | Inclusive departure range plus exact product/customer/counts | Complete read-only parent enumeration → validated date/tid target list → sequential single-child adapter reuse | All targets are known before the first write; execution is deterministic and stops at the first blocked, failed, or uncertain result with remaining targets not started. |
|
||||
| Browser worker selection | Immutable task assignee | One fresh account-bound browser connection | The heartbeat must prove the expected ERP identity from one unique login node by normalized exact equality; missing, duplicate, blank, substring-only, or mismatched identity is non-executable, with failover only after staleness. |
|
||||
|
||||
@@ -4,6 +4,7 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
|
||||
|
||||
## Integrated Through
|
||||
|
||||
- Source commit `5cbd8f1` from feature task `20260903-dashboard-refresh-no-data-b4e82f1a`, integrated as merge commit `b11dc7b`, for lightweight leadership-dashboard candidate reads that exclude full `operation` JSON, hydrate only the compact `action`/`kind`/`mode` shape needed by unresolved legacy classification, and retain complete payloads only for keyword search and current-page detail.
|
||||
- Integration task `20260909-business-instruction-batch-child-7e3c1a94` synchronized operator input catalog/DOCX `0.5.127` with all 19 system routes, adding the copyable `散拼团多个新增子单` entry while keeping that route Program-only and leaving the five Skills at `0.5.126`.
|
||||
- Source commit `be17f6c` from feature task `20260908-leader-webhook-api-7c4e9a12`, integrated as merge commit `295409b`, for organization-level external Webhook delivery of privacy-bounded leader summaries, migration `023_leader_summary_webhook_delivery`, and AUTH-005's one-attempt accepted-versus-delivered boundary.
|
||||
- Source commit `6ac90f8` from feature task `20260908-shared-child-batch-create-4e7c2a91`, integrated as merge commit `0d20544`, for Program-only `shared_child_order_batch_create`, parser `v1.0.7`, migration `022_shared_child_order_batch_create`, complete pre-write target enumeration, deterministic stop-on-first-non-success execution, and extension `0.5.170`.
|
||||
@@ -43,7 +44,7 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
|
||||
|
||||
## Current Focus
|
||||
|
||||
Operate the repository's current extension `0.5.170`, Program parser `v1.0.7`, Skills `0.5.126`, business-instruction `0.5.127`, roster normalizer `v1.4.0`, and migrations through `023_leader_summary_webhook_delivery` safely. The machine registry and operator input catalog contain 19 routes; the external Agent remains limited to its original 18 and the two passenger-list routes plus shared-child batch creation are Program-only. Administrators manage accounts, channels, employee grants, parser routing, automation settings, and audit but never enter the task data plane. Team leads/users own normal task operations through immutable assignment; same-account work remains FIFO and single-active while distinct accounts are independent. Team leads alone receive the read-only assignee-based dashboard. Future privacy-bounded organization summaries use one protected external Webhook and a separate encrypted one-attempt outbox, not a leader AgentBus route. Database migration, extension reload, route grants, service rollout, live ERP validation, and any external Webhook canary remain separately authorized runtime work. Server-side automatic extension updating is not part of the active main line.
|
||||
Operate the repository's current extension `0.5.170`, Program parser `v1.0.7`, Skills `0.5.126`, business-instruction `0.5.127`, roster normalizer `v1.4.0`, and migrations through `023_leader_summary_webhook_delivery` safely. The machine registry and operator input catalog contain 19 routes; the external Agent remains limited to its original 18 and the two passenger-list routes plus shared-child batch creation are Program-only. Administrators manage accounts, channels, employee grants, parser routing, automation settings, and audit but never enter the task data plane. Team leads/users own normal task operations through immutable assignment; same-account work remains FIFO and single-active while distinct accounts are independent. Team leads alone receive the read-only assignee-based dashboard, whose range-wide candidate pass stays lightweight and reserves full operation/result hydration for search and the current page. Future privacy-bounded organization summaries use one protected external Webhook and a separate encrypted one-attempt outbox, not a leader AgentBus route. Database migration, extension reload, route grants, service rollout, live ERP validation, and any external Webhook canary remain separately authorized runtime work. Server-side automatic extension updating is not part of the active main line.
|
||||
|
||||
## Recently Completed
|
||||
|
||||
@@ -79,6 +80,7 @@ Operate the repository's current extension `0.5.170`, Program parser `v1.0.7`, S
|
||||
- 2026-09-08: Replaced only the leader-summary AgentBus transport with an organization-level external Webhook. AUTH-005 and migration 023 retain future-only encrypted/privacy-bounded projection, mark only strict gateway success as accepted rather than delivered, and terminate rejected or uncertain attempts without automatic retry.
|
||||
- 2026-09-08: Removed the deleted external project-document Skill and task-registry requirement; repository-local Git worktree checks and `.project-docs/` remain the active collaboration and memory boundary.
|
||||
- 2026-09-09: Advanced the operator input catalog and generated DOCX to `0.5.127`, covering all 19 routes with a new copyable Program-only `散拼团多个新增子单` section while leaving Agent Prompt and Skill packages unchanged.
|
||||
- 2026-09-09: Integrated the missed dashboard candidate-query correction so normal date-range reads no longer load complete operation JSON before pagination; unresolved legacy classification receives only its compact required fields, while keyword search and current-page detail keep their existing fidelity.
|
||||
|
||||
## In Progress
|
||||
|
||||
|
||||
@@ -17,3 +17,4 @@ This is integrated history. Feature tasks write only their task-scoped records;
|
||||
| 2026-09-08 | Shared-child batch creation | Added the nineteenth machine route as Program-only, complete pre-write parent enumeration, ordered stop-on-first-non-success execution, parser `v1.0.7`, migration 022, and extension `0.5.170`. | [Feature task](tasks/20260908-shared-child-batch-create-4e7c2a91.md) |
|
||||
| 2026-09-08 | Leader-summary external Webhook | Replaced only the AgentBus summary transport with an organization-level encrypted one-attempt Webhook outbox, migration 023, strict accepted-versus-delivered semantics, and AUTH-005. | [Feature task](tasks/20260908-leader-webhook-api-7c4e9a12.md) |
|
||||
| 2026-09-08 | Repository-local project-document governance | Removed the deleted external Skill/task-registry dependency while preserving Git worktree safety checks and `.project-docs/` as canonical memory. | [Integration task](tasks/20260908-remove-maintain-project-docs-requirement-6d8a31f2.md) |
|
||||
| 2026-09-09 | Leadership dashboard candidate payload correction | Integrated the previously missed lightweight candidate projection: full operation JSON is excluded before pagination, unresolved legacy classification loads only compact fields, and complete payloads remain search/page scoped. | [Integration task](tasks/20260909-integrate-all-current-changes-8e4c2a71.md) |
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Task: Diagnose local dashboard refresh with no data
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20260903-dashboard-refresh-no-data-b4e82f1a
|
||||
- Mode: Feature
|
||||
- Branch: codex/20260903-dashboard-refresh-no-data-b4e82f1a-dashboard-refresh-no-data
|
||||
- Worktree: /Users/inmanx/Documents/lwltAPI-dashboard-refresh-no-data-b4e82f1a
|
||||
- Base commit: 69ea6d25178d75abf8d7fd728bd31c61764caa7d
|
||||
- Owner: codex
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Reproduce the signed-in local `127.0.0.1:8786` leadership-dashboard refresh failure without changing accounts, tasks, database state, ERP state, or the running service.
|
||||
- Trace the frontend request, HTTP response, structured service diagnostics, and dashboard candidate-query projection.
|
||||
- Keep the accepted administrator/team-lead read-only visibility and 30-day default range unchanged while removing the pre-pagination full-operation payload read that exhausts the dashboard statement timeout.
|
||||
- Add focused regression coverage and run repository verification from this isolated worktree; do not restart or deploy the service without separate authorization.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- Preserve the concurrently inspected team-lead dashboard scope and the integrated account-scoped execution/deletion decisions; this task changes dashboard read performance only.
|
||||
- Keep complete instruction/result projection limited to the current page and keep legacy business classification deterministic from the minimum required operation fields.
|
||||
- Do not read `.env`, credentials, cookies, browser storage, plaintext database business inputs, or customer payloads. Runtime observations must remain aggregate- or error-code-only.
|
||||
- Keep the occupied main worktree and its running 8786 service untouched. All repository edits remain rooted in this task worktree and its recorded base; current `origin/main` `f52d9d7` was compared read-only and has the same dashboard candidate query.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Reproduced the default 30-day refresh as HTTP 503 `operations_dashboard_query_timeout`; the matching service diagnostic reports PostgreSQL cancellation code `57014` before the `candidates` stage completes.
|
||||
- Confirmed the same authenticated dashboard succeeds for seven days in about 0.7 seconds and returns 13 aggregate task records, proving the service, database readiness, session, permissions, and underlying data are present.
|
||||
- Root cause: the candidate query selects the complete `t.operation` JSON for every matching task before applying the 20-row page, so the default range exceeds the 5-second SQL statement timeout as payload volume grows.
|
||||
- Evidence record: [Local dashboard candidate-query timeout](../../50-evidence/topics/20260903-dashboard-refresh-no-data-b4e82f1a__dashboard-query-timeout.md).
|
||||
- Confirmed current `origin/main` `f52d9d7` has the same dashboard candidate query, then kept the final feature commit on the task's recorded `69ea6d2` base so project-document drift is measured only against this task's changes.
|
||||
- Removed full `t.operation` from the normal pre-pagination candidate projection. The candidate pass now reads lightweight metadata plus encrypted input only for legacy unclassified rows.
|
||||
- Preserved legacy classification by hydrating only still-unresolved rows with a compact operation object containing the exact `action`, passenger `kind`, and arrangement `mode` fields used by the existing classifier.
|
||||
- Kept full operation and result fields in the current-page detail and keyword-search projections, preserving visible input/output and search behavior.
|
||||
- Added focused regression checks proving the base/candidate projections cannot reintroduce a full operation read and that legacy classification remains targeted.
|
||||
|
||||
## Verification
|
||||
|
||||
- Runtime read-only reproduction: 30-day request returned HTTP 503 after about 8.9 seconds; seven-day request returned HTTP 200 and 13 records.
|
||||
- `node --test LianSyn-platform/app-operations-dashboard.test.mjs` passed: 5/5.
|
||||
- `node --test --import tsx control-plane/test/account-authorization.test.ts` passed: 11/11.
|
||||
- `node --run check:repo` passed: 10/10.
|
||||
- `node --run check` passed.
|
||||
- `node --run test:control-plane` passed: 159/159.
|
||||
- `node --run test:legacy` passed: 268/268.
|
||||
- `node --run build` passed.
|
||||
- Post-change 30-day runtime timing was not claimed because applying the code requires integrating it and separately authorizing a restart of the occupied 8786 service.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Integrate this feature branch, then restart the local 8786 service only with explicit authorization and repeat the authenticated 30-day dashboard request. Compare aggregate totals with the working seven-day baseline and confirm the `candidates`, optional `legacy_classification`, and `page_details` stage timings.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Target canonical documents: `.project-docs/30-worklog/current-state.md` and `.project-docs/50-evidence/evidence-index.md` during Integration Gate review.
|
||||
- Proposal: record that dashboard range queries must keep full operation/result payloads out of the pre-pagination candidate projection; only unresolved legacy classification may load its minimal action/kind/mode shape, while full detail remains page-scoped.
|
||||
- Evidence: the authenticated 30-day/7-day comparison, PostgreSQL `57014` diagnostic, source diff, focused regression, and full repository verification above.
|
||||
- Future impact: prevents normal dashboard growth from turning a valid non-empty result into a misleading timeout/empty board while preserving role scope, filters, business classification, and business-facing detail.
|
||||
- Semantic conflicts: none; the change preserves `AUTH-001`, `AUTH-002`, the 30-day default, and the concurrent team-lead visibility inspection.
|
||||
- Human confirmation required: not for the repository performance correction; still required before service restart or rollout.
|
||||
@@ -0,0 +1,52 @@
|
||||
# Task: Integrate all current changes and push main
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20260909-integrate-all-current-changes-8e4c2a71
|
||||
- Mode: Integration
|
||||
- Branch: main
|
||||
- Worktree: /Users/inmanx/Documents/lwltAPI
|
||||
- Base commit: f0682eea38a87d07b212486a3223c3e2b0a81958
|
||||
- Owner: codex
|
||||
- Status: Ready to Push
|
||||
|
||||
## Scope
|
||||
|
||||
- Audit all linked worktrees and local branches against current `main` and `origin/main`.
|
||||
- Preserve unknown or unrelated dirty work without stashing, resetting, cleaning, moving, deleting, or silently adopting it.
|
||||
- Integrate every distinct, completed, ready-for-integration change into `main`, resolve shared-file conflicts semantically, run repository verification, and push `main` to `origin/main` without force.
|
||||
|
||||
## Constraints
|
||||
|
||||
- Treat historical diagnosis, rollback, superseded, and patch-equivalent branches as audit context rather than automatic merge candidates.
|
||||
- Do not read `.env`, run production migrations, deploy/restart services, reload extensions, access ERP, mutate runtime data, or send external messages.
|
||||
- Ask the user before resolving any conflict that changes product behavior, architecture direction, or an accepted decision without a clear existing source of truth.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Audited 43 linked worktrees and 50 local branches against `main`. Historical diagnosis, rollout, recovery, reverted architecture, superseded integration, patch-equivalent feature branches, and unrelated dirty worktrees were preserved without stashing, resetting, cleaning, moving, deleting, or adopting their changes.
|
||||
- Identified one distinct completed product change that remained absent from `main`: source commit `5cbd8f1` from task `20260903-dashboard-refresh-no-data-b4e82f1a`.
|
||||
- Integrated that source as merge commit `b11dc7b`. The sole conflict was the dashboard actor join: resolution keeps the active immutable-assignee model from AUTH-004 while removing full `operation` JSON from normal range-wide candidates.
|
||||
- Normal candidate reads now omit the full operation payload. Only unresolved legacy rows receive the compact `action`/`kind`/`mode` operation shape required for classification; keyword search and current-page detail retain complete payload fidelity.
|
||||
- Added the source task record and immutable timeout evidence to the mainline, then reconciled current state, data flow, task history, and the evidence index.
|
||||
- No other ready, distinct product change remained after the branch/worktree audit.
|
||||
|
||||
## Verification
|
||||
|
||||
- Refreshed `origin` successfully before integration and confirmed local `main` and `origin/main` were both `f0682eea38a87d07b212486a3223c3e2b0a81958`.
|
||||
- `git diff --check` and the active-tree merge-marker scan passed.
|
||||
- Focused leadership-dashboard regression passed, 5/5.
|
||||
- `node --run check:repo` passed, 10/10.
|
||||
- `node --run check` passed.
|
||||
- `node --run test:control-plane` passed, 183/183.
|
||||
- `node --run test:legacy` passed, 278/278.
|
||||
- `node --run build` passed.
|
||||
- Final remote synchronization and post-push hash verification are pending.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- After a separately authorized service rollout/restart, repeat the authenticated 30-day leadership-dashboard request and compare it with the previously successful seven-day baseline. This repository integration does not restart the service or access live task data.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- None; accepted source facts are promoted directly by this Integration task.
|
||||
@@ -20,6 +20,7 @@ Use this index for searchable, traceable evidence records.
|
||||
| 2026-09-02 | Leadership-dashboard filtering and summary interaction | Repository and focused regression verified; merged runtime not restarted | [Integration record](../30-worklog/tasks/20260902-integrate-all-push-c93a7f21.md) | Single-connection bounded reads, SQL prefiltering, selective hydration, 20-row paging, cancellation/timeout feedback, and display-only metric cards with explicit filters passed combined regression. |
|
||||
| 2026-09-02 | Native ERP product search for ordering forms | Root cause and live search-only behavior verified; repository/release verified; extension not reloaded | [Integration task](../30-worklog/tasks/20260902-integrate-product-search-3b7f6a20.md) | Both `plan_add.asp` and `orders_adds.asp` returned exactly one target product for the full keyword with radios left unchecked and no save; extension `0.5.165` now uses native non-empty search before its bounded empty-query fallback while retaining deterministic unique matching. |
|
||||
| 2026-09-03 | Account-scoped ERP queues, assignee-only executable routing, and force delete | Repository and full regression verified; runtime not deployed or mutated | [Integration task](../30-worklog/tasks/20260903-finalize-account-routing-7c4e2a91.md) | Source task `20260902-per-account-queue-hard-delete-a6d9f2c1` replaced global head-of-line blocking with per-assignee FIFO/advisory locks, isolated SSE/plugin-result/browser-command routing from administrator read visibility, and separated reversible archive from lifecycle-independent physical deletion. |
|
||||
| 2026-09-03 | Leadership dashboard candidate-query timeout | Root cause and repository correction verified; post-change runtime not restarted | [Evidence record](topics/20260903-dashboard-refresh-no-data-b4e82f1a__dashboard-query-timeout.md) | A healthy authenticated 30-day read timed out in PostgreSQL candidate selection while seven days succeeded; the integrated correction removes full operation JSON from normal pre-pagination candidates and uses a compact legacy-classification projection. |
|
||||
| 2026-09-03 | Adaptive ERP readiness and central extension host updates | Mixed disposition: plugin/release retained at rollback; server architecture reverted before production rollout | [Original integration task](../30-worklog/tasks/20260903-finalize-extension-update-a6c4e192.md) | Exact extension `0.5.167` and adaptive readiness were retained when migration 019 and central private-OSS/ECS orchestration moved to backup commit `b2e33e2`; the active plugin later advanced independently. |
|
||||
| 2026-09-03 | Extension-update iteration scoped rollback | Backup ref verified; server/migration rollback and regression rechecked | [Rollback task](../30-worklog/tasks/20260903-backup-revert-extension-update-c71a4e92.md) | The full stack was backed up before normal non-force commits removed server-side automatic updating and migration 019; the rollback retained extension `0.5.167` and migration 018 without rewriting Git history. |
|
||||
| 2026-09-07 | Team-lead task-summary projection and proactive AgentBus delivery | Repository and disposable-PostgreSQL verified; not deployed or externally sent | [Feature task](../30-worklog/tasks/20260907-implement-leader-agentbus-copy-b7e31a94.md) | Migration 020, future-only encrypted projection, privacy allowlist, stale-uncertainty supersession, employee-first outbound priority, stable proactive frame IDs, no `reply_to`, echo rejection, and administrator controls passed full regression; exact AgentBus/WeChat routing still needs an authorized canary. |
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Evidence: Local dashboard candidate-query timeout
|
||||
|
||||
## Scope
|
||||
|
||||
- Local signed-in `http://127.0.0.1:8786/operations-dashboard` reads only.
|
||||
- Current 8786 process, health endpoints, HTTP response metadata, and privacy-safe structured diagnostics.
|
||||
- Active dashboard query source at task base `69ea6d2`; read-only comparison confirmed current `origin/main` `f52d9d7` is unchanged in this query area.
|
||||
|
||||
## Findings
|
||||
|
||||
- `/health/live` and `/health/ready` passed; PostgreSQL and required migration `018_agentbus_account_workers` were ready.
|
||||
- The default 30-day dashboard GET returned HTTP 503 after about 8.9 seconds with `operations_dashboard_query_timeout`.
|
||||
- The matching service diagnostic reported PostgreSQL cancellation code `57014`; no `operations_dashboard.query.completed` event was emitted for the `candidates` stage.
|
||||
- The same authenticated page completed a seven-day GET in about 0.7 seconds. The candidate, actor, and page-detail stages completed, and the aggregate response contained 13 tasks.
|
||||
- Source inspection showed that the candidate projection selected complete `t.operation` JSON for every matching row before slicing the 20-row page. Full detail was therefore read for the entire range rather than only the current page.
|
||||
|
||||
## Conclusion
|
||||
|
||||
The visible empty board was a timeout presentation, not an empty database or authorization failure. Candidate payload amplification exhausted the five-second SQL statement timeout as the date range grew.
|
||||
|
||||
## Evidence Safety
|
||||
|
||||
- No `.env`, credentials, cookies, browser storage, plaintext instructions, customer data, task IDs, or operation payloads were read or recorded.
|
||||
- Runtime evidence is limited to health state, HTTP/error codes, durations, query-stage names, and aggregate counts.
|
||||
|
||||
## Confidence
|
||||
|
||||
- High for the reproduced failure and failing query stage.
|
||||
- Repository verification can prove the candidate projection no longer selects full operations, but post-change 30-day runtime timing requires a separately authorized service rollout/restart.
|
||||
|
||||
## Last Verified
|
||||
|
||||
2026-09-03
|
||||
|
||||
## Stale Trigger
|
||||
|
||||
Re-run the authenticated 30-day request after this feature is integrated and the local service is restarted from that revision, or whenever the dashboard query plan/projection changes again.
|
||||
@@ -90,6 +90,38 @@ test('table filters use a bounded single-connection read and default to 20 rows'
|
||||
assert.match(dashboardQuery, /SET LOCAL statement_timeout/);
|
||||
assert.match(dashboardQuery, /SELECT \$\{search \? taskSearchSelect : taskCandidateSelect\}/);
|
||||
assert.match(dashboardQuery, /CASE WHEN t\.business_route_id IS NULL THEN t\.original_text_ciphertext ELSE NULL END/);
|
||||
const baseSelect = dashboardQuery.slice(
|
||||
dashboardQuery.indexOf('const taskBaseSelect'),
|
||||
dashboardQuery.indexOf('const taskLegacyOperationSelect')
|
||||
);
|
||||
const legacyOperationSelect = dashboardQuery.slice(
|
||||
dashboardQuery.indexOf('const taskLegacyOperationSelect'),
|
||||
dashboardQuery.indexOf('const taskDetailSelect')
|
||||
);
|
||||
const detailSelect = dashboardQuery.slice(
|
||||
dashboardQuery.indexOf('const taskDetailSelect'),
|
||||
dashboardQuery.indexOf('const taskSearchSelect')
|
||||
);
|
||||
const searchSelect = dashboardQuery.slice(
|
||||
dashboardQuery.indexOf('const taskSearchSelect'),
|
||||
dashboardQuery.indexOf('const taskCandidateSelect')
|
||||
);
|
||||
const candidateSelect = dashboardQuery.slice(
|
||||
dashboardQuery.indexOf('const taskCandidateSelect'),
|
||||
dashboardQuery.indexOf('try {', dashboardQuery.indexOf('const taskCandidateSelect'))
|
||||
);
|
||||
assert.doesNotMatch(baseSelect, /t\.operation/);
|
||||
assert.match(legacyOperationSelect, /'action', t\.operation -> 'action'/);
|
||||
assert.match(legacyOperationSelect, /'kind', t\.operation #> '\{data,existing_refs,kind\}'/);
|
||||
assert.match(legacyOperationSelect, /'mode', t\.operation #> '\{data,arrangement,mode\}'/);
|
||||
assert.match(detailSelect, /t\.operation, t\.original_text_ciphertext/);
|
||||
assert.match(searchSelect, /t\.operation, t\.original_text_ciphertext/);
|
||||
assert.doesNotMatch(candidateSelect, /t\.operation/);
|
||||
assert.doesNotMatch(candidateSelect, /taskLegacyOperationSelect/);
|
||||
assert.match(dashboardQuery, /filter\(\(\{ projection \}\) => !projection\.task\.business_route_id\)/);
|
||||
assert.match(dashboardQuery, /'legacy_classification'/);
|
||||
assert.match(dashboardQuery, /SELECT t\.id, \$\{taskLegacyOperationSelect\}/);
|
||||
assert.match(dashboardQuery, /legacyOperationById/);
|
||||
assert.match(dashboardQuery, /'search_messages'/);
|
||||
assert.match(dashboardQuery, /filter\(\(\{ directSearchMatch \}\) => !directSearchMatch\)/);
|
||||
assert.doesNotMatch(dashboardQuery, /const pool = getPool\(this\.config\)/);
|
||||
|
||||
@@ -4786,12 +4786,25 @@ export class TaskService {
|
||||
{ key: 'unclassified', label: '其他任务' }
|
||||
];
|
||||
const taskBaseSelect = `t.id, t.task_id, t.status, t.business_route_id, t.archived_at,
|
||||
t.created_at, t.updated_at, t.operation,
|
||||
t.created_at, t.updated_at,
|
||||
assignee.id AS actor_id, assignee.username AS actor_username,
|
||||
assignee.role AS actor_role, assignee.is_active AS actor_is_active,
|
||||
to_char(timezone('Asia/Shanghai', t.created_at), 'YYYY-MM-DD') AS business_day`;
|
||||
const taskLegacyOperationSelect = `jsonb_build_object(
|
||||
'action', t.operation -> 'action',
|
||||
'data', jsonb_build_object(
|
||||
'existing_refs', jsonb_build_object(
|
||||
'kind', t.operation #> '{data,existing_refs,kind}'
|
||||
),
|
||||
'target_kind', t.operation #> '{data,target_kind}',
|
||||
'arrangement', jsonb_build_object(
|
||||
'mode', t.operation #> '{data,arrangement,mode}'
|
||||
),
|
||||
'mode', t.operation #> '{data,mode}'
|
||||
)
|
||||
) AS operation`;
|
||||
const taskDetailSelect = `${taskBaseSelect},
|
||||
t.original_text_ciphertext, t.message, t.success_receipt, t.success_receipt_at,
|
||||
t.operation, t.original_text_ciphertext, t.message, t.success_receipt, t.success_receipt_at,
|
||||
t.error_summary, t.error_summary_at, t.execution_result, t.parse_response,
|
||||
(SELECT COUNT(*)::int
|
||||
FROM agent_session_messages input_message
|
||||
@@ -4800,7 +4813,7 @@ export class TaskService {
|
||||
AND input_message.role = 'user'
|
||||
AND input_message.input_source IS DISTINCT FROM 'reparse') AS input_turn_count`;
|
||||
const taskSearchSelect = `${taskBaseSelect},
|
||||
t.original_text_ciphertext, t.message, t.success_receipt, t.success_receipt_at,
|
||||
t.operation, t.original_text_ciphertext, t.message, t.success_receipt, t.success_receipt_at,
|
||||
t.error_summary, t.error_summary_at,
|
||||
CASE
|
||||
WHEN t.status = 'completed'
|
||||
@@ -4878,8 +4891,40 @@ export class TaskService {
|
||||
[context.organizationId]
|
||||
);
|
||||
const candidateRows = candidateResult.rows as Record<string, unknown>[];
|
||||
const projectedCandidates = candidateRows.flatMap((row) => {
|
||||
const projection = operationsDashboardTaskProjection(this.config, row);
|
||||
let projectedRows = candidateRows.map((row) => ({
|
||||
row,
|
||||
projection: operationsDashboardTaskProjection(this.config, row)
|
||||
}));
|
||||
if (!search) {
|
||||
const unresolvedLegacyIds = projectedRows
|
||||
.filter(({ projection }) => !projection.task.business_route_id)
|
||||
.map(({ row }) => text(row.id))
|
||||
.filter(Boolean);
|
||||
if (unresolvedLegacyIds.length) {
|
||||
const legacyOperationResult = await dashboardQuery(
|
||||
'legacy_classification',
|
||||
`SELECT t.id, ${taskLegacyOperationSelect}
|
||||
FROM tasks t
|
||||
WHERE t.organization_id = $1
|
||||
AND t.id = ANY($2::uuid[])`,
|
||||
[context.organizationId, unresolvedLegacyIds]
|
||||
);
|
||||
const legacyOperationById = new Map(
|
||||
(legacyOperationResult.rows as Record<string, unknown>[])
|
||||
.map((row) => [text(row.id), row.operation])
|
||||
);
|
||||
projectedRows = projectedRows.map(({ row, projection }) => {
|
||||
const operation = legacyOperationById.get(text(row.id));
|
||||
if (operation === undefined) return { row, projection };
|
||||
const enrichedRow = { ...row, operation };
|
||||
return {
|
||||
row: enrichedRow,
|
||||
projection: operationsDashboardTaskProjection(this.config, enrichedRow)
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
const projectedCandidates = projectedRows.flatMap(({ row, projection }) => {
|
||||
const routeMatches = !businessRouteId
|
||||
|| (businessRouteId === 'unclassified'
|
||||
? !projection.task.business_route_id
|
||||
|
||||
Reference in New Issue
Block a user