Files
system-dev-template/template/system-dev/workflows/tasks-project-sync.yaml
T
Leo 6a49f25aef feat(W2 Phase 0-1): 雙 profile 地基+JDD 兩軸身分+兩支防炸閘
SDD: docs/3-specs/jdd-dual-profile(draft → active,leo 2026-08-05 回「開工」)
範圍:總管指定的「防炸兩件 → Phase 0 → Phase 1」,Phase 2 以後未開工。

■ 防炸(排在所有 task 之前,因為它們炸的是既有的東西)
- check-no-instance-names.sh + instance-names.txt:框架範本不得混入實例專名
  基線實測 22 行命中(非先前誤報的 20)→ 9 行無損泛化改寫、13 行檔級豁免記帳待 W3 搬走
  拒絕假性清理(把專名換成模糊詞=資訊消失、分層問題還在)
- check-legacy-paths.sh:已發佈腳本引用的 35 條遠端路徑只增不移
  舊實例跑的是舊腳本、路徑寫死;搬檔=整排 404 且不會有下一次更新來修它(1.16.0 前科)

■ Phase 0 地基
- template/manifest/{common,repo,orchestrator}.tsv:安裝清單單一真相源
  修好 install/update 兩份硬編清單的既有漂移——install 從不裝 wiki-first-search /
  subagent-wiki-guard / publish-lag-check / decisions-summary,但 update 會
  ⇒ 乾淨安裝反而拿不到 1.16/1.17/1.18 的招牌功能
- .claude/hooks/lib/role-lib.sh:scope×role 兩軸機械判定,零自陳
  身分矩陣六組實測全通過,含「成員 repo × orchestrator」不存在的格子擋下
- .sdt-framework-dev:框架開發標記(官方沒有 --framework-dev 這個參數,實查非記憶)

■ Phase 1 雙 profile
- profiles/{repo,orchestrator}/CLAUDE.md 兩部憲法
- install.sh:--profile + 自動偵測+寫檔前確認、manifest 驅動、
  CLAUDE.md 三段組裝(框架區/本地補充區界標+sha256)、.profile、.template-manifest、
  settings.json 寫入 env.AGENT_ROLE 預設
- update.sh:漂移偵測(不覆蓋手改檔、另存 .new、白話清單)+ 基準快照隨更新前進
- template/CLAUDE.md 原路徑凍結留底(相容)

■ 順手修掉兩個舊 bug(都在本次要動的函式裡)
- add_if_missing 少了 mkdir -p ⇒ 新目錄的檔 curl 失敗但 VERSION 照升(2026-07 記「待回報」至今未修)
- 下載健全性只用 [ -s ]=非空即接受 ⇒ 404 頁面會無聲覆寫好檔
  (SKILL.md 260→1 行的機制;同一支腳本的版本號那條路早就防了,檔案這條沒防)

■ 實測(非推論)
- G4 憲法分流:兩個乾淨環境各裝一次,orchestrator 版含 SDD 三件式關鍵字 0 次、
  repo 版含上游指針 8 次;界標 4/4;sha 宣告與實算相符
- G7 CI 擋實例名:注入違規行 → fail 並指出 sdd-check.md:77,exit 1;還原後 exit 0
- 漂移偵測:手改兩支 hook → 正確報 2 支、手改內容保住、產 .new;
  解掉後歸零;連跑三輪冪等

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:56:48 +08:00

159 lines
7.4 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# tasks-project-sync — tasks.md ⇄ GitHub Project 單向投影
#
# 來源:issue #16;設計:system-dev/docs/3-specs/tasks-project-projection/design.md
#
# ⚠️ sdt-instance-name-ok-file — 檔級豁免(實例專名檢查)
# 理由:整支是 **L2 政策包產物**,不是 L1 框架內容——它綁定某一家的工作流引擎,
# 「換一家公司就不成立」。它現在還躺在框架裡只是歷史包袱。
# 帳記在這:**W3(政策包 plugin 化)時整組移出 template/**,屆時本豁免一併刪除。
# 在那之前不做假性清理(把引擎名改寫成模糊詞=資訊消失、分層問題還在)。
#
# ── 這份 workflow 的職責邊界(很重要,別搞混)──────────────────
# arcrun workflow 在 Cloudflare Workers / WASM 上「遠端」執行,沒有本地檔案系統、
# 沒有 git、沒有 shell。所以「讀 tasks.md / 跑 git diff / 把 <!-- gh:id --> 回寫 md」
# 這三件事 **不是、也不該是 workflow 的步驟**——它們由本地觸發端(CC / push 後本機腳本)
# 先做完,把「分類好的 task 增量」當 input 餵進來(acr run -i tasks_json=...)。
#
# 本地端(住 templateCC/shell 跑):讀 tasks.md → git diff → 分類四動作 → 回寫 id
# │ acr run tasks-project-sync -i ...(把增量餵進來)
# ▼
# 遠端 workflow(這份 yaml):foreach 增量 → switch 動作 → github API 投影
#
# → 因此本 workflow 只負責「拿到分類好的增量後,打 GitHub API 投影成 issue/Project」。
# 單向:只寫 GitHub,永不回改 tasks.md(回寫 id 是本地端的事,且只在新 task 做一次)。
#
# ── 輸入(由本地觸發端用 acr run -i 餵)──────────────────────────
# owner GitHub repo owner(例:your-github-account
# repo GitHub repo 名
# project_id GitHub Projects v2 的 node id(投影目標,唯讀看板)
# tasks_json 本地分類好的增量陣列,每筆形如:
# { action: "create|close|edit|archive",
# gh: 42, # 已有 id 的帶上(create 無)
# title: "...", body: "...",
# subsystem: "wiki-architecture", # = SDD folder 名,當 label 分組
# assignee: "...", due: "..." }
#
# ── credential ─────────────────────────────────────────────────
# github_tokenacr auth-recipe scaffold github → 填 credentials.yaml → acr creds push
#
# ⚠️ 端到端(acr push 真部署 + acr run 真投影)尚未經 leo21c 驗證。
# 本檔為 code-done 骨架;真部署時 GitHub API 的欄位細節(Projects v2 GraphQL
# 可能要按實測微調,屆時於 issue #16 回報。
name: tasks_project_sync
description: >
把 SDD tasks.md 的待辦增量單向投影成唯讀 GitHub Projectissue CRUD + 加進 Project)。
本地端先讀檔/git diff/分類/回寫 id,這份只負責拿增量打 GitHub API。md 當家、單向、不反向同步。
# ── flow(三元組:A >> 關係詞 >> B)─────────────────────────────
# 對每筆增量 → 依 action 路由到四種 GitHub 動作。
flow:
- "input >> 完成後 >> each_task"
- "each_task >> 對每個 task >> route_action"
# 四種動作(issue 定案):新增/關閉/編輯/封存
- "route_action >> 完成後 >> gh_create"
- "route_action >> 完成後 >> gh_close"
- "route_action >> 完成後 >> gh_edit"
- "route_action >> 完成後 >> gh_archive"
# 新建的 issue 投影進 Project(唯讀看板)
- "gh_create >> 完成後 >> add_to_project"
config:
# 逐筆迭代本地餵進來的分類增量
each_task:
component: foreach_control
iterator: task
# 依 action 欄位分流到四種 GitHub 動作
route_action:
component: switch
key: "{{task.action}}"
cases:
create: gh_create # 有文字、無 id → 建 issue(id 由本地端回寫 md)
close: gh_close # 有 id 且 [ ]→[x] → 關 issue
edit: gh_edit # 有 id 且 文字/負責人/日期改 → 編輯 issue
archive: gh_archive # id 在但整行不見 → 關閉/封存
# ── 動作 1:建 issueREST POST /repos/:owner/:repo/issues)──
# 回傳的 issue number 由本地觸發端接住、回寫 <!-- gh:number --> 到那一行。
# ⚠️ 用 http_requestarcrun registry 沒有 github 零件,21 內建確認過);
# auth 走 credential{{creds.github_token}}acr creds push 上傳,不寫死 token)。
gh_create:
component: http_request
url: "https://api.github.com/repos/{{owner}}/{{repo}}/issues"
method: POST
headers:
Accept: "application/vnd.github+json"
Authorization: "Bearer {{creds.github_token}}"
User-Agent: "arcrun-tasks-project-sync"
body:
title: "{{task.title}}"
body: "{{task.body}}"
labels:
- "{{task.subsystem}}" # 子系統 label 分組(= SDD folder 名)
assignees:
- "{{task.assignee}}"
# ── 動作 2:關 issuestate=closed)──
gh_close:
component: http_request
url: "https://api.github.com/repos/{{owner}}/{{repo}}/issues/{{task.gh}}"
method: PATCH
headers:
Accept: "application/vnd.github+json"
Authorization: "Bearer {{creds.github_token}}"
User-Agent: "arcrun-tasks-project-sync"
body:
state: closed
# ── 動作 3:編輯 issue(標題/內文/負責人)──
gh_edit:
component: http_request
url: "https://api.github.com/repos/{{owner}}/{{repo}}/issues/{{task.gh}}"
method: PATCH
headers:
Accept: "application/vnd.github+json"
Authorization: "Bearer {{creds.github_token}}"
User-Agent: "arcrun-tasks-project-sync"
body:
title: "{{task.title}}"
body: "{{task.body}}"
assignees:
- "{{task.assignee}}"
# ── 動作 4:封存(行不見 = 關閉,標 not_planned 表示非完成而是移除)──
gh_archive:
component: http_request
url: "https://api.github.com/repos/{{owner}}/{{repo}}/issues/{{task.gh}}"
method: PATCH
headers:
Accept: "application/vnd.github+json"
Authorization: "Bearer {{creds.github_token}}"
User-Agent: "arcrun-tasks-project-sync"
body:
state: closed
state_reason: not_planned
# ── 投影進 GitHub Projects v2GraphQL)──
# Projects v2 只有 GraphQLREST 沒有。用 http_request 打 /graphql。
# ⚠️ 待 leo21c 端到端驗:addProjectV2ItemById 需要 content node idissue 的 GraphQL id
# 非 issue number),實測時可能要多一步「先查 issue node id」。屆時於 #16 回報。
add_to_project:
component: http_request
url: "https://api.github.com/graphql"
method: POST
headers:
Accept: "application/vnd.github+json"
Authorization: "Bearer {{creds.github_token}}"
User-Agent: "arcrun-tasks-project-sync"
body:
query: >
mutation($project: ID!, $content: ID!) {
addProjectV2ItemById(input: {projectId: $project, contentId: $content}) {
item { id }
}
}
variables:
project: "{{project_id}}"
content: "{{gh_create.node_id}}"