主题
Hermes-aligned Restructure — Implementation Plan
Status: ⏳ Drafted 2026-05-07 · Awaiting approval before execution Source spec:
docs/planning/08-hermes-aligned-structure.mdScope: Repo-side refactor to match Hermes canonical layout. Code logic untouched; this is a layout / docs / template migration.
Goal: Bring skill/stock-research/, profile/template-stock-research-pro/, and the references doc set into Hermes' canonical shape so P1.1 provisioner work in Phase 2 Initiative B is "rsync the template, fill placeholders, start systemd" with no impedance mismatch.
Architecture: No code changes; only manifest files (SKILL.md frontmatter), new template files (config.yaml.template, .env.example, secrets.schema.json), expanded references, and updated README/sidebar/install-script wiring.
Repo surface:
skill/stock-research/
├── SKILL.md # MODIFY frontmatter
└── references/
├── chinese-a-share-data-sources.md # unchanged
├── tool-usage.md # NEW
├── session-context.md # NEW
└── price-freshness.md # NEW (extracted from SKILL.md)
profile/template-stock-research-pro/
├── AGENTS.md # unchanged
├── SOUL.md # unchanged
├── config.yaml.template # NEW
├── .env.example # NEW
├── secrets.schema.json # NEW
└── README.md # MODIFY (install flow + Hermes refs)
scripts/install-skill.sh # MODIFY (use .env.example as source)
docs/planning/index.md # MODIFY (surface 08)
docs/.vitepress/config.ts # MODIFY (sidebar)Task 1: Migrate SKILL.md frontmatter to Hermes metadata schema
Files:
Modify:
skill/stock-research/SKILL.md[ ] Step 1.1: Move
category: researchundermetadata.hermes.category[ ] Step 1.2: Add
metadata.hermes.tags: [a-share, equity-research, citation, tushare, akshare][ ] Step 1.3: Keep
required_environment_variablesblock as-is (Hermes-native already)[ ] Step 1.4: Add
version: 0.1.1matchingcore/pyproject.toml[ ] Step 1.5: Add
platforms: [macos, linux](we don't test Windows)
yaml
# After (target frontmatter):
---
name: stock-research
description: "Research Chinese A-share stocks and global equities with citation-disciplined data gathering. Every numeric claim is sourced and verifiable."
version: 0.1.1
platforms: [macos, linux]
metadata:
hermes:
category: research
tags: [a-share, equity-research, citation, tushare, akshare]
required_environment_variables:
- name: TUSHARE_TOKEN
prompt: "Tushare Pro token (https://tushare.pro/register). Required for direct mode A-share data."
optional: true
- name: TWILIGHT_SERVICE_URL
prompt: "Twilight Drive backend URL (leave blank to use direct Tushare/akshare access)."
optional: true
- name: TWILIGHT_API_TOKEN
prompt: "Twilight Drive backend API token (only needed if TWILIGHT_SERVICE_URL is set)."
optional: true
required_core_version: ">=0.1"
---- [ ] Step 1.6: Run
bash scripts/install-skill.shagainst the live profile, confirm Hermes still loads the skill (no regression)
Task 2: Extract price freshness into a reference doc
Files:
Modify:
skill/stock-research/SKILL.md(replace inline freshness section with link)Create:
skill/stock-research/references/price-freshness.md[ ] Step 2.1: Create
references/price-freshness.mdwith the served_by / metric routing matrix, narration discipline ("当前价" vs "最近收盘"), and a worked example using the v0.1.1 envelope shape[ ] Step 2.2: Replace the SKILL.md inline subsection with a one-paragraph summary + link to
references/price-freshness.mdso the skill manifest stays compact
Task 3: Add tool-usage and session-context references
Files:
Create:
skill/stock-research/references/tool-usage.mdCreate:
skill/stock-research/references/session-context.md[ ] Step 3.1: tool-usage.md — per-tool sections (
fetch_price.py,fetch_fundamentals.py,search_reports.py):- synopsis (CLI surface)
- input contract (code format, period for fundamentals)
- output envelope shape with cite fields
- exit codes (0 success, 2 client error, 64 not_implemented, 1 unexpected)
- common pitfalls (do NOT prefix with
python; period must be a quarter end)
[ ] Step 3.2: session-context.md — typical session shapes:
- "single-stock snapshot" (price + fundamentals → narrate)
- "comparison" (two codes side-by-side)
- "fundamentals trend" (multi-period fetch_fundamentals)
- "post-market vs intraday" (which tools are valid when)
- what the agent should NOT do: trade signals, target prices, stop-loss recommendations
Task 4: Add config.yaml.template to profile template
Files:
Create:
profile/template-stock-research-pro/config.yaml.template[ ] Step 4.1: Top-level structure — start from current live
~/.hermes/profiles/stock-research-agent/config.yamlshape (custom provider + Qwen3.5-27B fallback) but parameterize:- User-level placeholders →
{{PLACEHOLDER}}(provisioner replaces) - Hermes-runtime env vars →
${ENV_VAR}(Hermes resolves at startup)
- User-level placeholders →
[ ] Step 4.2: Add
mcp_servers:block (commented out for v0.1.x; unblocks P2-C):yaml# mcp_servers: # # P2-C: SearXNG self-hosted web search (replace DashScope/Google in P1.3) # searxng: # url: "${SEARXNG_URL}" # # P2-C: New-API LLM gateway (replace direct provider for key pooling) # # not modeled here; New-API exposes OpenAI-compatible endpoint via `model:` block instead[ ] Step 4.3: Add
skills:block declaring the bundled stock-research skill:yamlskills: config: stock-research: path: ${HERMES_HOME}/skills/research/stock-research guard_agent_created: false[ ] Step 4.4: Add comments above each block explaining what
{{PLACEHOLDER}}and${ENV_VAR}mean
Task 5: Add .env.example and secrets.schema.json
Files:
Create:
profile/template-stock-research-pro/.env.exampleCreate:
profile/template-stock-research-pro/secrets.schema.json[ ] Step 5.1:
.env.example— list every env var with comment showing where to get it:bash# Tushare Pro token. Required in Direct mode (no Twilight backend). # Register: https://tushare.pro/register TUSHARE_TOKEN= # Twilight Drive backend URL. Set in Service mode (P1.0+). TWILIGHT_SERVICE_URL= # Twilight Drive user bearer. Required if TWILIGHT_SERVICE_URL is set. TWILIGHT_API_TOKEN= # WeChat (iLink) channel id. Provisioner plants this in P1.1. WEIXIN_HOME_CHANNEL=[ ] Step 5.2:
secrets.schema.json— JSON Schema describing what the provisioner must plant, withrequired,format,source:json{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "stock-research-pro secrets", "type": "object", "properties": { "TWILIGHT_API_TOKEN": { "type": "string", "format": "token-urlsafe-32", "source": "generated_by_provisioner", "description": "Per-user bearer; backend hashes SHA256 for storage." }, "WEIXIN_HOME_CHANNEL": { "type": "string", "format": "wechat-channel-id", "source": "from_user_payment", "description": "Captured from the WeChat iLink callback at signup." } }, "required": ["TWILIGHT_API_TOKEN", "WEIXIN_HOME_CHANNEL"] }[ ] Step 5.3: Note in README that
.env.exampleis the human-onboarding source;secrets.schema.jsonis the machine-onboarding source for P1.1
Task 6: Update install-skill.sh to source from .env.example
Files:
Modify:
scripts/install-skill.sh[ ] Step 6.1: Replace inline
entries=()array inensure_env_keys()with reading lines fromprofile/template-stock-research-pro/.env.example. Keeps the env-var documentation in one place (the template) instead of two (template + script).[ ] Step 6.2: Skip if
.env.exampleis missing — fall back to the existing inline behavior so older release-mode installs (without the new template) still work[ ] Step 6.3: Idempotency check unchanged (only adds keys that aren't already present as
KEY=or as# KEY: stored in Keychainmarkers)
Task 7: Update README.md and planning index/sidebar
Files:
Modify:
profile/template-stock-research-pro/README.mdModify:
docs/planning/index.mdModify:
docs/.vitepress/config.tsModify:
README.md(root) — Hermes-alignment one-liner in the "what's installed" section[ ] Step 7.1: Profile README — update "How it gets used today" to show the new 4-file template (
AGENTS.md,SOUL.md,config.yaml.template,.env.example) + secrets.schema; refresh provisioner P1.1 section to show how secrets.schema is consumed[ ] Step 7.2: planning/index.md — surface
08-hermes-aligned-structureand the dated plan[ ] Step 7.3: VitePress sidebar — add 08 to the layered-axis section
[ ] Step 7.4: Root README.md — link to docs/planning/08 from the "deployment" section
Task 8: Verification
- [ ] Step 8.1:
bash scripts/install-skill.shstill succeeds against the live profile (no regression after frontmatter migration) - [ ] Step 8.2:
~/.hermes/profiles/stock-research-agent/skills/research/stock-research/SKILL.mdhas the new metadata-nested frontmatter (manual diff) - [ ] Step 8.3:
pytest core/tests/ -qstill passes (sanity — none of these changes touch code, but confirm) - [ ] Step 8.4:
npm run docs:buildstill passes (no broken sidebar links) - [ ] Step 8.5: Live profile smoke:
~/.hermes/profiles/.../fetch_price.py 600519returns the same envelope as before - [ ] Step 8.6: Verify Hermes still picks up the skill by triggering it through
hermes -p stock-research-agent chat "查 600519 的最新 P/E"(manual)
Verification commands (cheat sheet)
bash
# Validate frontmatter parses (Python YAML)
python -c "
import yaml, sys
text = open('skill/stock-research/SKILL.md').read()
fm = text.split('---', 2)[1]
parsed = yaml.safe_load(fm)
print(parsed)
"
# Validate JSON schema
python -c "import json; json.load(open('profile/template-stock-research-pro/secrets.schema.json'))"
# Sidebar build check
npm run docs:build
# Skill loads (manual smoke)
~/.hermes/profiles/stock-research-agent/skills/research/stock-research/scripts/fetch_price.py 600519不在本 plan 范围
- 写 P1.1 provisioner 实现(消费 secrets.schema.json) — 见 Phase 2 Initiative B
- MCP server 实现(SearXNG / Tushare wrap) — 见 Phase 2 Initiative C
- 自动同步 profile 模板到 live profile(hermes-profile-manager CLI) — 同上 Initiative B
Risks / 缓解
| 风险 | 缓解 |
|---|---|
Hermes 不接受嵌套 metadata.hermes.category(version mismatch) | Step 1.6 在改完后立即 install + 跑 chat 命令验证;如失败回退到 top-level category(commit 留作 escape hatch) |
config.yaml.template 替换语法跟 provisioner 期望不一致 | Initiative B 设计阶段 sync;本 plan 只先落 {{PLACEHOLDER}} + ${ENV_VAR} 两套 marker,provisioner 实现时按需调整 |
.env.example 迁移破坏 install-skill.sh 的 idempotency | Step 6.2 fallback 保证旧 release 模式不依赖新模板 |
老用户已有 .env,缺少新 key (WEIXIN_HOME_CHANNEL) | Step 6.3 的"只增不删"策略让现有 .env 不被覆盖;新 key 以注释占位形式追加 |