Skip to content
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions docs/doc-freshness-sla.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# 文件鮮度保證機制(Doc Freshness SLA)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

這段敘述建議補上可驗證的操作步驟或明確的 acceptance criteria,避免後續落地時解讀分歧。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

這段文件描述目前偏概念;為了可落地與可驗證,建議補齊:

  • 名詞/狀態定義(觸發條件、例外清單)
  • failure mode(延遲、重複執行、外部依賴失效)與對應處置
  • 最小可行範例(至少 1–2 個具體案例)。

## 背景
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

若此設計涉及例外/邊界情境(例如:逾時、重入、並行),建議在文件中加上一小節說明預期行為與取捨。


claw-info 中的文件(`docs/`、`usecases/`)具有時效性。例如某功能在 v3.11 新增,可能在 v4.x 已被修改或移除。若文件長期無人維護,agent 讀取後可能產生錯誤行為。

## Frontmatter 標準欄位

每份文件須加入以下欄位:

```yaml
---
last_validated: YYYY-MM-DD
validated_by: <github-username>
freshness: ok # ok | stale | unreviewed
---
```

## Review 週期(依文件類型分級)

| 路徑 | 週期 |
|------|------|
| `usecases/` | 2 週 |
| `docs/` | 4 週 |
| 架構圖、穩定參考文件 | 8 週 |

## 自動化流程(GHA)

### Workflow 設計

```yaml
# .github/workflows/doc-freshness-check.yml
name: Doc Freshness Check
on:
schedule:
- cron: '0 2 * * 1' # 每週一 UTC 02:00
workflow_dispatch:

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check stale docs and open issues
env:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

腳本中的 為 GNU 特定語法,在 macOS 環境(如部分 agent 運行環境)中將失效。建議導入跨平台偵測邏輯或改用 Python one-liner 以確保執行的一致性。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正:新增 to_epoch() 函式,自動偵測 GNU / macOS BSD 環境並選擇對應語法。

GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash .github/scripts/check_freshness.sh
```

### 核心腳本(`.github/scripts/check_freshness.sh`)

```bash
#!/usr/bin/env bash
set -euo pipefail

TODAY=$(date +%s)

threshold_for() {
case "$1" in
usecases/*) echo 14 ;;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

使用 解析 YAML frontmatter 存在高度風險。應採用 或專門的 YAML 解析模組,以處理引號、多行字符串等邊界情況,確保解析過程的穩健性。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正:新增 parse_field() 函式,優先使用 yq;無 yq 時 fallback 至 awk state machine,僅讀取 --- 區塊內容,避免誤判正文。

docs/*) echo 28 ;;
*) echo 56 ;;
esac
}

for f in $(find docs usecases -name "*.md"); do
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for f in $(find ...) 會在檔名含空白/特殊字元時壞掉。雖然目前 repo 可能很乾淨,但這種腳本一旦被複製貼上就會踩雷。建議改成 find ... -print0 | while IFS= read -r -d f; do ...; done 這種安全寫法。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正:改用 find ... -print0 搭配 while IFS= read -r -d '' f,安全處理含空白或特殊字元的檔名。

last=$(grep '^last_validated:' "$f" | awk '{print $2}')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grep ^last_validated: 直接抓 YAML frontmatter 會有誤判風險(例如文件正文剛好出現同樣字串、或 frontmatter 有縮排/註解)。建議至少限定在 frontmatter 區塊內解析,或用簡單的 awk state machine 只讀 --- 之間的內容。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正:parse_field() 的 awk fallback 使用 state machine,僅在 --- 區塊內解析,不會誤判正文中的同名字串。

owner=$(grep '^validated_by:' "$f" | awk '{print $2}')
[ -z "$last" ] && continue

age=$(( (TODAY - $(date -d "$last" +%s)) / 86400 ))
threshold=$(threshold_for "$f")

if [ "$age" -gt "$threshold" ]; then
title="[Doc Review] $f 需要驗證"
# 防重複
existing=$(gh issue list --label doc-review --search "$title" --state open --json number --jq length)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One operational edge case here: if validated_by points to a user who no longer has assign permission in this repo, gh issue create --assignee can fail and prevent the review issue from being opened at all. It may be safer to make assignee best-effort, or document the fallback behavior explicitly.

if [ "$existing" -eq 0 ]; then
gh issue create \
--title "$title" \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script currently scans only docs and usecases, but the policy text also mentions stable reference material more generally. If that broader category is intentional, it may help to call out here that the MVP scope is limited to those two directories, otherwise readers may assume the workflow covers every markdown doc in the repo already.

--body "上次驗證:$last(${age} 天前)。請於 7 天內更新 \`last_validated\` 並送 PR。" \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue body 文字要求『7 天內更新 last_validated 並送 PR』,但沒有提到 freshness 欄位的預期變更(例如 stale → ok 的條件)。建議在訊息內補上更新 checklist,否則容易出現只改日期但內容沒驗證的形式化 compliance。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正:issue body 補上完整驗證 checklist,包含確認內容、修正過時處、更新 last_validatedfreshness: okvalidated_by

--assignee "$owner" \
--label doc-review
fi
fi
done
```

### Issue 格式

```
標題:[Doc Review] docs/xxx.md 需要驗證
Body:
- 文件路徑
- 上次驗證:YYYY-MM-DD(N 天前)
- 請於 7 天內更新 last_validated 並送 PR
Assignee:validated_by 欄位的 GitHub username
Label:doc-review
```

### 防重複機制

開 issue 前先執行:
```bash
gh issue list --label doc-review --search "[Doc Review] docs/xxx.md" --state open
```
若已有 open issue 則跳過。

原作者收到 issue 後須:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

『長期不回應的原作者,可能從信任名單中移除』之條款過於模糊。建議定義明確的量化指標(例如連續二次 review cycle 逾期或 30 天無回應),以提升規則的可執行性與透明度。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正:降級條件明確為「連續 2 次 review cycle(約 30 天)未回應」。

1. 對照 source code 確認內容仍正確
2. 更新 `last_validated` 與 `validated_by`
3. 若有過時內容,一併修正並送 PR

## 不回應的後果

- 超過 deadline(+7 天)未處理:文件標記為 `freshness: stale`
- Agent 讀取 stale 文件時,自動附加警告:`⚠️ 此文件已超過 review 週期,內容可能過時`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

這裡宣稱『Agent 讀取 stale 文件時自動附加警告』屬於產品行為,請補:1) 目前是否已有實作(連到 PR/issue/代碼路徑);2) 若尚未實作,需標記為 future work。否則這段會被讀者誤當成既有能力。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修正:加上 ⚠️ Future work 標註,明確說明 stale 警告機制尚未實作,待後續 PR 追蹤。

- 其他 agent 或貢獻者可接手更新
- 長期不回應的原作者,可能從信任名單中移除

## Agent 驗證流程

Agent 執行 review 時:

1. 讀取文件內容
2. 用 `gh search code` 查對應 source code
3. 比對是否有 breaking change 或 API 變更
4. 若有差異,自動送 PR 修正
5. 更新 frontmatter `last_validated`

## 相關 Issue

- [#346 提案:文件鮮度保證機制](https://github.com/thepagent/claw-info/issues/346)
Loading