Commit Graph
516 Commits
Author SHA1 Message Date
wecom-fullstack 790be2d6b1 fix(strategy-map): 三处缺陷——D1 完备度/摘要路由先注册(修 /completeness/objectives 422)、D2 连线增删显式 flag_modified(修 DELETE 200 不落库)、D3 拖拽命中改 rect 判定(修窄屏知识面板遮挡导致拖拽失效)
ci/woodpecker/push/main Pipeline was successful
2026-10-20 20:35:28 +08:00
wecom-fullstack 86e24c6310 fix(strategy-map): 移除悬空 import kpi_target_reader(该模块全仓不存在,致 app.main 导入失败/部署自检中止)→ 目标值取 target_monthly or target_value
ci/woodpecker/push/main Pipeline was successful
2026-10-20 13:01:02 +08:00
wecom-fullstack ecbe55c48a merge: origin/main 合入战略地图改造分支(解 MapCanvas 模板冲突:摘要条+编辑条+口径条并存)
ci/woodpecker/push/main Pipeline was successful
2026-10-20 11:34:29 +08:00
wecom-fullstack c030fb7d18 fix(strategy-map): 口径违禁串代码级清零(9,492.6/83.9%/19/19/el-dialog 仅存于注释)+ components.d.ts 补 MapDimensionFilter 2026-10-20 11:33:58 +08:00
wecom-fullstack a8c9b38fff feat(caliber-label): 科目口径·缺票 常驻标识 + 测算/待票 数值标识(展示层 P2)
ci/woodpecker/push/main Pipeline was canceled
- 新增 constants/caliber.ts(文案单一真源)+ components/CaliberBadge.vue(常驻,非 hover)
- 经营看板/Dashboard:页头常驻「科目口径 · 缺票」(tooltip 含 四件套 0/4、invoice_check 0 行)+ 毛利率与 A 口径 KPI 卡「测算/待票」
- 战略地图看板/StrategyMap:meta-bar 常驻标识位 + 节点级测算标识(与 v4 §2/§4 共用同一组件)
- 战略地图画布/MapCanvas、KPI 列表 KPIListView 同步复用同一组件
- 只做展示层:不改库、不重算历史值、不静默按实账回填
2026-10-20 02:11:00 +08:00
Hermes CI Fix 53cad7eaa9 merge: origin/main (A3 三维切片) 合入战略地图改造分支 2026-10-19 14:32:33 +08:00
Hermes CI Fix a8141e8879 wip(strategy-map): v4 口径落码(分线营收/新式毛利率/管理指标/C1 hold/57 归档) 2026-10-19 14:32:08 +08:00
wecom-fullstackandHermes CI Fix d85dd2a155 feat(strategy-map): A3 三维切片(时间/门店/产品)——切片重算 + 显式空态 + entity 隔离
ci/woodpecker/push/main Pipeline was successful
- 新增 /api/cma/maps/{id}/dimension-options 与 /{id}/slice(只读)
- 时间:kpi_values.period 月/季/年;flow 求和、ratio 均值、balance/status 取最新
- 产品:product_sales + 逐月源一致性闸门(偏差>1% 不切片)
- 门店:库内无门店级事实 ⇒ available=false + reason,绝不回退总额
- 前端 MapDimensionFilter 挂到 MapCanvas,切换即 emit 切片,清除恢复 /review
2026-10-19 13:32:49 +08:00
Hermes CI Fix 4d20c27de4 wip(strategy-map): V1+V3 合版 + v2/v3 口径(完备度/C1 hold/57 归档组) 2026-10-19 10:33:40 +08:00
project-bot c92dbab96a feat(kb): KnowledgePanel 接线 6 页 + /maps/canvas 错配消除
ci/woodpecker/push/main Pipeline was successful
- /budget /kpis /deviations /predict /maps-review /alerts 六页按 related_page 挂载 KnowledgePanel
- /maps/canvas 页 prop 由 /maps 更正为 /maps/canvas(与表值一致,消除恒取空)
- 匹配口径走 backend/app/utils/route_key.py(origin/main 已有,KBFF-v11c 精确等值)
- 验证:本地产物 CDP 冒烟 18/18(六页 dom=api=1;/maps 命中 0 负对照)
2026-10-19 10:23:12 +08:00
wecom-fullstack 0fc2c6109e style(page-title): 补漏——战略地图看板页标题弱化 + KPIListView 标题 emoji 清零
ci/woodpecker/push/main Pipeline was successful
- StrategyMap.vue: 页内 h2 19px/600/深色(与路由标题「战略地图看板」基本同名)降为
  div.page-subtitle 14px/500/#64748B(保留地图名+版本+状态等增量信息,不再充当 H1)
- KPIListView.vue: 组件 h3 图标默认值 '📊' 置空(v-if 渲染),分类标题与明细卡头
  '📋' 改为 Lucide 内联 SVG(clipboard-list,18/16px,#64748B)
- 仅模板与样式:不动 MainLayout、不改接口/数据/路由 key、不碰 MapCanvas.vue
2026-10-19 04:34:35 +08:00
wecom-fullstack bf641d8d31 refactor(menu): 侧边栏按决策域重构(L1 九域 + L2 决策场景)+ PDCA 回退开关
ci/woodpecker/push/main Pipeline was successful
- 新增 frontend/src/config/decisionDomains.ts:9 个决策域(100 战略…900 系统)
  与 22 个 L2 决策场景,只写 path 关系;文案/图标/roles 仍取 permission.ts MENU_ITEMS
- MainLayout.vue:决策域菜单为默认(el-sub-menu 域 → el-menu-item-group 场景 → 页面),
  「我的工作台」常驻置顶,系统域默认折叠;未登记菜单项兜底进 900「未归类」(不丢项)
- 回退开关:localStorage.cma_menu_mode='pdca' 或 URL ?menu=pdca,右上角下拉可切换
- 路由 path、页面、API、DB、zone A/B 权限判定一律未改
- components.d.ts 由 unplugin-vue-components 自动补 ElMenuItemGroup 声明
2026-10-18 21:45:32 +08:00
Hermes CI Fix 7f36608f60 chore(frontend): 重新生成 components.d.ts(budget 面板组件 + ForecastTag 自动注册)
ci/woodpecker/push/main Pipeline failed
2026-10-18 20:37:51 +08:00
Hermes CI Fix 5bda882aa9 Merge remote-tracking branch 'origin/main' into integration/merge-wt-20261018 2026-10-18 20:32:32 +08:00
wecom-fullstack f51fc72ac7 style(page-title): B 全站规范——页面内同名标题清零 + 增量副标题弱化 + 标题 emoji 换 Lucide
ci/woodpecker/push/main Pipeline failed
- 39+ 页删除与布局标题同名/基本同名的页面内 h1-h4(同屏三标题→两处)
- 增量副标题弱化为 14px #64748B 小字:收付款计划/战略回顾/地图版本/会计科目打标
- 标题 emoji 清零,保留标题处改 Lucide 内联 SVG(bar-chart-3/video/scale/clipboard-list/alert-circle/map/history)
- KPIListView 增加 hideTitle(仅展示),客户/学习看板隐藏组件内重复页头
- 不动 MainLayout、不改接口/业务逻辑、不碰 MapCanvas.vue
2026-10-18 19:33:11 +08:00
Hermes CI Fix a67f4b688f feat(receivables): customer-level rows only + register hanke_ar as balance snapshot batch
ASK-20261001-33: api_receivables counts only rows with a non-blank counterparty (monthly aggregate rows stay in table but out of the collection page cards/aging/detail/owners); BALANCE_SNAPSHOT_SOURCES gains hanke_ar (default skip, no per-customer overdue alerts). New pytest file covers aggregate-row exclusion, e2 baseline digitwise, snapshot registration.
(cherry picked from commit 475f78bc8c5f67f2716c721172a88ff89ec58227)
2026-10-18 16:42:06 +08:00
Hermes CI Fix fa1267c323 feat(budget): effective-version caliber + process-order tabs + 4 missing rings
Task: CMA-20261003 (budget module governance). Local commit only; push is
gated on release approval (see report).

Backend
- app/utils/budget_status.py (new): single source for the effective-version
  caliber. EFFECTIVE_STATUSES = approved + active; effective_plan_clause()
  enforces entity isolation; pick_effective() priority active > approved >
  updated_at desc. Fixes: approved budgets disappeared from the execution
  surface because the three queries only read status='active'.
- budget.py: /comparison, /comparison/kpi/{id}, /deviation-check now read the
  effective surface; versions list gains is_effective / can_release fields;
  submit/approve are fail-closed (draft|active -> submitted -> approved).
- deviation_engine.get_budget_for_kpi: effective surface + deterministic pick.
- 4 missing rings, zero DDL, appended to the same router:
  POST /versions/release (approved -> active, idempotent by operation_logs),
  POST /adjustments (derive a new draft version, base rows untouched),
  GET /control/status (effective budget vs actual -> ok/warn/over),
  GET /assessment (achieve rate + A/B/C/D grade).
  Audit rows written through app.utils.oplog.log_op with entity_id.

Frontend
- BudgetManagement.vue: top-level tabs reordered to the process order
  (strategy, method, driver, input, decompose, versions, release, execution,
  deviation, adjust, assess, rolling). Pane name values unchanged, so old
  bookmarks keep working; routes unchanged.
- Cash classify rules / unclassified queue moved to /cash-plan
  (components/CashClassifyPanel.vue); budget actual-value collection moved to
  /data-manage (components/BudgetCollectPanel.vue). Mount points only: no
  change to cash_plans data, classify logic, collection logic or kpi_values.
- api/index.ts: 4 ring endpoints exposed.

Docs / tests
- docs/budget-module-governance-design.md: phase-0 design doc (status machine,
  tab order, domain boundaries, 4-ring design, cleanup write pack scope).
- tests/test_budget_status_machine.py (new): effective surface, version
  guards, release idempotency, adjustment, control and assessment.
- tests/test_budget.py: existing cases adapted to the fail-closed contract.

(cherry picked from commit 4267fc4d25ee45c5675a541af9777be96fe9f9c2)
2026-10-18 16:32:55 +08:00
Hermes CI Fix 75a48f55d2 feat(strategy-map): live board reading map_objectives + kpi_targets (read-only)
Task: finance-20261011-strategy-map-frontend-fullstack (P2, read-only integration)

- backend/app/utils/strategy_board.py: single source of truth for the level
  caliber (layer colors, inverse-kpi explicit whitelist, status class by
  unit, zero guard, period ranking, latest-actual picking). Pure functions.
- backend/app/api/maps.py: GET /api/cma/maps/{map_id}/strategy-board
  - nodes straight from map_objectives (sorted by sort_order, id)
  - node<->kpi binding with 4-step fallback, binding_source echoed back
  - targets from kpi_targets (target_type compatible: yearly + annual),
    deduped per (kpi_id, period) with yearly preferred
  - actuals from kpi_values actual-only scope, latest period
  - causality edges from kpi_causality, out-of-map endpoints dropped+counted
  - entity_id taken from the token only (no cross-tenant reads)
  - zero writes; nothing is persisted by this endpoint
- frontend/src/views/StrategyMap.vue: /strategy-map live board (4 swim lanes
  bottom-up, node cards, 20 causality arrows in SVG, period switch, A3 print).
  No emoji, null guards everywhere (no toFixed on null).
- api/index.ts + router/index.ts + permission.ts: route + menu registration
  (/strategy-map, zone A read-only, roles ceo/finance/business/it).
- backend/tests/test_strategy_board_20261011.py: 33 cases (spec section 4 /
  4.1 / 4.2 / 4.3 + section 7 fixtures + threshold boundaries + period rank).
- backend/tests/test_map_objectives_kpis_form_20261011.py: 14 cases for the
  four kpis column shapes (list, json string, object list, NULL/[]/weird).

Not included: push + backend restart (production write, separate gate).

(cherry picked from commit c675bde6b4beaf1d8a9d02a80f5434203a53f348)
2026-10-18 16:31:52 +08:00
Hermes CI Fix 2cff58ca6a feat(docs-center): report reading section (type=report) on /api/cma/docs
Increment #2 over PoC ede0524 (task yanxue-20260924-cma-report-source).

- backend derives reports from existing drop points (wisdom/_reports + every profile pending-tasks/_reports), read live per request, no cache, no rebuild

- gate = front-matter plus non-empty conclusion; missing either means silently out of the list (receipts/audits never enter); title/date/domain/sources missing are marked incomplete instead of rejected

- entity + role partitioning (ceo/it cross-entity; others own entity plus group/generic); kpi_refs resolve to a one-hop metric link

- new GET /api/cma/docs/report/{rid} detail endpoint; knowledge branch unchanged (type defaults to knowledge)

- frontend: CMAKnowledge adds a report reading pane (filters + detail dialog), reuses the existing markdown renderer, no new deps

(cherry picked from commit 7c6e0857e68133f5ba2a539fd3569aeb82547911)
2026-10-18 16:31:52 +08:00
Hermes CI Fix 57f9dbae15 fix(action-plans): 「已逾期」改日期粒度(口径 B,当天到期不算逾期)
- _apply_overdue():`ActionPlan.due_date < datetime.now()` → `... < 今天0点`
  (唯一实现,plan_stats 与 list_plans 共用,故一处改即两端点同改)
- 口径同步注释(口径 A→B 的沿革与分界式);行为改动仅此一处
- 测试夹具改到日粒度(整天偏移),新增「今日到期不算逾期」鉴别行与
  `test_overdue_caliber_is_date_granularity` 口径锁定用例(防回退 A)
- 依据:任总 2026-09-22 10:10 拍板口径 B;前端角标 ActionPlanLibrary.vue::isOverdue
  与 cash.py::_plan_dict 本就同粒度,本单未动
- 只改码:未 push / 未部署 / 未重启(发布须放行)

(cherry picked from commit 2da5b6da018013f860430913b5b0e0436f966685)
2026-10-18 16:31:52 +08:00
wecom-project 5fa83e2532 fix(knowledge): related_page 过滤精确化(子串包含 -> 归一候选键等值)
KBFF-v11c(派单 KBFF-v11c-relatedpage-exact-match-filter · A 侧 wecom-yanxue · 执行人 wecom-project)
本提交=代码面切片:未 push、未部署;生产部署另走发布单 + approval-gate(回滚 = git revert <本 sha>)。

- backend/app/api/knowledge_articles.py:related_page 过滤由 LIKE '%<v>%'(子串包含,短键/前缀超集命中)
  收敛为「归一候选键 IN ∪ 模板子路由 <键>/:<占位符>」;不可归一入参 -> 空集(不退化为全量)
- backend/app/utils/route_key.py(新增):匹配口径唯一实现处(归一化 / 候选键派生 / 模板模式)
- backend/tests/test_kbff_v11c_related_page_exact_match_20261012.py(新增):42 用例
  —— 生产 seed 7 值逐值回归(各中 1 行)、短键 /maps->0 行 /kpi->0 行、带参路由与尾斜杠/query/大小写兼容、
  改造前 contains 语义负对照、账套分区与 category 组合语义保持

(cherry picked from commit 2a5cb182c237ae724d4b506b68eb48810ba27b16)
2026-10-18 16:31:52 +08:00
fullstackandHermes CI Fix 60b6ef3bfe fix(alert-rules): dynamic-thresholds 迭代 Column 当行取值致 500
GET /api/cma/alert-rules/dynamic-thresholds 在 {c.name: getattr(c, c.name) for c in
DynamicThresholdCache.__table__.columns} 里把 Column 对象当 ORM 行取属性,触发
AttributeError: 'Comparator' object has no attribute 'id'。改为列名取自表元数据、
值取自 query 结果行;entity_id 过滤与 limit 50/kpi_id 分支不变。

(cherry picked from commit 4130726be411a74a3318d9dc6bbc518a6c60d0ff)
2026-10-18 16:31:52 +08:00
wecom-fullstackandHermes CI Fix a9dcbf22bc chore(security): 摘除 knowledge_service 硬编码默认 DeepSeek Key(缺 env 抛明确错误/503)
- knowledge_service: 移除 os.getenv 默认值占位,改 _require_deepseek_key() 必填,缺 env 抛 DeepSeekKeyMissing
- knowledge API: generate/{daily,weekly,monthly} 缺 Key 返回 503(可观测,不再静默走模板兜底)
- finance_bot / verify_zxt_vouchers_json / bot_bridge_push: 凭据改 env 优先(CMA_BOT_KEY_* / CMA_BOT_API_KEYS / CMA_BRIDGE_TOKEN),历史共享键仅作兼容期兜底并告警
- tests: 新增 5 例回归(缺 Key 服务层抛错、API 503;有 Key 正常 200)

(cherry picked from commit 859bd8276d7c5aad4bf10ee3399b6cccc188f064)
2026-10-18 16:31:52 +08:00
wecom-fullstack 885cfddbff feat(warning-p0a): 资金缺口阈值外置 + 复算对拍 + 讲人话(数字守恒) + 数据就绪核验
ci/woodpecker/push/main Pipeline failed
P0-A(任务 fullstack-20261017-warning-capability-build-p0):
- cash_thresholds.py:阈值迁 per-entity(复用 alert_rules.rule_type=cash_gap_threshold,
  默认 20/10 万不动;无配置/非法/异常一律回落默认,fail-safe 不改预警行为)
- cash_forecast_engine.py:阈值改从配置读取,响应新增 threshold_source 明写来源
- verify_cash_gap_replay.py:同输入双跑逐字段 diff=0 + 手算 3/3 + 端点逐字段对拍(--live)
- cash_gap_narrative.py:复用 ai_brief.call_deepseek,只写原因/建议;
  断言生成文本数字集合 ⊆ 规则层数字集合,违例即不带文案上线
- audit_warning_data_readiness.py:G0 只读核验(cma_reader SELECT only),
  行数/期间/枚举 + 数据质量缺口(期初全 0、负期末、单批次、无员工维度表)

未 push(push 即部署,须项目侧书面放行);未改生产库/未动 cron。
2026-10-17 23:33:51 +08:00
Hermes FullstackandHermes CI Fix a52faa90a6 fix(dashboard): bep-card terms 分支补字段别名映射(修 289cc8f 引入的 e2 500)
ci/woodpecker/push/main Pipeline was successful
289cc8f(§4-1 博海固定成本仅借方)在 dashboard._bep_sum_field 新增 terms 分支,
把 bep_caliber 的 terms 记法字段名(debit/credit)原样传给 getattr(VoucherDetail, field)
⇒ AttributeError: type object 'VoucherDetail' has no attribute 'debit'
⇒ GET /api/cma/dashboard/bep-card(entity=2 博海)稳定 500(entity=1 走 filters 分支不受影响)。

修复:terms 分支内做字段名映射 debit→debit_amount / credit→credit_amount(与
profit_lines.FIELD_MAP、kpi_bep_deriver._TERM_FIELD 同式),再递归聚合。

回归测试:tests/test_profit_summary_real_caliber_20261014.py 新增
test_dashboard_card_e2_terms_mode_field_alias(修复前 RED:复现同一 AttributeError;
修复后 GREEN:e2 固定成本 98,000 元 / 卡面 9.80 万)。
2026-10-16 18:28:50 +08:00
wecom-fullstack 68ca27109e feat(report): 管理利润表「变动成本」行加负值标注(脚注+tooltip,纯展示)
ci/woodpecker/push/main Pipeline was successful
依据 e1 变动成本负值口径核查(口径无误,设计使然):变动成本含贷方冲减项(厂补),
个别期间(2026-08 / 2025-07)可为负。本单仅在报表层加说明,防读者误读为取数/口径错误。

- 项目列「变动成本」行加 InfoFilled 悬停 tooltip(按 line_key === 'variable_cost' 精确命中)
- 表格下方加脚注一行
- 未改取数逻辑、未改口径、未改任何数值(diff:1 file, 11 insertions(+), 0 deletions(-))
2026-10-16 18:13:50 +08:00
Hermes CI Fix 289cc8f2cc fix(profit-caliber): 博海口径 §4-1/§4-2/§4-5 落地 —— 固定成本仅借方 + 6403 进变动 + 财务收益单列 + 批次备注
ci/woodpecker/push/main Pipeline was successful
ASK-20261014-04(任总 2026-10-14 11:20「放行4」)批后口径:
- §4-1 博海固定成本弃净额:6601/6602/6603 仅借方(133.98 万,2026-01..09);2026-03 单月由 -9.02 万转正;
  6603 贷方(现金折扣收益 64.40 万)改 finance_income_terms 单列备查,不进固定成本/末行/勾稽。
- §4-2 博海变动成本追加 6403 营业税金及附加(530.17 万)。
- §4-3/§4-4 维持现行(酣客收入/边际贡献基数不动)。
- §4-5 管理利润表页加「数据批次/导入时刻」纯展示备注(import_logs)。
- 口径唯一源仍为 bep_caliber.ENTITY_CALIBERS;报表/卡面/派生器一律经 fixed_cost_spec() 解析(读口写口一致)。
2026-10-16 12:32:52 +08:00
wecom-fullstackandHermes CI Fix ff2d92ba54 ci(woodpecker): 部署通道收口为单链 —— CI 只做门禁,部署恒走宿主 Gitea hook
ci/woodpecker/push/main Pipeline was successful
② 现状:push origin main 同时触发两条写生产链 ——
   (a) 宿主 Gitea post-receive hook → /usr/local/sbin/gitea-cma-deploy-hook.sh → deploy.sh(铺站 + 重启 + 冒烟)
   (b) Woodpecker pipeline 的 frontend-deploy(rsync --delete dist → /var/www/cma + nginx reload)
       与 backend-deploy(在开发区 git pull + systemctl restart cma-backend)
   两条链并发 ⇒ 两套在途部署判定、重复劳动与证据歧义(2026-10-13 事故即此形态)。
本提交复用 ci/wp-v3-fix-20260916 已写就的 .woodpecker/main.yml(wecom-project 2026-09-16 8ddcbe1):
   删除 variables(ssh_setup) 与 frontend-deploy/backend-deploy 两步,只留门禁
   (frontend-install/typecheck/build + backend-test),并补国内镜像与 pytest 安装。
零生产写:候选仅落本 worktree 分支,未 push。
2026-10-16 03:05:57 +08:00
wecom-ops d2cb812bfa chore(deploy): 触发部署链复跑(真修复 · 无内容变更)
ci/woodpecker/push/main Pipeline failed
2026-10-16 00:19:31 +08:00
wecom-fullstackandHermes CI Fix 32f368a846 fix(infra): pnpm 工具链去脆弱化 —— frontend/package.json 落 packageManager pin + deploy.sh pnpm 版本断言(fail-closed)
ci/woodpecker/push/main Pipeline failed
① frontend/package.json 补 "packageManager": "pnpm@10.33.2+sha512.a90faf6f…":
   corepack 在项目未声明该字段时按全局 lastKnownGood.json 解析版本,而该文件会被任何跑过
   corepack 的项目改写(2026-10-13 → 12.11.2 ⇒ MODULE_NOT_FOUND;2026-10-14 → 9.15.9 ⇒
   packages field missing)。pin 落库后 corepack 只认 pin,宿主机状态漂移不再影响部署树。
   选 10.33.2 的依据:pnpm-workspace.yaml 的 allowBuilds 仅 pnpm 10 识别;部署树 node_modules
   .modules.yaml packageManager=pnpm@10.33.2(store/v11/v10);lockfileVersion 9.0;2026-10-13
   22:53 该版本下部署成功。
② deploy.sh 新增 assert_pnpm_version()(fail-closed,两处调用:1.2a 首次 pnpm 调用前、[2] 构建前):
   期望版本只取自 package.json 的 packageManager(单一源),与 pnpm -v 实读逐字比对,缺失/不一致
   即中止;两次调用都先于 [3] 铺站与 [5] 重启 ⇒ 任何生产写之前失败关闭。

零生产写:候选仅落本 worktree 分支,未 push、未动 /srv/hermes/shared/cma-deploy 与 dev 树。
2026-10-15 08:35:20 +08:00
wecom-fullstack e3e6b3ba8a fix(reports): 全表真实取数——清零示例兜底(BS_DEMO/CF_DEMO/_get_demo_block_total/0.50) + 上期同比/勾稽/预测标注 + CF官方口径单位收口
ci/woodpecker/push/main Pipeline failed
2026-10-15 04:13:40 +08:00
hermes 2244cd79b7 fix(reports): profit-summary 真实科目取数重建(去 KPI 比率倒推/硬编码 0.50 + 勾稽自检 + entity 隔离)
ci/woodpecker/push/main Pipeline was canceled
2026-10-14 23:14:41 +08:00
wecom-fullstack 6d8ef0d443 fix(infra): pnpm-workspace.yaml 补 packages 字段(pnpm 9.15.9 强制)+ vue-demi 占位符改 true
ci/woodpecker/push/main Pipeline failed
根因:corepack 修到 pnpm 9.15.9 后,pnpm 见 pnpm-workspace.yaml 即进 workspace 模式,
强制要求 packages 字段;缺失 ⇒ 'packages field missing or empty' ⇒ 部署树 pnpm build 失败。
本地 pnpm build 验证通过(16.05s, exit 0)。
2026-10-14 11:35:05 +08:00
wecom-fullstack e55f0ecdf9 fix(ui): 侧栏「资金内控」图标缺失——MainLayout 补 Lock 到 import 与 iconMap
ci/woodpecker/push/main Pipeline failed
任总 2026-10-14 10:49 报「资金内控:导航栏缺少图标」。
根因:permission.ts:40 icon:"Lock",而 layouts/MainLayout.vue 的
@element-plus/icons-vue import 与 iconMap 均无 Lock ⇒ iconMap["Lock"]=undefined
⇒ <component :is="undefined"> 渲染为空。全量核:菜单 40 项 / 19 个不同 icon 值,
仅 Lock 真缺。本提交仅该 1 文件 2 行(import + iconMap 各补 Lock),
不改其它图标、菜单顺序、分组、角色可见性。
2026-10-14 10:54:11 +08:00
wecom-fullstackandHermes CI Fix 26db15e6d3 fix(ui): 系统级设置归位(KPI对齐/预算模式切换入口收归系统设置)+ 业务页右下浮窗提醒
ci/woodpecker/push/main Pipeline failed
- KPIAlignment.vue: 移除页头切换按钮与模式选择器,去 saveAlignConfig;新增右下浮窗
- BudgetManagement.vue: 预算模式 el-switch -> 只读标签,去 onBudgetModeChange;新增右下浮窗
- RolePermissions.vue: 保留目标对齐正本,新增「预算模式」Tab(系统级切换入口)
- 仅 frontend/ 三件;build 通过
2026-10-13 23:04:07 +08:00
wecom-fullstack 424c33c085 feat(kpi,review): KPI direction 列 + KPITarget 模型 + 复盘产出方入库(R1 收口)
ci/woodpecker/push/main Pipeline failed
R1 收口批次(A 侧裁定 p12-ruling-input-r1-batch.RULING.md 主路径)· 单个快进提交:
- backend/app/models/__init__.py(+42/−2):CMA-KPI-20261003 阶段1 `direction`(KPIDefinition/KPITemplate)
  + ② KPITarget(kpi_targets,11 列 + uk_entity_kpi_period_type + 2 索引)
- 复盘产出方三件(review_builder 含 getattr(direction) 硬化 / review_run / 测试件),原始提交件 26dc242 的重铸件

收口边界申报:本提交**不含** D-1 批次(VoucherDetail.row_uid / ImportLog uq_import_logs_entity_batch_type)——
只读补证显示 prod `cma` 无该列/该唯一键(证据 out/r1-t1-batches.json + out/r1-t1-d1-placement.json),
携行会导致 deploy 后 voucher_details 整实体 SELECT/INSERT 报 1054;D-1 另单(先 DDL 后 ORM)。
2026-10-13 20:33:42 +08:00
Hermes CI Fix 4cdd30e321 feat(lead): 网站线索额外推送任总DM(经 ai-cs 实盘分流脚本)
ci/woodpecker/push/main Pipeline failed
- 新增 notify_boss():POST /api/cma/lead 时,除既有全员群 notify_wecom 外,
  额外经 ai-cs 实盘分流脚本(routing-live.py)通知 wecom:200653946(加性,不改动既有逻辑)
- 跨 profile 调用必须显式传 HOME/HERMES_HOME=/var/lib/wecom-ai-cs/profile:
  cma-backend.service Environment 为空,缺省会解析到非 ai-cs profile(实测无 wecom 目标)
- 失败静默(capture_output + except pass),不影响主流程
任务: ai-cs-20261013-website-lead-to-boss-and-routing-hook-ops
2026-10-13 17:48:00 +08:00
Hermes CI Fix 501322a8b9 feat(maps): 战略地图按 objective 粒度合并(granular 通道),不同 objective 并发不再互相 409
ci/woodpecker/push/main Pipeline failed
2026-10-13 11:37:24 +08:00
wecom-fullstackandwecom-yanxue f786ff9ae3 test(docs-center): 金丝雀分类断言改「必备分类在场+相对顺序」(分类扩展不再留假红)
ci/woodpecker/push/main Pipeline failed
- test_prod_content_readable 原硬编码 [term,formula,practice,faq],与生产 categories.json 全等比较;
  2026-10-12 14:05 内容目录新增 manual(模块手册,order 5) 后期望值失鲜 ⇒ 基线/改后两棵树同红。
- 改为子集式断言(必备分类在场 + 过滤后相对顺序),不再硬编码全集;分类扩展不再红。
- 同族断言盘点:本文件其余分类断言走 tmp content_dir 自持 categories.json,不依赖生产内容目录,无需改。
2026-10-13 07:48:18 +08:00
Hermes CI Fix cfd6a13ca4 fix(budget): 年度行(budget_month=0)不回落 1 月 + 同族 R1/R2/R3
ci/woodpecker/push/main Pipeline failed
- R-A2 sync-cash-plans: 年度行形态判定(_is_annual_budget_row)跳过 + skipped_annual 披露
- R2 POST /plans 期间形态校验(YYYY-MM / YYYY-00 显式接受)
- R3 budget_roll_forward 排除年度行
- R1 cash_classify 归类路径年度行判据 + 披露
- 新增 2 个回归件(14+10 例)

仅含本族 hunk(禁整文件提交): 开发区其余 14 hunk 属他会话在途件,未纳入。
2026-10-13 03:41:39 +08:00
Hermes CI Fix d08a8490eb fix(maps): 覆写通道扩面清点——同契约调用点补基准(3 例静默降级 + 2 例新增失败)
ci/woodpecker/push/main Pipeline failed
缺陷 cma-strategy-map-autosave-stale-overwrite 的护栏(PUT /api/cma/maps/{id} 覆写
dimensions/canvas_data 须带 base_updated_at,否则 409 fail-closed)改变了同一写通道的
契约 ⇒ 全仓清点调用点,在调用点取基准(写前读 updated_at),**不放宽护栏**:

- tests/test_map_versions.py: 新增 _base_updated_at(db, map_id) 助手;3 处覆写 dimensions 的
  PUT 补基准(test_rollback_backs_up_current_and_restores_content 会直接失败;
  test_rollback_again_uses_next_free_backup_version 两处此前已静默降级——PUT 被拒但用例仍绿,
  即「改了内容再回滚」的前提实际未发生)。
- tests/test_kr_name_pollution_20260916.py: 2 处 KR 透传护栏用例补基准。

改前/改后全量对拍(同树 pythonpath):
  baseline 22 failed / fixed2 18 failed;diff 仅剩 tests/test_doc_center_20260924.py::
  TestProdContentCanary::test_prod_content_readable —— 基线树同样失败(/srv/hermes/shared/
  cma-content 于 14:05 被写入 manual 分类,共享内容目录变化),与本单无关。
  本单新增的 5 例在基线树全红、改后全绿。

任务: yanxue-20261012-cma-map-autosave-stale-overwrite-defect-fullstack
2026-10-12 17:06:07 +08:00
wecom-fullstack 03254bd4c7 fix(maps): 战略地图写通道乐观并发 + 画布自动保存仅脏时写
生产缺陷 cma-strategy-map-autosave-stale-overwrite(D4 批次 19 行 map_objectives 被过期快照覆写):
- 后端 update_map: 覆写 dimensions/canvas_data 须带 base_updated_at,与服务端 updated_at 不符 → 409;
  校验在任何写入之前完成(校验不过时一行都不删/不改)
- 连线写通道(POST/DELETE connections)响应补 updated_at,供前端采纳新基准、避免自伤 409
- 前端 MapCanvas: 自动保存仅在 draft + isDirty 时触发;请求体带 base_updated_at;收到 409 停自动保存不重试
- 修复 async onMounted 竞态:await 期间被卸载后其续段仍注册定时器(清理钩子先跑完、无人回收)
  → 泄漏写者永久在后台用过期快照覆写(生产 referer=/maps 仍每 30–60s 写)。加 disposed 守卫 + stopAutoSave
- 测试: backend/tests/test_map_concurrency_20261012.py(8 例,改前 5 败);前端行为台架 11/11(改前 3/11)

任务: yanxue-20261012-cma-map-autosave-stale-overwrite-defect-fullstack
2026-10-12 11:42:56 +08:00
Hermes CI Fix 1613f7f961 fix(cpa): sales bill-type whitelist for customer revenue caliber (P0)
ci/woodpecker/push/main Pipeline failed
Customer revenue/concentration now filters bill_type IN (1,4,14) (XSD/XSTHD/XSHHD).

Non-sales docs (JHD purchase, YFKD prepay, YSKD accept, QTRK, SKD, YBFYD) carry SUPPLIER unit_id and were polluting 'customer concentration' (old Top1/Top2 were our biggest suppliers; root cause of 6.04x base gap).

Unify sign filter to (sum_money+sum_tax_money)>0 (equivalent to money_only on current data, diff 0 rows) and correct the withdrawn 407-row/17.2% wording in cpa_caliber docstring.

Deriver: anchors from cpa_caliber single source; new --concentration overwrite and --only concentration (minimal 9-row write face) with pre-overwrite backup.

Tests: fixture gains bill_type/sum_tax_money; +5 whitelist cases (44 passed targeted).
2026-10-09 17:00:37 +08:00
Hermes CI Fix 451c994a86 feat(cpa): customer profitability MVP P0-a/b - revenue caliber single source + snapshot table + 9-card tri-state
Task: finance-20261003-cpa-customer-profitability-mvp-fullstack (P0-a / P0-b)

- backend/app/utils/cpa_caliber.py (new): single source of truth for
  customer-level revenue aggregation from zxt_masterbill. Reused by
  alert_rules._customer_revenue_shares (dedupe: no second implementation).
- backend/scripts/migrate_cpa_snapshot_20261004.py (new): idempotent DDL for
  customer_profitability_snapshot (UNIQUE entity_id+period+unit_id),
  --check / --apply / --rollback / --status / --show-create + journal.
- backend/scripts/kpi_customer_profitability_deriver.py (new): monthly
  snapshot + kpi_values upsert (single transaction, idempotent).
  fail-closed: cogs_alloc / chan_sub / contrib / contrib_rate stay NULL and
  are never written as 0 or as an apportioned value.
- backend/scripts/sql/cpa_kpi_defs_20261004.sql (new): C_CUST_REVENUE and
  C_CUST_COUNT active; 5 P1 codes registered inactive with fail-closed reason.
- backend/app/api/customer_dashboard.py: new read-only endpoint
  GET /api/cma/customer-dashboard/standard-indicators returning the 9-card
  tri-state (value / no_data / undefined). Reads kpi_definitions via raw SQL
  to stay decoupled from the in-flight KPI direction DDL.
- frontend/src/views/CustomerDashboard.vue: 9-card panel rendering the three
  states (never renders an empty value as 0).

Anchor check 2026-01..09 (offline sqlite rehearsal, ALL_PASS=true):
73 customers / 4883.52 wan / top1 25.3835 / top2 23.4905 / top4 63.3249 /
top10 81.7675 - all six match the task acceptance anchors.

No production write and no deploy in this commit; release is gated.
2026-10-09 17:00:37 +08:00
wecom-fullstack a48a116e06 fix(dupont): insight.detail 叙述段字面 None 收口(表现层 _fmt_val,仅文案)
ci/woodpecker/push/main Pipeline failed
- 恒等式叙述段 5 处裸 f-string 插值(三因子 value / ROE / identity.diff)改走 _fmt_val:
  None → 「-」(与同段四列 _fmt 同族),有值原样输出(不经 :.2f,保证有值路径逐字节不变)
- 结构化字段 roe / factors[*].value / identity.diff 仍为 null;check_identity 语义、dupont_basis.py 未改
- 基线 origin/main acf179a;本单零生产写(不推远端/不同步部署树/不重启/不连库)
2026-10-06 23:36:06 +08:00
Hermes CI Fix acf179a199 fix(subjects): migrate 脚本口径乙 fail-closed(排除白名单逐码 + 双轨锚点)
ci/woodpecker/push/main Pipeline failed
2026-10-06 17:03:44 +08:00
wecom-fullstack b58513c48d docs(ddl): runbook 首步强制「迁移前像 dump 哈希」(--apply 之前)
ci/woodpecker/push/main Pipeline was successful
CMA-DDL-RUNBOOK-20261005 / parent: CMA-KPI-20261003-D-T1
- docs/db-migration-runbook.md 新增 §3.0:任何 --apply 之前对每张受影响表落
  全表有序 (PK, 受影响列) dump,记录 sha256 + 行数 + 字节数,归档 backups/pre-ddl-<task>/
- 含可直接复制的一行命令(ORDER BY 主键保证字节级确定性)
- §4 发布 checklist 第 4 条(列级 ALTER)指向 §3.0

仅文档;零生产库/零部署/零重启。
2026-10-05 13:02:02 +08:00
wecom-fullstack 4f9bab6bc0 fix(dupont): reject out-of-domain window + bidirectional clip + suffix discipline (R1-R4/M2)
ci/woodpecker/push/main Pipeline failed
Per finance ruling 2026-10-05 (project-20261005-dupont-oob-window-fix):

- R1: no intersection with available month domain => explicit error (endpoint 400), no window fields

- R2: with intersection => intersection window, months>=1 (kills inversion and months<=0)

- R3: quarter/half/... suffix kept only when returned window == nominal window (clipped flag)

- R4: symmetric lower-bound clip note; M2: TTM nominal window = [anchor-11, anchor] (12 months)

- M1: docstring correction (lower-bound overflow is clipped, not 400)

No push / no deploy / no restart / no DB write.
2026-10-05 02:02:21 +08:00
Hermes CI Fix 3ed9fa0611 fix(cvp): O1 residue - e2 rebate_policy_pct 置 null(口径单一源 = bep_caliber)
ci/woodpecker/push/main Pipeline failed
问题:/bep-card 端点对 e2(博海)回落模块内硬编码常量 BEP_REBATE_POLICY_PCT=84.61,
而 bep_caliber.ENTITY_CALIBERS[2]["policy_pct"] 为 None(博海无渠补科目)⇒ 下游 API
消费者会把 payload 里的 rebate_policy_pct=84.61 误读为「博海有 84.61% 政策渠补率」。

改动(严格限定 dashboard.py 一个模块 + 1 条守护用例):
- 删除模块级常量 BEP_REBATE_POLICY_PCT;四处回落分支改为直接取口径值
  (未注册口径分支置 None;其余取 cal.get("policy_pct") / 已算出的 policy_pct)。
- 口径单一事实源维持 app/utils/bep_caliber.py,端点不做任何回落。
- 新增 tests/test_bep_rebate_actual_caliber.py::test_o1_policy_pct_single_source_no_hardcoded_fallback
  (改前必红 / 改后必绿,e1=84.61 作同端点负对照)。

改前/改后(端点函数直调,生产库只读,e1/e2 同批):
  改前 e2 inputs.rebate_policy_pct = 84.61 → 改后 null;e1 恒为 84.61(负对照不变)。
2026-10-04 22:37:20 +08:00
wecom-fullstackandHermes CI Fix 587d5b3983 fix(cvp): BEP ⑤ 口径统一落地(变动成本率=完整口径)
ci/woodpecker/push/main Pipeline failed
- 派生器/口径:F_BEP_VC_RATE 新增;卡面/公式行文案改「月固定成本 ÷ 边际贡献率」
- 保本额 = 月固定成本 ÷ (1 − 变动成本率);实测渠补率(F_BEP_REBATE)降为 e1 专用 chip
- 报告卡口径说明文字同步(固定成本=固定费用合计)

任务: finance-20261003-cvp-fix-and-bohai-coverage-fullstack ⑤
2026-10-04 19:53:12 +08:00