Skip to content

fix(dashboard): add missing gather_status_payload (status endpoint 500) - #12

Open
allenter wants to merge 3 commits into
MaxMiksa:mainfrom
allenter:pr/fix-dashboard-status-endpoint
Open

fix(dashboard): add missing gather_status_payload (status endpoint 500)#12
allenter wants to merge 3 commits into
MaxMiksa:mainfrom
allenter:pr/fix-dashboard-status-endpoint

Conversation

@allenter

@allenter allenter commented Aug 2, 2026

Copy link
Copy Markdown

PR: fix(dashboard): 补全缺失的 gather_status_payload,修复状态接口 500

类型:bug fix | 影响:看板状态面板在任何平台均不可用 | +33 行

问题描述

看板页面能加载(HTML/JS/CSS 正常),但 /api/status 返回空响应(HTTP 连接被重置),状态卡片、共识预览、日志面板全部不可用。

复现步骤

  1. python3 dashboard/server.py
  2. curl -v http://127.0.0.1:8787/api/status
  3. 观察:Empty reply from server,服务端日志报:
NameError: name 'gather_status_payload' is not defined
  File ".../server.py", line 610, in do_GET
    self._json(gather_status_payload())

根因

DashboardHandler.do_GET/api/status 路由调用了 gather_status_payload(),但整个文件中从未定义该函数(疑似重构时遗漏)。Python 解释器在请求时抛 NameError,连接被异常中断。

同文件已有的相关函数:run_status_command()parse_status_output()read_state_file_pairs()read_text_file()read_tail() 都已存在且可复用——只缺把它们串起来的 gather_status_payload()

修复

parse_status_outputgather_vault_payload 之间补全该函数,完全复用现有工具函数,并保持代码库的防御式风格:

def gather_status_payload() -> dict[str, Any]:
    """Gather live status for the dashboard.

    Runs the host status script, parses its output, and layers in the
    state file, consensus preview, and recent log for the UI.
    """
    payload: dict[str, Any] = {
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "ok": False,
        "parsed": blank_parsed(),
        "stateFile": {},
        "consensusHead": "",
        "logTail": "",
        "raw": "",
    }

    try:
        result = run_status_command()
    except Exception as exc:  # pragma: no cover - defensive
        payload["raw"] = f"(status command error: {exc})"
        return payload

    raw = result.get("output", "")
    payload["ok"] = bool(result.get("ok"))
    payload["raw"] = raw
    if raw:
        payload["parsed"] = parse_status_output(raw)
    payload["stateFile"] = read_state_file_pairs()
    payload["consensusHead"] = read_text_file(CONSENSUS_FILE, "").strip()[:2000]
    payload["logTail"] = read_tail(LOG_FILE, lines=120)
    return payload

返回结构对齐 dashboard/app.js 的消费方:parsed / stateFile / consensusHead / logTail / raw / ok / timestamp

验证

  • curl http://127.0.0.1:8787/api/status 返回完整 JSON(loop/daemon/guardian/autostart 状态、共识预览、日志尾部)
  • 前端状态卡片、共识、日志面板正常渲染
  • 状态命令异常时返回 ok: false 而非 500

变更文件

  • dashboard/server.py(+33 行)

测试建议

  • python3 -c "import dashboard.server" 无 NameError
  • 启动后 curl /api/status | python3 -m json.tool 校验结构

Co-Authored-By: Claude noreply@anthropic.com

allenter and others added 3 commits August 2, 2026 08:50
Layer a zero-dependency, pure-Python vector memory store (memories/vault/)
on top of the existing single-file consensus baton:

- scripts/core/memory_vault.py: chunk consensus + docs, index into
  memories/vault/index.json (TF-IDF char n-grams + cosine similarity,
  no external deps), and semantic search with -top-k / min-score.
  Backend swappable: replace _embed_chunk() to plug in ChromaDB or a
  model embedding.
- auto-loop.sh: each cycle auto-retrieves the top relevant historical
  blocks (keyed off Next Action) and injects them into the prompt as
  '## Highly-relevant past memory'; after a successful/soft-timeout
  cycle it indexes the latest consensus + docs into the vault.
- .gitignore: ignore memories/vault/* runtime data.
- Docs updated: README(EN/ZH), CLAUDE.md, PROMPT.md, INDEX.md.

consensus.md remains the authoritative running-state baton; the vault
adds long-term recall of decisions/context that consensus collapses.
Add a Memory Vault panel to the control deck:

- server.py: new GET /api/vault endpoint. Reads memories/vault/index.json
  directly (no subprocess) and returns stats (chunk/source/term counts,
  size, last-indexed), per-source breakdown, latest entries, plus optional
  in-process cosine semantic search via ?q=.
- app.js: fetchVault() renderer with stat cards, a canvas bar chart of
  chunks per source, latest-entry list, and a live semantic-search box
  (Enter or button) showing scored hits with source tags.
- index.html: Memory Vault section between Consensus and Recent Log.
- styles.css: dark-theme styles for stats, canvas, entries, tags.

Pure stdlib on the server side; canvas drawn client-side.
The dashboard page loads but /api/status returns an empty reply and
the status panel is unusable on every platform: do_GET calls
gather_status_payload(), which is never defined anywhere in
dashboard/server.py, so the request dies with
`NameError: name 'gather_status_payload' is not defined`.

Implement it by composing the already-existing helpers
(run_status_command / parse_status_output / read_state_file_pairs /
read_text_file / read_tail), matching the shape app.js consumes
(parsed / stateFile / consensusHead / logTail / raw / ok / timestamp),
and keeping the codebase's defensive try/except style.

Verified: curl /api/status returns the full status JSON; frontend
cards/consensus/log panels render; a failing status command returns
ok:false instead of 500.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant