@v587d/capital-generation 2.7.9 → 2.7.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,8 +28,9 @@ export const SELECTED_SKILL_SKILL_DIRS = Object.freeze({
28
28
  })
29
29
 
30
30
  // Selected-skill metadata owned by Capital Generation. Upstream snapshots remain unchanged.
31
- // 能力标签的词表就是下面 SELECTED_SKILL_TAG_LABELS 的键:卡片按条目实际用到的标签现算筛选条,
32
- // 少一套语言的显示名就会露出英文原词(test/capital-config.test.mjs 钉着)。
31
+ // 能力标签的词表由文件末尾的 SELECTED_SKILL_TAGS 注册表现算派生(SELECTED_SKILL_TAG_LABELS):
32
+ // 卡片按条目实际用到的标签现算筛选条,少一套语言的显示名就会露出英文原词(test/capital-config.test.mjs
33
+ // 钉着);tags 同时决定条目进哪几颗任务型内置 skill 的索引,所以登记一处、两处生效。
33
34
  export const SELECTED_SKILL_CATALOG = Object.freeze([
34
35
  {
35
36
  key: 'buffettFramework',
@@ -1329,59 +1330,140 @@ export const SELECTED_SKILL_CATALOG = Object.freeze([
1329
1330
  },
1330
1331
  ])
1331
1332
 
1333
+ // ── 能力标签注册表:索引与筛选的唯一来源 ─────────────────────────────────────────
1334
+ //
1335
+ // 一条精选 skill 的 tags 同时决定两件事:① 设置卡片左侧筛选条怎么分类它;② 它进哪几颗
1336
+ // **任务型内置 skill** 的索引。所以标签不是"展示分类",而是"路由声明"——登记一次,两处生效。
1337
+ //
1338
+ // 新增一个标签 = 在 SELECTED_SKILL_TAGS 里加一行(zh / en 本来就必须填,`capital-config.test.mjs`
1339
+ // 钉着),`serves` 或 `fallback` 顺带填掉。没有第二处要改,也没有任何东西会因为"忘了挂"而静默变成孤儿:
1340
+ // 下面四条闸门(`test/selected-skill-tags.test.mjs`)会把漏挂、拼错、孤儿和上限都打红。
1341
+
1342
+ /**
1343
+ * 任务型内置 skill:正文会被补上"外部精选 skill 索引"的那几颗(住 `preset/capital-generation/skills/`)。
1344
+ * 其余五颗内置 skill 是协议 / 流程类(data / web / chart / visualization / orchestration),读者是
1345
+ * 特定角色或特定工具调用,不是"用户提了一个研究任务"的入口,因此不接索引。
1346
+ */
1347
+ export const SELECTED_SKILL_TASK_IDS = Object.freeze([
1348
+ 'capital-equity-research',
1349
+ 'capital-event-impact',
1350
+ 'capital-portfolio-review',
1351
+ ])
1352
+
1353
+ /** 没有任何归属的标签,其条目兜底进这一颗(2026-10-13 决策:一切兜底都往 equity 里装)。 */
1354
+ export const SELECTED_SKILL_FALLBACK_TASK = 'capital-equity-research'
1355
+
1356
+ /**
1357
+ * 标签轴。`routes: false` 的轴只做**标注**,不决定条目进哪颗任务型 skill;`routes: true` 的轴参与路由。
1358
+ *
1359
+ * 市场口径轴是**不路由**的,这一点被实测纠过一次:最初把它写成"对所有任务型 skill 生效",结果
1360
+ * 你这 10 个启用项(9 颗带 `a-share`)在三颗任务型 skill 里得到**完全相同**的清单,索引等于失效;
1361
+ * 修成不路由之后,`10k-digest`(美股 10-K 深读)只进 equity / event-impact,`tax-lens` 只进
1362
+ * portfolio。判据因此是:"是 A 股"不蕴含"服务单股研究 / 事件影响 / 组合复盘"。
1363
+ *
1364
+ * 好处顺带落在自动化上:**新增一个市场口径标签零决策**——不写 serves、不重跑任何分配,
1365
+ * 只登记一行(zh/en/axis)即可。新增一个 routing 轴 = 这里加一行,该轴的标签各自带 `axis`。
1366
+ */
1367
+ export const SELECTED_SKILL_TAG_AXES = Object.freeze({
1368
+ market: Object.freeze({ routes: false }),
1369
+ capability: Object.freeze({ routes: true }),
1370
+ topic: Object.freeze({ routes: true }),
1371
+ })
1372
+
1373
+ /**
1374
+ * 能力标签注册表。键集 ≡ 标签词表(`SELECTED_SKILL_TAG_LABELS` 由它派生)。三轴判据:
1375
+ * market —— 什么市场口径(A 股 / 美股 / 将来的港股…),**不路由**,只做标注;
1376
+ * capability —— 调用什么分析方法(估值 / 财务健康 / 证据核验…);
1377
+ * topic —— 落在什么场景或对象上(组合、监控、税务…)。
1378
+ * routing 轴(capability / topic)的 `serves` 与 `fallback` 二选一:前者点名接收它的任务型 skill
1379
+ * (允许重叠),后者是"还没想好挂哪颗"的显式承认。两者都不给 = 孤儿,闸门会红——不写成"静默不出现",
1380
+ * 因为静默正是这套东西最容易坏的地方。
1381
+ */
1382
+ export const SELECTED_SKILL_TAGS = Object.freeze({
1383
+ 'a-share': { zh: 'A 股', en: 'A-share', axis: 'market', serves: [] },
1384
+ 'business-analysis': { zh: '业务分析', en: 'Business analysis', axis: 'capability', serves: ['capital-equity-research'] },
1385
+ 'capital-allocation': { zh: '资本配置', en: 'Capital allocation', axis: 'capability', serves: ['capital-equity-research'] },
1386
+ 'cash-flow': { zh: '现金流', en: 'Cash flow', axis: 'capability', serves: ['capital-equity-research', 'capital-event-impact'] },
1387
+ competition: { zh: '竞争格局', en: 'Competition', axis: 'topic', serves: ['capital-equity-research'] },
1388
+ earnings: { zh: '业绩与电话会', en: 'Earnings', axis: 'capability', serves: ['capital-equity-research', 'capital-event-impact'] },
1389
+ // `education` 是这张表里最勉强的一条:post-trade-review / journal-pattern-analyzer 确实服务组合复盘,
1390
+ // learning-coach 则哪边都不像。归到 portfolio 是先给一个明确归属,而不是让它掉进兜底。
1391
+ education: { zh: '教学', en: 'Education', axis: 'topic', serves: ['capital-portfolio-review'] },
1392
+ filings: { zh: '披露文件', en: 'Filings', axis: 'capability', serves: ['capital-equity-research', 'capital-event-impact'] },
1393
+ 'financial-health': { zh: '财务健康', en: 'Financial health', axis: 'capability', serves: ['capital-equity-research', 'capital-event-impact'] },
1394
+ instruments: { zh: '期权与基金', en: 'Options & funds', axis: 'topic', serves: ['capital-portfolio-review'] },
1395
+ macro: { zh: '宏观与行业', en: 'Macro & industry', axis: 'topic', serves: ['capital-equity-research', 'capital-event-impact'] },
1396
+ monitoring: { zh: '监控', en: 'Monitoring', axis: 'topic', serves: ['capital-event-impact', 'capital-portfolio-review'] },
1397
+ orders: { zh: '订单', en: 'Orders', axis: 'topic', serves: ['capital-equity-research'] },
1398
+ perspective: { zh: '分析视角', en: 'Perspective', axis: 'topic', serves: ['capital-equity-research', 'capital-event-impact'] },
1399
+ 'peter-lynch': { zh: '彼得·林奇', en: 'Peter Lynch', axis: 'topic', serves: ['capital-equity-research'] },
1400
+ portfolio: { zh: '组合与仓位', en: 'Portfolio', axis: 'topic', serves: ['capital-portfolio-review'] },
1401
+ risk: { zh: '风险', en: 'Risk', axis: 'topic', serves: ['capital-equity-research', 'capital-event-impact', 'capital-portfolio-review'] },
1402
+ strategy: { zh: '战略', en: 'Strategy', axis: 'topic', serves: ['capital-equity-research'] },
1403
+ tax: { zh: '税务', en: 'Tax', axis: 'topic', serves: ['capital-portfolio-review'] },
1404
+ technicals: { zh: '技术面', en: 'Technicals', axis: 'topic', serves: ['capital-event-impact', 'capital-portfolio-review'] },
1405
+ 'trade-discipline': { zh: '交易纪律', en: 'Trade discipline', axis: 'topic', serves: ['capital-portfolio-review'] },
1406
+ 'us-stock': { zh: '美股', en: 'US equity', axis: 'market', serves: [] },
1407
+ valuation: { zh: '估值', en: 'Valuation', axis: 'capability', serves: ['capital-equity-research', 'capital-event-impact'] },
1408
+ verification: { zh: '证据核验', en: 'Verification', axis: 'capability', serves: ['capital-equity-research', 'capital-event-impact', 'capital-portfolio-review'] },
1409
+ })
1410
+
1411
+ /**
1412
+ * 设置卡片最多能同时勾选的精选 skill 数。**只约束"能勾几个",不约束"已勾的生效"**:
1413
+ * 运行期 provider 不按这个数截断——老配置多于 6 个时照常全部生效并提示收敛,否则就是
1414
+ * "卡片上开着 10 个、会话里只有 6 个"那种静默砍功能(AGENTS.md §9.7)。
1415
+ */
1416
+ export const SELECTED_SKILLS_MAX_ENABLED = 6
1417
+
1418
+ /** 标签的显示名(含恒在第一格的「全部」)。键集恒等于注册表,所以新标签只登记一次。 */
1332
1419
  export const SELECTED_SKILL_TAG_LABELS = Object.freeze({
1333
- zh: {
1420
+ zh: Object.freeze({
1334
1421
  all: '全部',
1335
- 'a-share': 'A 股',
1336
- 'business-analysis': '业务分析',
1337
- 'capital-allocation': '资本配置',
1338
- 'cash-flow': '现金流',
1339
- competition: '竞争格局',
1340
- earnings: '业绩与电话会',
1341
- education: '教学',
1342
- filings: '披露文件',
1343
- 'financial-health': '财务健康',
1344
- instruments: '期权与基金',
1345
- macro: '宏观与行业',
1346
- monitoring: '监控',
1347
- orders: '订单',
1348
- perspective: '分析视角',
1349
- 'peter-lynch': '彼得·林奇',
1350
- portfolio: '组合与仓位',
1351
- risk: '风险',
1352
- strategy: '战略',
1353
- tax: '税务',
1354
- technicals: '技术面',
1355
- 'trade-discipline': '交易纪律',
1356
- 'us-stock': '美股',
1357
- valuation: '估值',
1358
- verification: '证据核验',
1359
- },
1360
- en: {
1422
+ ...Object.fromEntries(Object.entries(SELECTED_SKILL_TAGS).map(([tag, meta]) => [tag, meta.zh])),
1423
+ }),
1424
+ en: Object.freeze({
1361
1425
  all: 'All',
1362
- 'a-share': 'A-share',
1363
- 'business-analysis': 'Business analysis',
1364
- 'capital-allocation': 'Capital allocation',
1365
- 'cash-flow': 'Cash flow',
1366
- competition: 'Competition',
1367
- earnings: 'Earnings',
1368
- education: 'Education',
1369
- filings: 'Filings',
1370
- 'financial-health': 'Financial health',
1371
- instruments: 'Options & funds',
1372
- macro: 'Macro & industry',
1373
- monitoring: 'Monitoring',
1374
- orders: 'Orders',
1375
- perspective: 'Perspective',
1376
- 'peter-lynch': 'Peter Lynch',
1377
- portfolio: 'Portfolio',
1378
- risk: 'Risk',
1379
- strategy: 'Strategy',
1380
- tax: 'Tax',
1381
- technicals: 'Technicals',
1382
- 'trade-discipline': 'Trade discipline',
1383
- 'us-stock': 'US equity',
1384
- valuation: 'Valuation',
1385
- verification: 'Verification',
1386
- },
1426
+ ...Object.fromEntries(Object.entries(SELECTED_SKILL_TAGS).map(([tag, meta]) => [tag, meta.en])),
1427
+ }),
1387
1428
  })
1429
+
1430
+ /** 该标签服务的任务型 skill(不路由的轴 → 空;未登记的标签 → 空)。 */
1431
+ export function taggedTaskSkills(tag) {
1432
+ const meta = SELECTED_SKILL_TAGS[tag]
1433
+ if (meta === undefined) return []
1434
+ const axis = SELECTED_SKILL_TAG_AXES[meta.axis]
1435
+ if (axis === undefined || !axis.routes) return []
1436
+ return [...meta.serves]
1437
+ }
1438
+
1439
+ /** 该任务型 skill 收到的全部标签。派生自注册表:反向可达闸门与文档读它,不手写清单。 */
1440
+ export function taskSkillTags(taskId) {
1441
+ return Object.keys(SELECTED_SKILL_TAGS).filter((tag) => taggedTaskSkills(tag).includes(taskId))
1442
+ }
1443
+
1444
+ /** 该条目是否挂上了至少一颗任务型 skill——没挂上的按兜底规则进 `SELECTED_SKILL_FALLBACK_TASK`。 */
1445
+ function entryRoutesAnywhere(entry) {
1446
+ return entry.tags.some((tag) => taggedTaskSkills(tag).length > 0)
1447
+ }
1448
+
1449
+ /**
1450
+ * **唯一实现**:已启用(按运行时 skill name)的精选条目里,某颗任务型 skill 应当索引到哪几条。
1451
+ * 目录(provider 的 `list()`)、任务型 skill 的索引块、测试三处都调这一个函数,不许各自重算
1452
+ * (AGENTS.md §9.7:两份实现必然漂移,而漂移的表现是"某一处少了/多了一条",零报错)。
1453
+ * `enabledNames` 由调用方在**调用期**现读开关得到——开关是 settings 偏好,不许在装配期定格。
1454
+ */
1455
+ export function selectedSkillsForTask(taskId, enabledNames) {
1456
+ const enabled = new Set(enabledNames)
1457
+ return SELECTED_SKILL_CATALOG.filter((entry) => {
1458
+ if (!enabled.has(entry.name)) return false
1459
+ if (entry.tags.some((tag) => taggedTaskSkills(tag).includes(taskId))) return true
1460
+ // 兜底只在 equity 生效(2026-10-13 决策):一条都挂不上的条目,宁可多给它看一条,
1461
+ // 也不要静默不出现。`fallback: true` 的标签走的就是这条路。
1462
+ return taskId === SELECTED_SKILL_FALLBACK_TASK && !entryRoutesAnywhere(entry)
1463
+ })
1464
+ }
1465
+
1466
+ /** 只靠兜底才看得见的条目(当前应为空)。闸门钉住它:新增孤儿会当场点名,而不是静默消失。 */
1467
+ export function fallbackOnlySkillNames() {
1468
+ return SELECTED_SKILL_CATALOG.filter((entry) => !entryRoutesAnywhere(entry)).map((entry) => entry.name)
1469
+ }
@@ -17,7 +17,7 @@
17
17
  `LICENSE` 的版权行是 **`Copyright (c) 2026 KOMVIA`**;`marketplace.json` 的 `publisher` 也是 `KOMVIA`,
18
18
  上游 `AGENTS.md:11` 自述 `**Creator**: KOMVIA`;而仓库 owner 与 `README.md:5` 的 "Built by" 都是
19
19
  **Ayotunde Oso(账号 `GAJETOso`)**。catalog 的 `owner` 用仓库账号 `GAJETOso`——设置卡片那条
20
- 上游链接是按 `https://github.com/${owner}/${repository}` 拼的(`capital-config/client.src.cjs:576`),
20
+ 上游链接是按 `https://github.com/${owner}/${repository}` 拼的(`config/client.src.cjs:576`),
21
21
  换成品牌名就是死链。MIT 与 Apache-2.0 的差别在本仓有实际后果,见下面"许可义务"一节。
22
22
  - Imported content: 只带 `skills/` 这一棵树(48 颗,337 个文件 / 2.4 MB)与 `LICENSE` 原件,
23
23
  与所钉 commit 逐字节相同(除下面列出的 10 份)。**上游仓库根其余材料整个不复制进本仓**,
@@ -1,6 +1,6 @@
1
- // 由 scripts/build-capital-watchlist-client.mjs 生成,请勿手改;源码见 capital-watchlist/client.src.cjs。
1
+ // 由 scripts/build-watchlist-client.mjs 生成,请勿手改;源码见 watchlist/client.src.cjs。
2
2
  window.__ModuleLoader__.load({
3
- id: '@v587d/capital-watchlist',
3
+ id: '@v587d/watchlist',
4
4
  factory: (require) => {
5
5
  var module = { exports: {} }
6
6
  var exports = module.exports
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `@v587d/capital-watchlist` 的浏览器半边。
2
+ * `@v587d/watchlist` 的浏览器半边。
3
3
  *
4
4
  * 两个 surface,缺一都不成立:
5
5
  * 1. `ctx.commandUi` 的一条 **contribution**(不是 decoration——我们没有同名宿主命令),
@@ -65,7 +65,7 @@ const { createSnapshotStore } = require('@deepseek-ai/dsh-client-store')
65
65
  // 组件与文本减号。⛔ 也不用 `IconCheckCircle*`:那两支圆心里都画着东西,未勾选挂着它就像已经被
66
66
  // 选中(2026-10-09 实机点名的正是这个错觉)。
67
67
  const { IconChecklistOutlineRegular, IconCloseOutlineRegular, IconDatabaseOutlineRegular, IconEllipsisOutlineRegular, IconGoalOutlineRegular, IconListPenOutlineRegular, IconPinOutlineRegular, IconRefreshOutlineRegular, IconSearchOutlineRegular, IconTrashOutlineRegular, Menu, MenuItemButton, Modal, Switch } = require('@deepseek-ai/dsh-client-ui-primitives')
68
- // 「哪些标的可以是一个仓位」与「占比合计封顶多少」都来自 `capital-watchlist/holding-rules.js`
68
+ // 「哪些标的可以是一个仓位」与「占比合计封顶多少」都来自 `watchlist/holding-rules.js`
69
69
  // (构建期由 esbuild 内联进来):面板画不画那一行、`+` 什么时候置灰,与 `/holding` 收不收这一格
70
70
  // 不许各说一套。
71
71
  const { isHoldable, weightCeiling } = require('./holding-rules.js')
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `@v587d/capital-watchlist` 的 host half。
2
+ * `@v587d/watchlist` 的 host half。
3
3
  *
4
4
  * 用户自选股是**宿主级(跨 workspace)的用户侧资产**:清单与报价快照住在官方
5
5
  * `storage-domain` 域 `capital_watchlist`(`~/.dsh/storages/capital_watchlist.json`),
@@ -1,6 +1,6 @@
1
1
  {
2
- "name": "@v587d/capital-watchlist",
3
- "version": "2.7.9",
2
+ "name": "@v587d/watchlist",
3
+ "version": "2.7.11",
4
4
  "description": "Capital 模式的用户自选股(宿主级清单 + Fuyao 报价快照 + /capital-watchlist 路由 + 输入框菜单弹窗):由 @v587d/capital-generation 随包携带并作为 host 平面行挂载。",
5
5
  "license": "MIT",
6
6
  "type": "module",