@dac-tech-team-tw/itsaplan-cli 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,17 @@
1
1
  # itsaplan-cli
2
2
 
3
- It's a Plan 的獨立 CLI,入口為 `iap` 與 `itsaplan`。Node.js 22+;API 基線 1.9.0。npm 套件名稱選定為 `@dac-tech-team-tw/itsaplan-cli`,尚未首次發布;scope 擁有權與 Trusted Publisher 設定仍待維護者完成。
3
+ It's a Plan 的獨立 CLI,入口為 `iap` 與 `itsaplan`。Node.js 22+;API 基線 1.9.0。公開 npm 套件為 `@dac-tech-team-tw/itsaplan-cli`,原始碼維持 private;目前採本機手動發布,GitHub Actions 負責 CI。
4
4
 
5
5
  ## 安裝
6
6
 
7
+ ```sh
8
+ npm install -g @dac-tech-team-tw/itsaplan-cli
9
+ iap --help
10
+ itsaplan --version
11
+ ```
12
+
13
+ 從原始碼安裝:
14
+
7
15
  ```sh
8
16
  pnpm install
9
17
  pnpm build
@@ -33,6 +41,16 @@ printf '%s' "$ITSAPLAN_API_KEY" | iap auth login --with-token --storage file
33
41
 
34
42
  Endpoint:`--api-url` > `ITSAPLAN_URL` > 使用者設定。Key:`ITSAPLAN_API_KEY` > 與 endpoint 配對的本機憑證 > 一次性 `--api-key`。env key 或顯式 key flag 必須搭配 env URL 或 URL flag,不能偷偷使用已存 endpoint;flag 可能暴露在 process list,正常使用請選 env 或登入。
35
43
 
44
+ 首次登入請向服務管理者確認 **API 服務網址**(部署的 API domain,含 `https://` 與必要的 base path),不要填平常開啟的網頁登入網址;不能只填裸 hostname。登入提示會標明預設網址來自 `--api-url`、`ITSAPLAN_URL` 或已儲存設定,手動輸入可覆寫該預設。若 `/me` 回傳 redirect,CLI 仍安全拒絕,不會跟隨或把 key 轉送到目的地;即使手動輸入相同網頁網址也會被拒絕,不代表 key 無效。確認 API 網址後,以 `iap auth login --api-url <API_URL>` 重試;CLI 不猜測 API hostname。
45
+
46
+ 互動登入會在輸入 key 前辨識既有 `ITSAPLAN_API_KEY`,說明後續指令仍受環境設定影響,讓使用者選擇繼續儲存或取消;不修改父 shell 或 shell 啟動設定,也不改變 CI 的憑證優先序。登入驗證/儲存成功不代表後續未帶參數的命令會使用同一身份。`auth status` 區分已儲存憑證的 metadata 與目前生效來源;未實際驗證的已存身份不會宣稱已認證。
47
+
48
+ 一般 `auth login` 成功只在 stdout 顯示 `OK` 與已儲存結果;必要警告以繁體中文輸出至 stderr,不印出完整身份或設定。需要完整資料時加 `--json`,仍保留一個完整 JSON envelope;登入失敗沿用既有錯誤 envelope 與 exit code。提示、環境憑證警告與 redirect 診斷使用繁體中文,旗標、環境變數與錯誤碼名稱不變。
49
+
50
+ 登入的 `data.authenticated`/`data.user` 保留「本次輸入 key 已驗證」的既有語意;`data.saved` 描述已存登入,`data.effective` 描述後續不帶登入旗標的命令。Status 則驗證目前生效身份。兩者的 `verification` 與 `usable` 不混用:`not_run`/`usable:null` 表示尚未確認生效憑證可用,`usable:false` 表示已知阻礙;未檢查的已存 key 使用 `tokenAvailable:null`,不等同沒有 key。
51
+
52
+ 要暫時使用已存登入而不更動目前 shell,POSIX 可執行 `env -u ITSAPLAN_API_KEY -u ITSAPLAN_URL iap auth status --json`;其他平台請在目前 shell 明確移除這兩個變數後再查詢。環境 key 未搭配明確 URL 時仍回報 `EXPLICIT_ENDPOINT_REQUIRED`,絕不將它送往已存 endpoint。
53
+
36
54
  macOS 設定在 `~/Library/Application Support/itsaplan/config.toml`;Linux 在 `$XDG_CONFIG_HOME/itsaplan/config.toml`(預設 `~/.config`);Windows 在 `%APPDATA%/itsaplan/config.toml`。設定不含 key;原生憑證庫採 Keychain/Secret Service/Credential Manager。不可用時不自動降級,須明確指定 `--storage file`。POSIX 憑證目錄 0700、檔案 0600;Windows 使用 ACL。完整正規化 base URL(含 path)隔離憑證。`auth logout` 只清除該 endpoint 本機憑證,不撤銷 key,也不能清除外部 env。
37
55
 
38
56
  Login 會先檢查設定檔安全性並準備完整的設定暫存檔,再儲存憑證。後續設定提交失敗時,會還原原憑證或移除本次新憑證,保留其他 endpoint;讀回確認還原後回報 `not_applied`/exit 1。若無法確認還原,則回報 exit 6 與 `data.recovery` 清理位置,不宣稱登入成功或已安全還原。
@@ -55,9 +73,47 @@ iap issue list --project acme.MKT --search 'login' --json
55
73
 
56
74
  範例名稱與 ID 皆為虛構。`MKT-42` 的 42 是 project sequence,不是內部 ID;裸數字需要專案範圍。`--id` 與 positional 互斥,已知識別碼直接解析,不先掃清單。跨團隊 key 歧義請指定完整 `team.KEY`。明確識別碼與專案矛盾會拒絕。
57
75
 
58
- 專案範圍:`--project` > `ITSAPLAN_PROJECT` > 最近 `.itsaplan.toml`(到 git root 為止,repo 外不超過 home)。`init --project <team.KEY>` 先驗證專案,只在目前目錄寫入 project_ref;拒絕既有或 dangling symlink,以同目錄暫存檔原子替換設定,不寫穿 symlink 目標。
76
+ 目錄專案設定使用最近 `.itsaplan.toml`(到 git root 為止,repo 外不超過 home)。`init --project <team.KEY>` 先驗證專案,只在目前目錄寫入 project_ref;拒絕既有或 dangling symlink,以同目錄暫存檔原子替換設定,不寫穿 symlink 目標。
59
77
 
60
- List/search 預設 30,只有真實 limit、完整性 unknown,不提供假 `--all`。Search 不混用 assignee。Feed 預設 25、最多 100;把回傳 `data.nextCursor` 原樣交給 `--cursor`。`view --comments` 只讀最近 25 個頂層留言與可取得的回覆,並非全部討論。附件只提供 metadata,不代表已讀取內容。
78
+ 使用者層級預設專案可跨目錄使用,與完整 API 服務網址(含 path)綁定;切換 endpoint 不會套用另一個伺服器的預設:
79
+
80
+ ```sh
81
+ iap config set project acme.MKT --json
82
+ iap config get project --json
83
+ iap issue list --search 'login' --json
84
+ iap config unset project --json
85
+ ```
86
+
87
+ `set` 先向目前可信 endpoint 驗證專案,保存伺服器回傳的完整 `team.KEY`;`get` 顯示該 endpoint 的預設與目前生效專案及來源;`unset` 只移除該 endpoint 的使用者預設,不刪認證或目錄設定。專案優先序為 `--project` > `ITSAPLAN_PROJECT` > 最近 `.itsaplan.toml` > 該 endpoint 的使用者預設;清除後仍可能由較高優先序來源選定專案。此功能不取代 `init`,也不將 endpoint 或 key 寫入 repo。
88
+
89
+ List/search 預設 30,本地 `--limit` 接受 1–500,但不保證 server 回滿;僅支援 bounded limit,沒有接續分頁(cursor/page),完整性維持 unknown,不提供假 `--all`。Feed 預設 25、最多 100;把回傳 `data.nextCursor` 原樣交給 `--cursor`。`view --comments` 只讀最近 25 個頂層留言與可取得的回覆,並非全部討論。附件只提供 metadata,不代表已讀取內容。
90
+ 所有指令的 help 說明、標題與內建 help/version 說明均以繁體中文顯示;指令、旗標、佔位符、值、API/JSON 欄位名及技術識別字維持原樣。各層 help 顯示繼承的全域選項(含 `--project`/`--json`)、專案來源優先序與全域說明入口 `iap --help`。查末級指令說明請使用 `iap issue view --help`;list 與 view 提供手動 list → view 範例:從清單選出 `KEY-42` 或內部 ID 後明確傳入,`view` 不會從標準輸入自動接收 list 的 JSON。
91
+
92
+ ### Agent 分階段讀取與欄位選取
93
+
94
+ `--summary` 與 `--fields <paths>` 為互斥、明確 opt-in 的資料選取;未指定時保留原有完整輸出。`--json` 只控制 compact JSON 序列化,可與任一選取模式合用。僅支援 `project list/view` 與 `issue list/view/resolve/comments/activity`;其他命令(含寫入與 dry-run)拒絕選取旗標,錯誤結果不投影。
95
+
96
+ ```sh
97
+ # 探索與搜尋:保留完整標題、可讀狀態;先定位再閱讀
98
+ iap project list --summary --json
99
+ iap issue list --project acme.MKT --search 'login' --summary --json
100
+ # Workflow 值按需查詢,不必每張票重印完整 project setup
101
+ iap project view acme.MKT --fields project.ref,columns.id,columns.name,columns.stateType --json
102
+ # 閱讀需求:不截斷正文、驗收條件、自訂欄位或已取得的討論
103
+ iap issue view MKT-42 --project acme.MKT --comments --summary --json
104
+ # 明確的窄查詢;不代表已完整閱讀需求
105
+ iap issue view MKT-42 --project acme.MKT --fields identifier,title,priority --json
106
+ ```
107
+
108
+ 摘要層級:project list 保留 id/ref/name;project view 保留精簡 project 與 columns、issueTypes、labels,以及完整 customFields,其他 setup 資料請選欄位或用完整輸出。Issue list 保留 id/identifier/title/columnId/state;issue view 只縮小巢狀 project metadata,保留其他原始 issue 資料及自訂欄位定義。Resolve 與討論/活動摘要不刪除其資料,避免漏掉討論內容。
109
+
110
+ `--fields` 為資料相對點路徑:list/feed 作用於每個 item,view/resolve 作用於 data;巢狀陣列維持原形,例如 `columns.id,columns.name`。欄位名稱依各命令的固定 schema 驗證,空集合仍能抓到錯字;未知或不安全路徑於 API 請求前拒絕。整個已知欄位(如 `customFields`)可直接選取;未支援的新 server 欄位請用完整輸出。`meta.output` 標明模式、選取欄位(適用)與 `missing` 路徑:已選但 server 未提供的欄位不補 null;null 保留原意,未選欄位不出現在資料中。
111
+
112
+ 選取不會移除 envelope、分頁游標及既有 meta。Issue list 的 `meta.scope` 描述本次專案與搜尋/負責人範圍;取得 setup 時使用其 canonical ref,否則保留請求 ref。其餘 issue 讀取的 scope 保留 issueId、identifier、projectId 及可得 projectRef;view 即使只指定 `--id`,也保留後續取得的 canonical projectRef。Issue view 的 `meta.read.comments` 區分 `not_read` 與 `read_page`,後者另附 nextCursor;其 limit、returned、completeness 統一讀取 `meta.comments`。附件為 `metadata_only`、`contentRead:false`。Comments/activity 的 `meta.read.entries` 描述 status、contentRead、filter 與輸入/下一頁游標,筆數與完整性統一讀取既有 `meta.limit/returned/completeness`,其 attachments 為 `not_read`。`--fields` 不能移除這些讀取範圍標記。`nextCursor:null` 仍不代表 issue list 完整。
113
+
114
+ Issue list 摘要或選取 `state`/`state.*`,會共用最多一次額外 project setup GET;搭配負責人篩選則重用既有 setup。List 的 state 僅支援 id/name/stateType/unavailable;color、WIP 等完整欄位請用 project view 或 issue view 查詢。未知 columnId 保留 ID 並標示 `unavailable:true`,不猜測狀態;即使只選 `state.name`,仍保留診斷用 id/unavailable,且將 name 標為 missing。只選其他欄位不增加這項請求。投影不改變其他既有讀取流程,不代表減少 HTTP payload,也不新增持久快取。多票共用同一份已讀 workflow 上下文即可;修改前仍須讀取最新相關資訊,既有寫入 preflight 不使用該上下文取代查證。
115
+
116
+ 驗收以相同 fixture、相同 compact serializer 比較完整/分階段整個任務的 UTF-8 stdout bytes(含 LF)、API/CLI 呼叫次數與需求保留正確性。不能只看單次回應或行數;沒有指定 tokenizer/model 實測時不宣稱 token 節省比例。
61
117
 
62
118
  ## 預覽與寫入
63
119
 
@@ -135,7 +191,7 @@ iap api /some-resource --method POST --input payload.json --dry-run --json
135
191
  {"ok":true,"data":{"id":123,"identifier":"MKT-42"},"meta":{"schemaVersion":1,"apiVersion":"1.9.0"}}
136
192
  ```
137
193
 
138
- 列表 `data` 為 `{ "items": [], "nextCursor": null }`,`meta` 包含 returned、completeness 及適用的 limit。PR 清單改用真實 `nextPage`,不提供假 cursor;`null` cursor 不等於所有列表皆完整。doctor/auth/init/project/issue/document/api 全部遵循相同 envelope;上方各家族命令可直接加 `--json`。
194
+ 列表 `data` 為 `{ "items": [], "nextCursor": null }`,`meta` 包含 returned、completeness 及適用的 limit。PR 清單改用真實 `nextPage`,不提供假 cursor;`null` cursor 不等於所有列表皆完整。doctor/auth/config/init/project/issue/document/api 全部遵循相同 envelope;上方各家族命令可直接加 `--json`。
139
195
 
140
196
  ```json
141
197
  {"ok":false,"error":{"code":"ACTOR_REQUIRED","message":"Provide --agent or --human","retryable":false},"outcome":"not_applied","verification":"not_run","data":null,"meta":{"schemaVersion":1}}
@@ -161,58 +217,23 @@ npm pack --dry-run --json
161
217
 
162
218
  測試使用本機 HTTP fixture 與 fake client,不呼叫 production 寫入。npm `files` allowlist 只含 dist 與 README(npm 另含 package metadata),不發布開發 OpenAPI、設計稿、AGENTS、本機設定或 secrets。`publishConfig.access=public`;private GitHub repo 不代表 npm 內容私有。未實測的平台不得據此宣告支援;macOS/Windows 原生憑證庫、ACL 與安裝仍需各平台實測。
163
219
 
164
- ### npm Release runbook
165
-
166
- 原始碼維持 private,npm 套件與 tarball **公開**。不需要為發布公開 GitHub repo。private repo 不支援 npm provenance,`publishConfig.provenance=false` 並於發布時明確關閉;不宣稱具備來源證明。參考 [npm Trusted Publishing](https://docs.npmjs.com/trusted-publishers/) 與 [scoped public packages](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/)。
167
-
168
- #### 首次發布前的人工設定(尚未完成)
169
-
170
- 1. #3 已完成,但維護者仍須確認試用結果、正式名稱與版本;本票的實作不授權首次發包。
171
- 2. 在自己的終端執行 `npm login --registry=https://registry.npmjs.org`,再執行 `npm whoami`。使用擁有 `@dac-tech-team-tw` scope 的 npm 個人帳號;GitHub organization 不會自動建立 npm organization。若 scope 屬於組織,確認帳號具備該組織的套件建立/發布權限。不要分享 token、OTP 或 `.npmrc`。
172
- 3. 啟用 npm 帳號 2FA。首次 package 尚不存在時,先由維護者明確授權,用下方流程產生、安裝驗證的**同一份 tarball** 做一次人工 bootstrap。人工發布需 npm 登入與 2FA;不要建立長期 CI 發布 token。發布前保存 receipt、確認 package/version/tag/commit/integrity 與最新 registry 狀態;結果不明時先查證,禁止直接重送。
173
- 4. bootstrap 指令形式為 `npm publish /absolute/path/to/verified-package.tgz --access public --provenance=false --ignore-scripts --registry=https://registry.npmjs.org`。這是需要另行授權的真正公開發布,**不是本票已執行的步驟**。首次版本必須來自已合併 main 的版本 PR 與正確 tag,保留人工操作與安裝證據。因尚未建立 package,不能假裝已綁定 Trusted Publisher。
174
- 5. package 建立後,在 npm package Settings → Trusted Publisher 新增 GitHub Actions:Organization `dac-tech-team-tw`、Repository `itsaplan-cli`、Workflow filename `release.yml`(不是完整路徑)。基線未使用 GitHub Environment,該欄留空;若另加 environment,workflow 必須同步。Allowed actions **明確勾選直接 `npm publish`**;新建設定預設允許 staged publish 不等於允許直接發布。新 publisher 須於兩天內完成首次成功 OIDC 發布,過期需重建;不要因此跳過版本審核。
175
- 6. npm Publishing access 選擇「Require two-factor authentication and disallow tokens」;OIDC 不受禁止 token 影響。GitHub 不設定 `NPM_TOKEN`/`NODE_AUTH_TOKEN` 等發布 secret。
176
- 7. GitHub Settings → Rules → Rulesets:建立 active 的 tag ruleset,include `refs/tags/v*`,限制 creation/update/deletion,僅 release 維護者具 bypass。維護者需保存設定證據。**目前 API 回傳 403,帳號方案不支援此 private repo 的 ruleset**;須升級適用方案或另行決定等效保護方案,不要為此公開原始碼;本機流程無法代替 GitHub tag 保護。
177
- 8. 完成上述前置、由維護者確認後,才設定 repository Actions variable `NPM_RELEASE_ENABLED=true`。未設定時 CD 拒絕發布。此開關不是 npm 權限替代品,也不代表本文件所列人工設定已完成。Environment approval 可依方案額外加上;人工正式關卡仍是建立正式 Release。
220
+ ### npm 發布
178
221
 
179
- #### 每版流程
222
+ 使用 **GitHub CI + 本機手動發布**,操作步驟與失敗處理見 [DEPLOY.md](DEPLOY.md)。每次以版本 PR 更新 package version、合併並確認 main CI 後,在乾淨的 main checkout 執行 `pnpm run release`,會自動測試、打包/安裝驗證並透過互動式 npm 發布同一份 tarball;`pnpm run release --dry-run` 只驗證、不發布,也不要求新版本或乾淨 main。正式發布不自動加版號或重送,仍須完成 npm/2FA 及發布後 registry 安裝驗證。
180
223
 
181
- 1. 建立版本 PR,修改 `package.json` version,執行 `pnpm install --lockfile-only --ignore-scripts` 並提交任何 lockfile 變更。pnpm lockfile 不儲存根套件 version,純版號變更可能沒有 lockfile diff;不可人工加入無效欄位。CLI `--version`/doctor 直接讀 package version,不再維護第二份常數。
182
- 2. PR 與 push 到 main 只跑 CI;固定 Node 24.22.1、npm 11.19.1、pnpm 12.14.0,frozen install → build → typecheck → test。沒有 npm 寫入憑證或 OIDC 寫入權限。
183
- 3. 合併後,選定 main 歷史中的 commit,建立恰為 `v` 加 package version 的 tag,例如 `v0.1.0`。禁止移動既有 release tag。單純 push tag 不會發布。
184
- 4. 在該 tag 建立並 **publish 正式 GitHub Release**。draft/edited 不觸發;prerelease、beta/rc、非正式 SemVer、版本不符、非 main 歷史均拒絕。不要測試性 publish Release,因為這是正式發包授權。
185
- 5. Actions → Release:檢查實際 tag commit、測試、pack receipt 與 artifact。工作流僅 pack 一次,驗證實際內容並從隔離暫存目錄安裝同一 tarball;兩個 bin 的 help/version 與無認證 doctor 都須通過。doctor 缺 auth 非零是預期,不注入正式 API key。
186
- 6. 僅 publish job 有 `contents: read` 與 `id-token: write`,使用 GitHub-hosted runner 的 OIDC;發布下載的同一 tarball,不重新打包。發布序列化、不因新 release 取消進行中的 publish;舊版本不得把 latest 倒退。
187
- 7. 首次真正 OIDC 發布後,保存成功 Actions run URL、npm package/version、tag/commit、sha512 integrity,以及在乾淨目錄以 `npm install --prefix /tmp/iap-release-check @dac-tech-team-tw/itsaplan-cli@X.Y.Z` 安裝後執行兩個 bin 的證據。這些**真實發布證據尚未取得**,本機 dry verification 不可替代。
224
+ 不需要 GitHub 付費方案、tag ruleset 或 Trusted Publisher。原始碼 private、npm package public;明確關閉不支援 private repo 的 provenance。既有 Release 工作流保留但 `NPM_RELEASE_ENABLED` 維持未啟用,不因合併 main 或 push tag 自動發布。日後改用 OIDC 必須另行完成設定。
188
225
 
189
- 本機產物驗證(不發布):
190
-
191
- ```sh
192
- pnpm install --frozen-lockfile --ignore-scripts
193
- pnpm build
194
- pnpm typecheck
195
- pnpm test
196
- node --test test/release-*.test.mjs
197
- node scripts/pack-check.mjs /tmp/itsaplan-release-artifact
198
- ```
199
-
200
- 此目錄保存唯一 tarball 與 `release.json`;另行檢查 receipt 的 tag/commit,未建立 tag 的本機驗證不是可發布 release。artifact 包含全部公開內容,仍需人工內容審閱。pack allowlist 從 `src/` 平面 runtime 模組推導,拒絕額外 dist 檔案。
226
+ ### 已執行驗證
201
227
 
202
- #### 失敗與重跑
228
+ - #11/#12(含 PR #15 review 修正):build、型別檢查與 63 個相關 output/issue/實際 CLI 測試通過,涵蓋 internal ID view 的 canonical 專案範圍、list state 欄位驗證與未知狀態巢狀投影診斷。Linux 本機 HTTP fixture 的相同雙票流程(compact JSON,含 LF)完整輸出累計 28531 bytes、11 次 API/5 次 CLI;分階段輸出 18825 bytes、12 次 API/5 次 CLI。正文、自訂欄位、checklists、討論及附件 metadata 保持一致;多一次 API 為搜尋可讀狀態的 setup GET。未量測 tokenizer/model token,未呼叫正式 API 或發布 npm 套件。
203
229
 
204
- - 版本/歷史驗證、測試或 tarball 檢查失敗:不 publish;修復後走新版本 PR/Release,不改寫既有 tag。
205
- - 查 registry 失敗不是「版本不存在」。禁止在查證失敗時繼續發布。
206
- - 同版本存在時,只有 registry 的完整 sha512 integrity 與已驗證 tarball 相同才視為完成;不同則失敗,由維護者處理。重跑不強制覆蓋、不加版號、不無條件重送,不藉重跑調整 latest。
207
- - publish 失敗/連線中斷可能已成功;先保存 Actions artifact、receipt 與 log,再比對 registry。尚未能確認時不重送。稍後只在查證相同版本產物一致後才標示完成。
208
- - 工作流在唯一一次 npm 嘗試前,先保存 `publication-intent-<run_id>` artifact。Actions rerun 僅以原始 intent 查證 registry,絕不再次 publish;即使第一次停在發送之前,也不例外。原始 intent 缺失/過期/不符時拒絕重跑。確認前次完全未發布後,任何新的嘗試仍須維護者另行審核並建立新的正式 Release,不可盲目重建 Release。
209
- - 誤發採新修正版,或由維護者授權 `npm deprecate` 並說明原因;`unpublish` 不是常規 rollback。
230
+ - #10 help 繁體中文化:打包安裝檢查不再依賴英文 `Usage:` 文案;Linux 隔離安裝 tarball 後,`iap`/`itsaplan` 的 help、version 與無認證 doctor JSON 驗證通過,未發布 npm 套件或呼叫正式 API。
210
231
 
211
- 驗收邊界:本機政策測試可證明拒絕案例與 registry 比對邏輯,實際 Actions 觸發、OIDC、tag ruleset 與 registry 安裝驗證仍須推送工作流並完成上述人工設定後取得。不要為取得證據擅自建立 Release 或公開套件。
232
+ - PR #13 登入 review 調整:build、型別檢查與 48 個相關測試通過。實際 Node CLI/本機 fixture 驗證一般登入只印簡短結果、警告走 stderr、`--json` 保留完整 envelope;Linux TTY 驗證繁中提示、預設網址來源、手動覆寫成網頁網址後安全拒絕 307,且失敗不覆蓋已存 API 網址。未呼叫正式 API。
212
233
 
213
- ### 已執行驗證
234
+ - #7/#8/#9:build、型別檢查與 75 個相關測試通過。本機 HTTP fixture 驗證實際 CLI 的 redirect 拒絕、已存/生效身份、環境 key 缺 URL 時零請求、跨目錄預設專案及清除後保留認證;Linux TTY 實測登入衝突提示、取消與繼續儲存、隱藏 key 輸入。未呼叫正式 API,未據此宣稱 Windows/macOS 互動流程已實測。
214
235
 
215
- - #4 本機驗證:Node 24.22.1/npm 11.19.1/pnpm 12.14.0 的 frozen install、build、typecheck、146 個既有測試與 20 個發布政策/tarball 邊界測試通過;兩份 workflow YAML 解析通過。實際 tarball 從隔離暫存目錄安裝,`iap`/`itsaplan` 的 help、0.1.0 版本與無認證 doctor JSON 通過。未執行 npm publish 或建立 Release,未宣稱 Actions/OIDC 實測成功。
236
+ - 2026-11-11:以本機手動流程發布 `@dac-tech-team-tw/itsaplan-cli@0.1.0`;registry latest、metadata integrity、下載 tarball 與原始 receipt 一致。Linux 從 npm 安裝後,兩個 bin 的 help、version、無認證 doctor JSON 通過;發布前 build、typecheck、146 個既有測試與 20 個發布/tarball 測試通過。完整紀錄見 [DEPLOY.md](DEPLOY.md)。[main CI](https://github.com/dac-tech-team-tw/itsaplan-cli/actions/runs/42779451450) 已通過;未啟用或宣稱實測 OIDC 自動發布。
216
237
  - 本次 build、型別檢查及 113 個相關案例通過,涵蓋文件發布、文件/PR 關聯、權限/專案邊界、未知寫入結果、CLI stdin、重複關聯不重送及既有 issue/raw API/認證回歸路徑。
217
238
  - 部署中的公開 OpenAPI 1.10.0 已核對本次相關 request/response schema 與權限宣告,與本機 1.9.0 契約相容;未對正式環境做文件或關聯寫入,也未驗證使用者實際獲授的寫入權限。
218
239
  - Linux 從 `/tmp` 執行已安裝的 `iap document create --help`、`itsaplan issue link-pr --help`;本機 HTTP fixture 驗證實際 CLI 發布與關聯流程。