Skip to content

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: research under metadata.hermes.category

  • [ ] Step 1.2: Add metadata.hermes.tags: [a-share, equity-research, citation, tushare, akshare]

  • [ ] Step 1.3: Keep required_environment_variables block as-is (Hermes-native already)

  • [ ] Step 1.4: Add version: 0.1.1 matching core/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.sh against 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.md with 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.md so the skill manifest stays compact

Task 3: Add tool-usage and session-context references

Files:

  • Create: skill/stock-research/references/tool-usage.md

  • Create: 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.yaml shape (custom provider + Qwen3.5-27B fallback) but parameterize:

    • User-level placeholders → {{PLACEHOLDER}} (provisioner replaces)
    • Hermes-runtime env vars → ${ENV_VAR} (Hermes resolves at startup)
  • [ ] 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:

    yaml
    skills:
      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.example

  • Create: 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, with required, 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.example is the human-onboarding source; secrets.schema.json is 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 in ensure_env_keys() with reading lines from profile/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.example is 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 Keychain markers)

Task 7: Update README.md and planning index/sidebar

Files:

  • Modify: profile/template-stock-research-pro/README.md

  • Modify: docs/planning/index.md

  • Modify: docs/.vitepress/config.ts

  • Modify: 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-structure and 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.sh still succeeds against the live profile (no regression after frontmatter migration)
  • [ ] Step 8.2: ~/.hermes/profiles/stock-research-agent/skills/research/stock-research/SKILL.md has the new metadata-nested frontmatter (manual diff)
  • [ ] Step 8.3: pytest core/tests/ -q still passes (sanity — none of these changes touch code, but confirm)
  • [ ] Step 8.4: npm run docs:build still passes (no broken sidebar links)
  • [ ] Step 8.5: Live profile smoke: ~/.hermes/profiles/.../fetch_price.py 600519 returns 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 的 idempotencyStep 6.2 fallback 保证旧 release 模式不依赖新模板
老用户已有 .env,缺少新 key (WEIXIN_HOME_CHANNEL)Step 6.3 的"只增不删"策略让现有 .env 不被覆盖;新 key 以注释占位形式追加

进一步阅读

团队内部文档