alp-code 0.9.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.
Files changed (204) hide show
  1. package/CHANGELOG.md +770 -0
  2. package/LICENSE +21 -0
  3. package/README.md +295 -0
  4. package/alp.config.yaml +5 -0
  5. package/dist/src/agents/agent-definition.js +28 -0
  6. package/dist/src/agents/capability-catalog.js +33 -0
  7. package/dist/src/agents/compaction.js +36 -0
  8. package/dist/src/agents/errors.js +12 -0
  9. package/dist/src/agents/librarian.js +38 -0
  10. package/dist/src/agents/main.js +37 -0
  11. package/dist/src/agents/memory-grant.js +29 -0
  12. package/dist/src/agents/model-context.js +70 -0
  13. package/dist/src/agents/modes.js +134 -0
  14. package/dist/src/agents/oracle.js +36 -0
  15. package/dist/src/agents/read-thread.js +38 -0
  16. package/dist/src/agents/registry.js +238 -0
  17. package/dist/src/agents/render-identity.js +38 -0
  18. package/dist/src/agents/review.js +37 -0
  19. package/dist/src/agents/search.js +37 -0
  20. package/dist/src/agents/shared/house-rules.js +33 -0
  21. package/dist/src/agents/shared/principal.js +18 -0
  22. package/dist/src/agents/shared/voice.js +29 -0
  23. package/dist/src/agents/titling.js +32 -0
  24. package/dist/src/agents/types.js +15 -0
  25. package/dist/src/backend/execution-backend.js +2 -0
  26. package/dist/src/backend/local-execution-store.js +144 -0
  27. package/dist/src/backend/local-process-backend.js +533 -0
  28. package/dist/src/backend/local-supervisor.js +104 -0
  29. package/dist/src/cli/alp.js +380 -0
  30. package/dist/src/cli/commands/context.js +203 -0
  31. package/dist/src/cli/commands/delegate.js +136 -0
  32. package/dist/src/cli/commands/identity-sync.js +31 -0
  33. package/dist/src/cli/commands/init.js +184 -0
  34. package/dist/src/cli/commands/mode.js +22 -0
  35. package/dist/src/cli/commands/principal.js +114 -0
  36. package/dist/src/cli/commands/run-main.js +90 -0
  37. package/dist/src/cli/commands/runtime.js +21 -0
  38. package/dist/src/cli/mode-preference-store.js +62 -0
  39. package/dist/src/cli/mode-selector.js +178 -0
  40. package/dist/src/cli/update-check.js +77 -0
  41. package/dist/src/context/checkpoint.js +134 -0
  42. package/dist/src/context/compact-journal.js +153 -0
  43. package/dist/src/context/compact-payload.js +121 -0
  44. package/dist/src/context/continuity.js +70 -0
  45. package/dist/src/context/types.js +2 -0
  46. package/dist/src/delegation/backend-registry.js +40 -0
  47. package/dist/src/delegation/delegation-service.js +300 -0
  48. package/dist/src/delegation/types.js +12 -0
  49. package/dist/src/execution/execution-policy.js +96 -0
  50. package/dist/src/execution/execution-service.js +115 -0
  51. package/dist/src/execution/execution-store.js +78 -0
  52. package/dist/src/execution/identity-capsule.js +65 -0
  53. package/dist/src/execution/types.js +12 -0
  54. package/dist/src/hooks/execution-bridge.js +84 -0
  55. package/dist/src/index.js +4 -0
  56. package/dist/src/memory/adapters/markdown-file-store.js +257 -0
  57. package/dist/src/memory/adapters/memory-api-client.js +2 -0
  58. package/dist/src/memory/adapters/memory-path-mapper.js +76 -0
  59. package/dist/src/memory/adapters/remote-api-store.js +25 -0
  60. package/dist/src/memory/context-ranker.js +21 -0
  61. package/dist/src/memory/errors.js +58 -0
  62. package/dist/src/memory/memory-service.js +149 -0
  63. package/dist/src/memory/memory-store.js +2 -0
  64. package/dist/src/memory/types.js +2 -0
  65. package/dist/src/policy/capability-policy.js +29 -0
  66. package/dist/src/policy/delegation-policy.js +25 -0
  67. package/dist/src/policy/errors.js +10 -0
  68. package/dist/src/policy/invariants.js +31 -0
  69. package/dist/src/policy/memory-policy.js +22 -0
  70. package/dist/src/policy/policy-engine.js +85 -0
  71. package/dist/src/policy/types.js +8 -0
  72. package/dist/src/policy/workspace-policy.js +77 -0
  73. package/dist/src/principal/principal-profile-store.js +89 -0
  74. package/dist/src/runtime/adapter-files.js +147 -0
  75. package/dist/src/runtime/claude-adapter.js +177 -0
  76. package/dist/src/runtime/codex-adapter.js +169 -0
  77. package/dist/src/runtime/permission-rules.js +156 -0
  78. package/dist/src/runtime/render-session-context.js +124 -0
  79. package/dist/src/runtime/render-task-input.js +33 -0
  80. package/dist/src/runtime/runtime-adapter.js +2 -0
  81. package/dist/src/runtime/runtime-preference-store.js +66 -0
  82. package/dist/src/runtime/runtime-selector.js +178 -0
  83. package/dist/src/runtime/types.js +2 -0
  84. package/dist/src/runtime/windows-shim.js +57 -0
  85. package/dist/src/state-paths.js +49 -0
  86. package/dist/src/workflow/output-validator.js +27 -0
  87. package/dist/src/workflow/repair-policy.js +8 -0
  88. package/dist/src/workflow/types.js +22 -0
  89. package/dist/src/workflow/workflow-runner.js +81 -0
  90. package/hooks/compact-record.cjs +109 -0
  91. package/hooks/session-boot.cjs +112 -0
  92. package/hooks/session-end.cjs +34 -0
  93. package/package.json +48 -0
  94. package/scaffold/memory/INDEX.md +27 -0
  95. package/scaffold/memory/README.md +76 -0
  96. package/scaffold/memory/projects/INDEX.md +22 -0
  97. package/scaffold/memory/projects/PROTOCOL.md +128 -0
  98. package/scaffold/memory/projects/_template/PROJECT.md +45 -0
  99. package/scripts/alp.cjs +126 -0
  100. package/scripts/alp.ps1 +4 -0
  101. package/scripts/alp.sh +3 -0
  102. package/scripts/bootstrap.cjs +144 -0
  103. package/scripts/checkout-release.cjs +30 -0
  104. package/scripts/delegate.cjs +19 -0
  105. package/scripts/doctor.cjs +158 -0
  106. package/scripts/doctor.sh +3 -0
  107. package/scripts/ensure-state.cjs +22 -0
  108. package/scripts/lib/cli-link.cjs +375 -0
  109. package/scripts/lib/codex-role.cjs +18 -0
  110. package/scripts/lib/delegation/command-runner.cjs +108 -0
  111. package/scripts/lib/delegation/config.cjs +81 -0
  112. package/scripts/lib/install-paths.cjs +154 -0
  113. package/scripts/lib/release-manifest.cjs +42 -0
  114. package/scripts/lib/semver-lite.cjs +20 -0
  115. package/scripts/lib/state.cjs +274 -0
  116. package/scripts/lib/uninstall.cjs +252 -0
  117. package/scripts/lib/update-check-worker.cjs +21 -0
  118. package/scripts/lib/update.cjs +395 -0
  119. package/scripts/run-role.cjs +42 -0
  120. package/scripts/run-role.ps1 +4 -0
  121. package/scripts/run-role.sh +3 -0
  122. package/scripts/sync-project-index.sh +167 -0
  123. package/skills/agent-memory/SKILL.md +109 -0
  124. package/skills/alp-debug/SKILL.md +90 -0
  125. package/skills/alp-debug/references/defense-in-depth.md +118 -0
  126. package/skills/alp-debug/references/investigation-methodology.md +106 -0
  127. package/skills/alp-debug/references/log-and-ci-analysis.md +96 -0
  128. package/skills/alp-debug/references/performance-diagnostics.md +112 -0
  129. package/skills/alp-debug/references/reporting-standards.md +120 -0
  130. package/skills/alp-debug/references/root-cause-tracing.md +134 -0
  131. package/skills/alp-debug/references/systematic-debugging.md +93 -0
  132. package/skills/alp-debug/references/verification.md +86 -0
  133. package/skills/alp-debug/scripts/find-polluter.sh +63 -0
  134. package/skills/alp-debug/scripts/find-polluter.test.md +102 -0
  135. package/skills/alp-plan/SKILL.md +128 -0
  136. package/skills/alp-plan/references/archive-workflow.md +77 -0
  137. package/skills/alp-plan/references/codebase-understanding.md +55 -0
  138. package/skills/alp-plan/references/output-standards.md +96 -0
  139. package/skills/alp-plan/references/plan-organization.md +129 -0
  140. package/skills/alp-plan/references/red-team-personas.md +76 -0
  141. package/skills/alp-plan/references/red-team-workflow.md +81 -0
  142. package/skills/alp-plan/references/research-phase.md +57 -0
  143. package/skills/alp-plan/references/scope-challenge.md +82 -0
  144. package/skills/alp-plan/references/solution-design.md +76 -0
  145. package/skills/alp-plan/references/validate-question-framework.md +89 -0
  146. package/skills/alp-plan/references/validate-workflow.md +83 -0
  147. package/skills/alp-predict/SKILL.md +98 -0
  148. package/skills/alp-scenario/SKILL.md +86 -0
  149. package/skills/code-review/SKILL.md +111 -0
  150. package/skills/code-review/references/code-review-reception.md +114 -0
  151. package/skills/code-review/references/edge-case-scouting.md +78 -0
  152. package/skills/code-review/references/verification-before-completion.md +117 -0
  153. package/skills/delegation/SKILL.md +46 -0
  154. package/skills/docs-seeker/.env.example +15 -0
  155. package/skills/docs-seeker/SKILL.md +87 -0
  156. package/skills/docs-seeker/package.json +25 -0
  157. package/skills/docs-seeker/references/advanced.md +82 -0
  158. package/skills/docs-seeker/references/context7-patterns.md +68 -0
  159. package/skills/docs-seeker/references/errors.md +72 -0
  160. package/skills/docs-seeker/scripts/analyze-llms-txt.js +211 -0
  161. package/skills/docs-seeker/scripts/detect-topic.js +172 -0
  162. package/skills/docs-seeker/scripts/fetch-docs.js +213 -0
  163. package/skills/docs-seeker/scripts/tests/run-tests.js +72 -0
  164. package/skills/docs-seeker/scripts/tests/test-analyze-llms.js +119 -0
  165. package/skills/docs-seeker/scripts/tests/test-detect-topic.js +112 -0
  166. package/skills/docs-seeker/scripts/tests/test-fetch-docs.js +84 -0
  167. package/skills/docs-seeker/scripts/utils/env-loader.js +94 -0
  168. package/skills/docs-seeker/workflows/library-search.md +73 -0
  169. package/skills/docs-seeker/workflows/repo-analysis.md +90 -0
  170. package/skills/docs-seeker/workflows/topic-search.md +69 -0
  171. package/skills/git/SKILL.md +121 -0
  172. package/skills/git/references/branch-management.md +90 -0
  173. package/skills/git/references/commit-standards.md +82 -0
  174. package/skills/git/references/gh-cli-guide.md +132 -0
  175. package/skills/git/references/safety-protocols.md +86 -0
  176. package/skills/git/references/workflow-commit.md +89 -0
  177. package/skills/git/references/workflow-merge.md +63 -0
  178. package/skills/git/references/workflow-pr.md +70 -0
  179. package/skills/git/references/workflow-push.md +62 -0
  180. package/skills/gkg/SKILL.md +87 -0
  181. package/skills/gkg/references/cli-commands.md +92 -0
  182. package/skills/gkg/references/http-api.md +99 -0
  183. package/skills/gkg/references/language-support.md +54 -0
  184. package/skills/problem-solving/SKILL.md +86 -0
  185. package/skills/problem-solving/references/attribution.md +48 -0
  186. package/skills/problem-solving/references/collision-zone-thinking.md +71 -0
  187. package/skills/problem-solving/references/inversion-exercise.md +88 -0
  188. package/skills/problem-solving/references/meta-pattern-recognition.md +80 -0
  189. package/skills/problem-solving/references/scale-game.md +82 -0
  190. package/skills/problem-solving/references/simplification-cascades.md +83 -0
  191. package/skills/problem-solving/references/when-stuck.md +76 -0
  192. package/skills/repomix/SKILL.md +94 -0
  193. package/skills/repomix/references/configuration.md +134 -0
  194. package/skills/repomix/references/usage-patterns.md +106 -0
  195. package/skills/repomix/scripts/.coverage +0 -0
  196. package/skills/repomix/scripts/README.md +179 -0
  197. package/skills/repomix/scripts/repomix_batch.py +455 -0
  198. package/skills/repomix/scripts/repos.example.json +15 -0
  199. package/skills/repomix/scripts/requirements.txt +15 -0
  200. package/skills/repomix/scripts/tests/test_repomix_batch.py +531 -0
  201. package/skills/research/SKILL.md +107 -0
  202. package/skills/security-scan/SKILL.md +101 -0
  203. package/skills/security-scan/references/secret-patterns.md +75 -0
  204. package/skills/security-scan/references/vulnerability-patterns.md +136 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,770 @@
1
+ # Changelog
2
+
3
+ Mọi thay đổi đáng chú ý của alp-code được ghi ở đây.
4
+
5
+ Định dạng theo [Keep a Changelog](https://keepachangelog.com/vi/1.1.0/); phiên bản theo
6
+ [Semantic Versioning](https://semver.org/lang/vi/). Mỗi mục `## [X.Y.Z]` tương ứng một tag
7
+ `vX.Y.Z` và một GitHub Release.
8
+
9
+ ## [Chưa phát hành]
10
+
11
+ ## [0.9.0] - 2026-09-07
12
+
13
+ ### Thêm
14
+
15
+ - **`npm i -g alp-code` — máy người dùng không build gì nữa.** Trước đây installer clone repo
16
+ rồi chạy `npm ci --include=dev` và `tsc` ngay trên máy người dùng. Cách đó bắt mọi người cài
17
+ phải có Git, phải tải toàn bộ devDependencies, và biến mỗi lần cài thành một lần build có thể
18
+ hỏng vì lý do chẳng liên quan gì tới ALP. Claude Code và Codex CLI đều không làm vậy, và
19
+ không có lý do gì ALP phải làm khác.
20
+
21
+ Từ bản này có hai kênh phát hành, cùng một cây file, khác nhau ở ai sở hữu thư mục cài:
22
+
23
+ | Channel | Cài bằng | Thư mục cài |
24
+ |---|---|---|
25
+ | `npm` (chính) | `npm i -g alp-code` | npm sở hữu, dưới `node_modules/` |
26
+ | `tarball` (dự phòng) | `install.sh` / `install.ps1` tải bundle của GitHub Release | `~/.alp-code/versions/<tag>`, `current` trỏ vào bản đang dùng |
27
+
28
+ Tarball tồn tại cho máy không có npm hoặc bị chặn registry, và nó mang sẵn dependency runtime
29
+ — giải nén ra là chạy, không `npm install` sau đó. Dev clone (`--branch`) là channel thứ ba
30
+ và là chỗ duy nhất còn build tại máy.
31
+
32
+ - **`scripts/pack-release.cjs`** dựng cả hai artifact trên máy maintainer, kiểm nội dung
33
+ (`scripts/lib/release-manifest.cjs`) rồi cố ý dừng trước `npm publish` và `gh release
34
+ upload` — giống `cut-release.cjs` dừng trước `git push`. `scripts/test-pack-release.cjs`
35
+ kiểm cùng hợp đồng đó ở mỗi lần chạy test, vì `files` trong `package.json` sai thì `npm pack`
36
+ vẫn xanh và lỗi chỉ lộ ra ở máy người dùng.
37
+
38
+ - **Giấy phép MIT.** `LICENSE` ở gốc repo và `"license": "MIT"` trong `package.json`.
39
+ Trước đây cả hai đều thiếu: npm hiển thị package là không có giấy phép, và người dùng không
40
+ có căn cứ nào để biết mình được phép làm gì với nó. `LICENSE` nằm trong danh sách file bắt
41
+ buộc của artifact nên nó đi theo mọi bản cài.
42
+
43
+ - **Hook forwarder `~/.alp/hooks/<tên>.cjs` và `scripts/ensure-state.cjs`.**
44
+ `<project>/.claude/settings.local.json` do `alp init` ghi nằm trong repo của người dùng và
45
+ sống lâu hơn mọi bản cài, nên nó phải trỏ vào một đường dẫn không đổi. Forwarder đọc
46
+ `~/.alp/install.json` để tìm bản cài hiện hành; project đã init từ trước được sửa lại tự
47
+ động. `ensure-state.cjs` chạy được như một tiến trình riêng vì sau update, tiến trình `alp`
48
+ đang chạy vẫn giữ code cũ trong RAM.
49
+
50
+ ### Thay đổi
51
+
52
+ - **Memory và toàn bộ state chuyển sang `~/.alp`; thư mục cài thành artifact thay được.**
53
+ Đây là điều kiện để bỏ được bước build: update giờ thay nguyên khối thư mục cài, nên bất cứ
54
+ thứ gì của người dùng còn nằm trong đó đều là dữ liệu hẹn ngày mất. `<thư mục cài>/memory`
55
+ được di trú sang `~/.alp/memory` ở lần chạy `alp` đầu tiên sau khi lên bản này, kèm một dòng
56
+ ghi chú để lại chỗ cũ. Di trú chỉ chạy khi chỗ mới chưa có dữ liệu thật, và không hàm nào
57
+ trong `state.cjs` được phép ghi đè nội dung đã có.
58
+
59
+ - **`alp update` đi theo channel của bản cài** — `npm install -g alp-code@<version>`, hoặc tải
60
+ bundle mới và đổi `current`, hoặc checkout tag rồi build (dev clone). Không còn bước
61
+ backup/restore memory nào cả: không có gì của người dùng nằm trong vùng bị thay nữa. Đường
62
+ tarball tải về staging rồi mới rename và trỏ lại `current`, nên tải hỏng để lại thư mục rác
63
+ chứ không để lại bản cài dở.
64
+
65
+ - **`alp uninstall` không còn xoá cả `~/.alp`.** Nó xoá đúng những tên do alp-code tạo
66
+ (`agents`, `hooks`, `executions`, `delegation`, `install.json`, `update-check.json`,
67
+ `mode.json`, `projects.json`) và không đụng vào thứ của người khác trong cùng thư mục.
68
+ Memory vẫn được chuyển sang backup cạnh `~/.alp` trừ khi có `--purge-memory`. Bản npm được gỡ
69
+ bằng `npm uninstall -g alp-code` thay vì `rm -rf` sau lưng npm; bản tarball gỡ cả
70
+ `~/.alp-code`.
71
+
72
+ - **`install.sh`/`install.ps1` viết lại quanh `--channel auto|npm|tarball`.** `auto` dùng npm
73
+ khi có, tự lùi về tarball khi npm thất bại. Cả hai không còn chạy `npm ci` hay `tsc`.
74
+ `bootstrap.cjs` chỉ build khi channel là dev clone, và bỏ qua bước link `alp` cho bản npm —
75
+ hai lệnh `alp` tranh nhau PATH thì lệnh của ta trỏ vào thư mục npm có quyền xoá.
76
+
77
+ - **`alp doctor` biết channel.** Bản phát hành được kiểm là còn đủ file artifact và install
78
+ record còn khớp; gợi ý sửa là `alp update` thay vì `npm run build`. Kiểm build drift chỉ còn
79
+ ý nghĩa với dev clone nên chỉ chạy ở đó.
80
+
81
+ - **`low` nâng `main` từ `claude-haiku-4-5 @ low` lên `claude-sonnet-5 @ high`.** `oracle` của
82
+ `low` giữ nguyên `gpt-5.6-sol @ high`, nên bất biến "oracle luôn ở runtime đối diện main"
83
+ vẫn giữ nguyên qua cả năm nấc.
84
+
85
+ ## [0.8.0] - 2026-09-06
86
+
87
+ ### Thêm
88
+
89
+ - **Dial công suất năm nấc: `alp --mode low|medium|high|ultra|puck`.** Trước đây mỗi vai chạy
90
+ đúng một model **cho mỗi runtime**, khai cứng trong definition, nên hai câu hỏi lúc mở phiên
91
+ là "chạy Claude hay Codex" và "sửa file nào để đổi model". Dial gộp cả hai thành thứ người
92
+ dùng thật sự biết: **việc này khó cỡ nào**. Mượn khuôn của Amp — `medium` mặc định — nhưng
93
+ chỉ dùng model Codex và Claude.
94
+
95
+ Mỗi nấc là một **loadout hoàn chỉnh**: mỗi vai đúng **một** model và một mức suy nghĩ.
96
+
97
+ | Nấc | `main` | effort | `oracle` | effort |
98
+ |---|---|---|---|---|
99
+ | `low` | claude-haiku-4-5 | low | gpt-5.6-sol | high |
100
+ | `medium` (mặc định) | gpt-5.6-sol | high | claude-opus-5 | high |
101
+ | `high` | claude-opus-5 | high | gpt-5.6-sol | xhigh |
102
+ | `ultra` | claude-opus-5 | high | gpt-6-astra | high |
103
+ | `puck` | gpt-5.6-sol | xhigh | gpt-5.6-sol | xhigh |
104
+
105
+ Bốn nấc dial chỉ xoay hai ghế mà độ khó chạm tới: `main` (người làm) và `oracle` (người được
106
+ hỏi khi bí). Sáu vai còn lại giống nhau qua cả bốn nấc — `search` gpt-5.6-terra, `librarian`
107
+ gpt-5.6-sol, `read-thread` và `titling` claude-haiku-4-5, `review` và `compaction`
108
+ claude-opus-5 — đúng chỗ Amp ghim cứng subagent: model của chúng là một phần công việc chứ
109
+ không phải một mức cố gắng. `oracle` luôn đứng ở runtime **đối diện** `main`: người được hỏi
110
+ khi bí phải là một cách nhìn khác, không phải cùng model tự hỏi lại chính nó. `high` và
111
+ `ultra` cùng cầm bút bằng Opus 5 — khác nhau ở oracle, nơi `ultra` leo lên model mới nhất
112
+ (`gpt-6-astra`) thay vì chỉ cộng thêm effort.
113
+
114
+ **`puck` nằm ngoài trục độ khó**: toàn Codex ở cả tám vai (`read-thread`/`titling` sang
115
+ gpt-5.6-luna, `review` sang gpt-5.6-terra). Dành cho máy chỉ cài `codex`, cho lúc hạn mức
116
+ Claude đã hết, hoặc cho người muốn đúng loadout Amp mặc định.
117
+
118
+ Chọn nấc theo thứ tự `--mode` → `ALP_MODE` → `alp mode set` (`~/.alp/mode.json`) → menu ↑/↓
119
+ trên TTY → `medium`. Nấc gõ sai (`--mode smart`) dừng ngay chứ không rơi về mặc định, vì một
120
+ phiên chạy nấc khác nấc người dùng tưởng là im lặng tốn tiền hoặc im lặng yếu đi. Nấc đi vào
121
+ `ExecutionPolicy.mode`, nên `policy.json` ghi lại nấc đã chạy và `policyHash` đổi theo nấc —
122
+ hai lần chạy khác model không thể trùng hash. `definitionHash` **không** đổi: nấc là lựa chọn
123
+ lúc phóng, không phải một vai khác. Adapter export `ALP_MODE` nên execution delegated kế thừa
124
+ nấc của phiên cha, thay vì subagent lặng lẽ tụt về `medium` giữa một phiên `ultra`.
125
+
126
+ **Đổi hành vi mặc định:** `main` trước đây là opus-5 (Claude) hoặc gpt-5.6-sol (Codex) @
127
+ high/xhigh. Mặc định mới `medium` cho `main` `gpt-5.6-sol` @ high — tức phiên mặc định giờ
128
+ chạy trên Codex CLI, không phải Claude Code. Muốn một phiên main do Claude cầm bút: `alp
129
+ --mode high|ultra` (Opus 5) hoặc `--mode low` (Haiku), hoặc `export ALP_MODE=ultra`.
130
+
131
+ Một test giữ điều kiện mọi model của mọi nấc đều có mặt trong cả `MODEL_RUNTIMES` lẫn
132
+ `MODEL_CONTEXT_WINDOWS` —
133
+ thiếu bảng đầu thì không biết phóng CLI nào, thiếu bảng sau thì ngưỡng auto-compact mặc định
134
+ (90% cửa sổ) lặng lẽ biến mất đúng ở nấc đó.
135
+
136
+ - **`alp mode show|set <nấc>`** — nấc ghi nhớ machine-local ở `~/.alp/mode.json` (0600, atomic
137
+ write), thay chỗ `alp runtime show|set` và `~/.alp/runtime.json`. Menu lúc mở phiên giờ hỏi
138
+ nấc chứ không hỏi runtime, mỗi dòng kèm một câu nói nấc đó dành cho việc gì. Preference hỏng
139
+ → warning + fallback `medium`, không throw. `alp update` bảo toàn `mode.json` qua các lần
140
+ cập nhật.
141
+
142
+ ### Thêm
143
+
144
+ - **Ba grant khai bằng tên: `capabilities.skills`, `capabilities.subagents`,
145
+ `capabilities.mcpServers`.** Một vai trước đây chỉ khai `tools`, nên `Skill` là một ô vuông
146
+ duy nhất: có hoặc không. Có nghĩa là mọi skill trên máy — kể cả cái vừa `git pull` về sáng
147
+ nay. Ba field mới nói tên cụ thể, và chỉ tên (§5.3): định nghĩa không được viết `command:`
148
+ hay đường dẫn, vì một file khai báo tự viết được egress của mình thì nó không còn là khai
149
+ báo nữa. Tên resolve đúng một lần, ở `createExecutionPolicy`, đối chiếu với catalog của
150
+ principal trong `src/agents/capability-catalog.ts`; **spec đã resolve** (command, args,
151
+ egress, prompt) mới là thứ đi vào snapshot. Nhờ vậy `policy.json` ghi lại lệnh thật sự đã
152
+ chạy chứ không trỏ vào machine config có thể đổi phía dưới.
153
+
154
+ Cả ba vào `definitionHash` **và** `policyHash`: nới một grant là đổi định danh của vai, y
155
+ như đổi `tools`.
156
+
157
+ - **Trần thi hành lúc registry load.** `UNKNOWN_SKILL`, `UNKNOWN_SUBAGENT`,
158
+ `UNKNOWN_MCP_SERVER` cho tên ngoài catalog; `DUPLICATE_GRANT` cho tên khai hai lần; và một
159
+ bất biến hai chiều — có `Skill` trong `tools` thì phải kể tên skill, kể tên skill thì phải
160
+ có `Skill` (`INVALID_SKILL_GRANT`). Chiều thứ nhất bắt được đúng hình dạng §5.5 cấm, và nó
161
+ đang tồn tại thật: sáu built-in cầm `Skill` mà không kể tên gì, tức trần bằng cả skill root
162
+ của máy. Subagent còn một trần nữa — `tools` của nó không bao giờ rộng hơn `tools` của vai
163
+ cấp nó (`UNKNOWN_TOOL`), vì subagent không phải đường vòng qua một giới hạn.
164
+
165
+ `SUBAGENT_CATALOG` và `MCP_SERVER_CATALOG` **rỗng** ở v1 (§5.5). Rỗng là mặc định
166
+ fail-closed chứ không phải chỗ trống chờ điền: khai bất cứ tên nào cũng bị từ chối ngay lúc
167
+ load. `SKILL_CATALOG` liệt kê 14 skill trong project scope, có test giữ đồng bộ với thư mục
168
+ `skills/`.
169
+
170
+ - **Policy engine trả lời được ba câu hỏi mới** — `SKILL_NOT_GRANTED`, `SUBAGENT_NOT_GRANTED`,
171
+ `MCP_SERVER_NOT_GRANTED` — và tự route tool name dạng `mcp__<server>__<tool>` về grant của
172
+ server đó. Route này nằm **sau** guardrail raw runtime tool, nên `mcp__paseo__spawn_agent`
173
+ vẫn dừng ở `RAW_RUNTIME_TOOL_DENIED` chứ không rơi xuống thành một câu hỏi về MCP.
174
+
175
+ - **Ba dòng mới trong bảng Authority** của session context: `Skills`, `Subagents`,
176
+ `MCP servers` — server in kèm egress (`docs (network egress)`), vì "được nối MCP nào" thực
177
+ chất là câu hỏi "cái gì rời khỏi máy này".
178
+
179
+ - **Harness test tier 2–3 cho agent** (`test/support/agent-dry-run.ts`): prepare một
180
+ execution thật, đọc argv, settings file, `mcp-config.json` và bảng Authority mà không chạy
181
+ runtime. Bộ test mới đi kèm phủ cả ba grant trên cả hai adapter.
182
+
183
+ - **`autoCompactTokens` — ngưỡng compact khai theo vai, theo từng model.** Trước bản này,
184
+ một execution ALP spawn ra nén transcript theo cửa sổ mặc định của runtime, tức theo cấu
185
+ hình của **máy** đang chạy chứ không theo vai đang chạy. Nhưng "còn nhớ được bao nhiêu" là
186
+ thuộc tính của vai: `main` giữ cả bức tranh nên phải giữ được tối đa model cho phép, còn một
187
+ `search` phình tới 150k token là đã hỏng — nén sớm là cách hỏng rẻ hơn.
188
+
189
+ Field mới nằm trên `AgentDefinition` như một **map theo runtime** — `{ claude?, codex? }`,
190
+ cùng khuôn với `model` và `reasoningEffort` — vì ngân sách này đi theo model chứ không theo
191
+ vai một mình: cùng một con số 500 000 là "nén sớm" trên cửa sổ 1M của opus-5, nhưng trên cửa
192
+ sổ 272k của gpt-5.6 thì transcript không bao giờ chạm tới, và runtime lặng lẽ rơi về chốt
193
+ cứng của nó (95% cửa sổ) — muộn hơn cả mặc định, trong khi argv vẫn in ra con số nói ngược
194
+ lại. Cả map vào `definitionHash` và `policyHash`; snapshot ghi đủ một khoá mỗi runtime, vì
195
+ policy viết ra trước lúc dispatch và chưa biết runtime nào sẽ chạy.
196
+
197
+ Dịch khác nhau ở hai runtime: Claude nhận `autoCompactWindow` trong settings file của
198
+ execution, Codex nhận `-c model_auto_compact_token_limit=` **trên argv** — cùng lý do với
199
+ hook và MCP, vì `codex-config.toml` là file ALP ghi chứ không phải file Codex đọc.
200
+
201
+ Ngân sách tám vai built-in (— là bỏ trống, nhận mặc định 90%):
202
+
203
+ | Vai | claude | codex | Thực nén ở (claude / codex) | Vì sao |
204
+ |---|---:|---:|---|---|
205
+ | `main` · `oracle` | — | — | 900 000 / 244 800 | Giữ tối đa model cho phép; suy luận trên cả tập bằng chứng |
206
+ | `librarian` · `review` | 300 000 | — | 300 000 / 244 800 | Doc nguyên văn, diff cộng code quanh nó; quá 300k trên cửa sổ 1M là đã đi lạc |
207
+ | `read-thread` | — | 200 000 | 180 000 / 200 000 | Thread hữu hạn; cửa sổ haiku-4-5 đúng bằng 200k nên phía Claude phải là mặc định |
208
+ | `search` · `compaction` | 150 000 | 150 000 | 150 000 / 150 000 | Không được phép phình; viết handoff chứ không gom corpus |
209
+ | `titling` | 100 000 | 100 000 | 100 000 / 100 000 | Sàn; một cái tiêu đề gần như không cần gì |
210
+
211
+ Trần thi hành lúc registry load, cho **từng phía**: số nguyên trong khoảng 100 000–1 000 000
212
+ **và** không vượt cửa sổ context của chính model phía đó, ngoài khoảng thì
213
+ `INVALID_AUTO_COMPACT_LIMIT`. Vế thứ hai là vế bắt được lỗi im lặng: khai vượt cửa sổ không
214
+ hỏng gì trông thấy, chỉ khiến vai nén **muộn hơn** mức nó tưởng. Chặn ở chỗ con số được viết
215
+ ra, chứ không clamp ở chỗ nó được đọc.
216
+
217
+ - **Vai không khai ngưỡng thì mặc định là 90% cửa sổ context của model đó.** Bỏ trống trước đây
218
+ nghĩa là "để runtime tự chọn", mà hai runtime chọn khác nhau: Codex nén ở 90% cửa sổ model,
219
+ Claude nén ở cửa sổ nó tự tune theo model và theo settings của **máy** đang chạy. Cùng một vai
220
+ lại nhớ được nhiều ít khác nhau tuỳ chỗ chạy — đúng cái phụ thuộc-vào-máy mà việc khai ngưỡng
221
+ sinh ra để chấm dứt. Nay ALP tự tính mặc định từ bảng `MODEL_CONTEXT_WINDOWS`
222
+ (`src/agents/model-context.ts`) và ghi ra cả hai runtime như một ngưỡng khai tường minh:
223
+
224
+ | Model | Cửa sổ | Mặc định (90%) |
225
+ |---|---:|---:|
226
+ | `claude-opus-5` · `claude-sonnet-5` | 1 000 000 | 900 000 |
227
+ | `claude-haiku-4-5` | 200 000 | 180 000 |
228
+ | `gpt-5.6-sol` · `gpt-5.6-terra` · `gpt-5.6-luna` | 272 000 | 244 800 |
229
+
230
+ Model không có trong bảng thì không có mặc định — runtime giữ cửa sổ của nó, vì để runtime
231
+ tự lo còn hơn dựng ngân sách từ phỏng đoán. Test giữ bảng phủ hết model mà tám vai built-in
232
+ route tới, và pin 90% của mọi cửa sổ trong bảng vẫn nằm trong khoảng Claude chấp nhận.
233
+
234
+ ### Đã bỏ
235
+
236
+ - **`--runtime`, `alp runtime show|set`, và `alp delegate --runtime`.** Từ khi mỗi vai ở mỗi
237
+ nấc chỉ có một model, **model quyết định runtime**: `claude-*` phóng Claude Code, `gpt-*`
238
+ phóng Codex CLI, tra qua bảng `MODEL_RUNTIMES` viết tay trong `model-context.ts` (không đoán
239
+ theo prefix — một tên lệch quy ước mà đoán sai thì phóng nhầm CLI trong im lặng). Giữ thêm
240
+ một lựa chọn runtime song song chỉ tạo ra tổ hợp vô nghĩa: `--runtime claude` cộng nấc
241
+ `medium` là yêu cầu Claude Code chạy `gpt-5.6-sol`.
242
+
243
+ Cả ba đường cũ **dừng với lỗi chỉ sang nấc**, không bị bỏ qua trong im lặng — một script cũ
244
+ còn `--runtime codex` sẽ nói ra rằng nó không còn ép được gì, thay vì chạy đúng nấc mặc định
245
+ mà người viết tưởng đang ép Codex. `DelegationExecutionOptions.runtime` cũng biến mất khỏi
246
+ request; `DelegationExecutionRecord.runtime` giữ nguyên, vì nó ghi lại CLI **đã thật sự
247
+ chạy**. Một nấc có thể trộn hai CLI trong cùng một phiên — `high` chạy `main` trên Codex và
248
+ `oracle` trên Claude — nên "runtime của phiên" không còn là một khái niệm có thật.
249
+
250
+ ### Thay đổi
251
+
252
+ - **Mọi delegated execution giờ chạy với `--mcp-config` tường minh cộng `--strict-mcp-config`.**
253
+ Trước bản này, một vai delegated kế thừa toàn bộ MCP config của máy — egress không policy
254
+ nào cho phép, không hash nào ghi lại. Giờ ALP ghi ra một file cho từng execution, rỗng
255
+ (`{"mcpServers":{}}`) khi vai không được cấp gì, và cờ strict cấm runtime đọc thêm chỗ khác.
256
+ Phiên interactive vẫn giữ config của máy, cùng đánh đổi đã ghi với
257
+ `--dangerously-skip-permissions`.
258
+
259
+ - **Codex nhận MCP qua `-c mcp_servers.<name>={ … }` trên argv**, không qua
260
+ `codex-config.toml`. Lý do là file đó Codex không đọc: nó đọc `$CODEX_HOME/config.toml`, thứ
261
+ ALP không ghi. Grant nào chỉ nằm trong file ấy là grant chỉ tồn tại trên giấy — hook đã đi
262
+ đường `-c` từ trước, MCP giờ đi cùng đường. Codex không có subagent in-process và không có
263
+ cờ strict tương đương; §4.6 đã ghi subagent là tối ưu hoá chứ không phải điều kiện, nên bên
264
+ Codex không dịch gì cả.
265
+
266
+ - **Claude ACL đổi từ deny-only sang có `allow`.** Skill được cấp vào allow list dạng
267
+ `Skill(<tên>)` thay vì deny từng skill không cấp — vì một tool name trần trong `deny` gỡ hẳn
268
+ tool khỏi context của model, nên "chỉ những skill này" bắt buộc phải viết bằng allow.
269
+ Subagent thành `Agent(<tên>)`, MCP server thành `mcp__<tên>`.
270
+
271
+ - **`Task` và `Agent` thật sự bị deny.** Vòng lặp deny chỉ chạy trên `TOOL_CATALOG`, mà hai
272
+ tool này không nằm trong đó — nên chúng chưa từng bị chặn dù không vai nào được cấp. `Task`
273
+ giờ luôn deny; `Agent` chỉ mở khi vai có subagent được cấp.
274
+
275
+ - **House rule tách theo audience.** Một vai đọc quy tắc của chính nó, không phải quy tắc của
276
+ vai khác; `InstructionOptions.audience` quyết định block nào được render.
277
+
278
+ - Review chuyển sang `gpt-5.6-terra` ở phía Codex (`docs/model-routing.md` cập nhật theo).
279
+
280
+ ### Sửa
281
+
282
+ - **Workspace root tương đối resolve theo từng request**, không còn theo `process.cwd()` lúc
283
+ policy được tạo. Một delegation phát đi từ thư mục khác trước đây nhận nhầm root.
284
+
285
+ - **Vai không có workspace root giờ prepare được.** `ExecutionService.prepare` vẫn hỏi câu
286
+ workspace cho cả vai chỉ đọc memory, nên `compaction` và `titling` chết ngay ở bước chuẩn
287
+ bị. `ExecutionPolicy` có thêm `workspaceAccess: "granted" | "none"` để phần còn lại của
288
+ chuỗi biết phân biệt "không được cấp" với "chưa resolve".
289
+
290
+ **Cần làm khi nâng cấp:** ba field mới là **bắt buộc** trên mọi `AgentCapabilities` — một
291
+ định nghĩa cũ không khai sẽ không compile. Vai không dùng skill khai `skills: []` và bỏ
292
+ `Skill` khỏi `tools`; vai có dùng thì kể tên, và tên phải có trong `SKILL_CATALOG`.
293
+ `subagents` và `mcpServers` khai `[]`, vì catalog của cả hai đang rỗng.
294
+
295
+ ## [0.7.0] - 2026-09-04
296
+
297
+ ### Thêm
298
+
299
+ - **Continuity qua compaction.** Claude Code và Codex CLI tự nén transcript khi hết context, và
300
+ cái bị nén đi trước tiên là những gì đã chốt từ sớm: objective, ràng buộc, quyết định đã cân
301
+ nhắc xong. ALP giờ giữ một checkpoint nhỏ **ngoài** transcript và trả nó lại ở `SessionStart`
302
+ ngay sau lần compact kế tiếp. Không copy native summary, không chèn synthetic turn — chỉ
303
+ đúng phần ALP tự biết là quan trọng vì chính agent hoặc principal đã pin nó.
304
+
305
+ ```bash
306
+ alp context status # objective, số pin, generation, restore mode
307
+ alp context pin decision -- "chose X over Y because Z"
308
+ alp context pin constraint -- "do not touch Z"
309
+ alp context unpin <pin-id>
310
+ alp context validate # kiểm checkpoint + journal
311
+ ```
312
+
313
+ `pin`/`unpin` chạy được cả từ CLI của principal lẫn từ trong một phiên agent — không có
314
+ execution ID trên dòng lệnh thì nó đọc `ALP_DELEGATION_EXECUTION_ID`. Bốn loại pin
315
+ (`decision`, `constraint`, `open-item`, `next-action`) tương ứng bốn mục trong bản chiếu
316
+ Markdown mà model đọc lại.
317
+
318
+ Checkpoint và `continuity.md` được seed ngay trong `ExecutionService.prepare()`, nên một
319
+ execution mới không bao giờ có continuity rỗng vì bị bỏ quên: riêng objective đã đáng
320
+ reinject. Cả hai nằm dưới `context/` trong execution root, ghi atomic như mọi artifact khác.
321
+
322
+ - **`ALP_COMPACT_BRIDGE=1`** bật phần ghi journal lúc `PreCompact`/`PostCompact`. Đây là phần
323
+ duy nhất opt-in; seed và reinject checkpoint chạy mặc định. Hook `hooks/compact-record.cjs`
324
+ không có dependency, chỉ append envelope đã lọc vào `context/compact-events.jsonl` — journal
325
+ append-only, replay ra được generation hiện tại và compaction nào đang dang dở.
326
+
327
+ Cái đi vào journal là **whitelist**, không phải blacklist. Payload đo thật ngày 2026-09-04
328
+ mang những trường không schema nào của binary khai báo (`context_tokens`,
329
+ `estimated_cache_write_usd`, `prompt_cache_likely_expired`, `seconds_since_last_response`),
330
+ và mang khác nhau tuỳ `source`; blacklist sẽ ghi hết chúng vào file ALP giữ lại.
331
+ `compact_summary` bị loại theo tên lẫn theo luật — đo được 22–32 KB, so với giới hạn 16 KiB
332
+ một dòng journal.
333
+
334
+ - Hai adapter khai báo `CompactCapabilities` đã ghim theo phiên bản CLI, và bridge chỉ bật
335
+ những event mà capability đó xác nhận. Thứ tự event **khác nhau giữa hai runtime** và ALP
336
+ không giả vờ là chúng giống nhau: Claude phát
337
+ `PreCompact → SessionStart(source="compact") → PostCompact` (reinjection nằm *trong* lúc
338
+ compact, nên `PostCompact` không phải chỗ an toàn để biết compaction đã xong), còn Codex
339
+ phát `PreCompact → PostCompact → SessionStart`.
340
+
341
+ ### Thay đổi
342
+
343
+ - Codex adapter nhận `hooksDirectory` tường minh trong `defaultDependencies` thay vì suy ra
344
+ ngầm từ `ALP_REPO_ROOT` — nó wire bốn hook thay vì hai kể từ bản này.
345
+
346
+ ## [0.6.0] - 2026-09-03
347
+
348
+ ### Đã gỡ
349
+
350
+ - **Backend Paseo, và cùng với nó là cả khái niệm "chọn backend".** ALP giờ chỉ chạy trên
351
+ `LocalProcessBackend`. Lý do là ACL: chỉ backend local trao cho runtime settings file của
352
+ chính vai đó, nên `permissions.deny` và `sandbox.filesystem.denyWrite` mới thật sự tới được
353
+ agent — đo ngày 2026-09-03, một `search` delegated đọc private memory của vai khác bị chặn ở
354
+ ba lớp độc lập. Backend spawn runtime qua daemon riêng không tái hiện được điều đó vì
355
+ permission request của nó không mang path. Giữ hai backend nghĩa là giữ một cấu hình cho
356
+ phép chọn bản yếu hơn.
357
+
358
+ Gỡ theo: `scripts/lib/delegation/backends/paseo/`, `CjsExecutionBackendAdapter`,
359
+ `BackendRegistry`, `resolveBackend` + fallback, cờ `--backend` (giờ bị **từ chối** chứ không
360
+ bị lờ đi, để một script cũ không âm thầm biến `--backend paseo` thành lời văn của task),
361
+ `alp init --backend`, `alp delegation switch`, `alp delegation health`, các khoá
362
+ `backends:`/`backend:`/`fallback_backend:` trong `alp.config.yaml`, biến môi trường
363
+ `ALP_DELEGATION_BACKEND`/`ALP_DELEGATION_FALLBACK`, và `scripts/lib/delegation/core/` —
364
+ cây type/store/error CJS không còn ai require sau khi backend đi.
365
+
366
+ `ExecutionBackend` vẫn là interface, vì test cần thay nó bằng fake; nó thôi là điểm mở
367
+ rộng. `DelegationService` nhận thẳng một backend thay vì một registry và một cái tên.
368
+
369
+ **Cần làm khi nâng cấp:** bỏ `--backend` khỏi mọi script gọi `alp delegate`/`alp init`, bỏ
370
+ hai biến môi trường trên khỏi shell profile, và xoá `backend:`/`fallback_backend:`/`backends:`
371
+ khỏi `alp.config.yaml` (chỉ `state_dir` còn được đọc). Execution cũ do Paseo sở hữu trong
372
+ `code-native-executions.json` không còn resolve được — lệnh lifecycle trên chúng trả
373
+ `EXECUTION_NOT_FOUND`; dọn bằng tay trong `state_dir`.
374
+
375
+ - **`RuntimeLaunchSpec.intent`.** Launch spec từng mang hai cách viết cùng một lần chạy: form
376
+ exec (`command`/`args`) và một form khai báo (`prompt`/`model`/`mode`) chỉ tồn tại vì backend
377
+ cũ tự spawn runtime và không exec được `command`. Hai adapter phải giữ chúng khớp nhau, mà
378
+ chỉ form exec là được thi hành — một permission mode đặt trong `args` là thật, cùng mode đó
379
+ đặt trong `intent` chỉ là lời đề nghị. Một cách viết thì mode một vai chạy dưới không thể
380
+ lệch khỏi mode policy của vai đó yêu cầu.
381
+
382
+ - Guardrail chặn agent tự gọi `paseo`/`herdr` **giữ nguyên**: regex trong
383
+ `src/policy/invariants.ts`, `Bash(paseo:*)` trong deny rule Claude và `[[rules]] allow = false`
384
+ bên Codex. Gỡ backend không có nghĩa là mở đường cho agent gọi thẳng binary.
385
+
386
+ ### Thay đổi
387
+
388
+ - `scripts/test-delegation-backends.cjs` → `scripts/test-delegation.cjs`. Contract sáu method
389
+ từng chạy hai lần, mỗi backend một lần, để chứng minh chúng thay thế được cho nhau; giờ chạy
390
+ một lần trên backend thật. Test workspace của caller được viết lại: thay vì một CLI Paseo giả,
391
+ nó che `codex` trên `PATH` bằng một runtime giả rồi đọc lại đúng thứ runtime nhận được.
392
+ - `scripts/lib/delegation/backends/command-runner.cjs` → `scripts/lib/delegation/command-runner.cjs`.
393
+ Thư mục `backends/` không còn backend nào.
394
+
395
+ ## [0.5.1] - 2026-09-03
396
+
397
+ ### Thay đổi
398
+
399
+ - **Đã kiểm chứng ALP chạy đúng trên Paseo 0.7.2.** Không có thay đổi hành vi nào — bản này chỉ
400
+ ghi lại kết quả đo. Trên daemon 0.7.2: `alp delegation health` báo đúng phiên bản, delegation
401
+ end-to-end trả kết quả khớp, execution kẹt ở permission prompt vẫn được báo `failed` kèm lý do,
402
+ và toàn bộ test xanh. Hai shape mà backend Paseo đọc không đổi so với 0.5.1 —
403
+ `inspect --json` vẫn trả `Status: running` cho agent đã dừng chờ duyệt trong khi vẫn mang
404
+ `PendingPermissions`, còn `permit ls --json` vẫn cắt `id` còn tám ký tự. Chạy được trên cả
405
+ 0.5.x lẫn 0.7.x, không cần nâng cấp.
406
+ - Bỏ ghim `0.5.x` trong hai comment giải thích vì sao vai Codex dùng mode `auto`: đã kiểm lại trên
407
+ 0.7.2, Paseo vẫn chỉ cho Codex `Default Permissions, Auto-review, Full Access`, không có
408
+ `read-only`. Lập luận giữ nguyên, chỉ ghi rõ đã kiểm tới bản nào.
409
+
410
+ ## [0.5.0] - 2026-09-03
411
+
412
+ ### Thêm
413
+
414
+ - **Vai được cấp quyền delegate giờ biết delegate bằng cách nào.** Bảng Authority in
415
+ `| Delegates to | search, librarian, … |` như một quyền hạn, nhưng không runtime nào có
416
+ tool delegation — `DelegationService` chỉ với tới được qua CLI `alp delegate`. Vai cầm
417
+ quyền đó tìm không ra tool nào khớp và **báo blocked**, đúng theo dòng "do not route around
418
+ it" ngay dưới bảng. Session context nay có mục `## Delegation` nêu thẳng cú pháp. Chỉ hiện
419
+ khi vai thật sự có `delegatesTo` và có `Bash` trong grant toàn phiên — không phải grant đã
420
+ bị lọc theo workflow state, vốn không có shell ở state mở màn của `main` và sẽ giấu mục này
421
+ suốt phiên.
422
+
423
+ ### Sửa
424
+
425
+ - **Delegation qua backend Paseo chưa từng nhận được task.** `paseo run` là
426
+ `run [options] <prompt>` và tự spawn runtime — CLI không có exec passthrough. ALP truyền
427
+ `-- claude --settings … "ALP task is in …"`, parser đọc `claude` làm prompt rồi vứt phần còn
428
+ lại. Mọi specialist thức dậy với đúng chữ `claude` làm việc phải làm, chạy model và
429
+ permission mode mặc định của Paseo thay vì của ALP. Identity vẫn tới nơi qua `--env` +
430
+ SessionStart hook, nên triệu chứng nhìn như treo chứ không như crash. `RuntimeLaunchSpec`
431
+ nay mang thêm `intent` — cùng một launch nhưng diễn đạt khai báo — và Paseo dịch nó thành
432
+ `--model`, `--mode` cùng prompt ở positional cuối. Spec không có prompt bị từ chối ngay tại
433
+ chỗ gọi, vì agent không tự báo được lỗi đó.
434
+ - **Execution kẹt ở permission prompt bị báo là đang chạy.** `paseo inspect` trả
435
+ `Status: running` cho agent đã dừng chờ duyệt; chỉ `paseo wait` gọi đúng tên `permission`,
436
+ mà `wait` thì block. `alp delegation status` nay đọc `PendingPermissions` có sẵn trong chính
437
+ response của `inspect`, và báo `failed` kèm lý do. Không ai trả lời được prompt đó: delegated
438
+ run chạy background.
439
+ - **Delegation đầu tiên vào một project mới luôn thất bại.** `paseo run` in
440
+ `Created workspace wks_… - <tên>` và một dòng `Tip:` **trước** JSON ở lần đầu nó đặt tên cho
441
+ workspace, còn ALP thì `JSON.parse` cả stdout. Lần sau qua được vì workspace đã tồn tại.
442
+ Nay parse bắt đầu từ `{` hoặc `[` đầu tiên.
443
+ - **Lý do thất bại bị nuốt trên đường về.** Backend sinh `error` từ lâu nhưng
444
+ `BackendExecutionResult` không khai báo trường đó, nên `DelegationService` không thể copy
445
+ thứ nó không biết — mọi thất bại tới tay người gọi dưới dạng `failed` trơ trọi. Đã khai báo
446
+ ở cả hai kiểu kết quả và propagate.
447
+ - **`alp delegation status` không còn làm mất output.** `wait` đọc transcript rồi lưu lại,
448
+ `status` thì không trả gì — poll sau khi `wait` là thấy output vừa nhận biến mất. Cả hai nay
449
+ đi qua một `transcript()` chung, `status` fallback về bản đã lưu khi Paseo không đọc được log.
450
+
451
+ ## [0.4.0] - 2026-09-03
452
+
453
+ ### Thêm
454
+
455
+ - **Tên principal và cách xưng hô không còn hard-code trong source.** `src/agents/shared/principal.ts`
456
+ từng giữ hằng `PRINCIPAL_CONTEXT = { name: "Lê Phúc Anh", … }`, nên tên một người đi vào
457
+ prompt của cả 8 vai ở mọi bản cài. Nay profile sống ở `~/.alp/principal.json` (0600, cạnh
458
+ `runtime.json`/`projects.json`) với ba trường: `name`, `addressAs` (agent gọi principal là
459
+ gì), `selfAs` (agent tự xưng là gì). `alp init` hỏi một lần khi profile chưa có **và** có
460
+ TTY, ghi xong mới sinh `.alp/agents/<role>.md` để tài liệu identity mang đúng tên. Không có
461
+ TTY thì init vẫn thành công, in `NOTE` gợi ý `alp principal set` và mọi vai dùng bản trung
462
+ tính `Serve the principal.` — không chặn CI, không đoán tên từ `git config`.
463
+ - **`alp principal show|set`.** `show` in profile và đường dẫn file (exit 1 khi chưa đặt);
464
+ `set` hỏi lại ba câu, ghi đè, rồi chạy luôn `identity sync` để `.alp/agents/` không giữ tên
465
+ cũ. Giá trị nhập vào bị gộp khoảng trắng, cấm rỗng và giới hạn 60 ký tự — chúng được nội
466
+ suy thẳng vào prompt nên một ký tự xuống dòng sẽ lặng lẽ thành một dòng chỉ thị mới.
467
+
468
+ ### Sửa
469
+
470
+ - Bỏ hai trường chết `PRINCIPAL_CONTEXT.language` và `.timezone`: không nơi nào đọc chúng, và
471
+ `"Vietnamese"` thực ra là literal viết cứng lần thứ hai ngay trong câu instruction.
472
+
473
+ ## [0.3.2] - 2026-09-03
474
+
475
+ ### Sửa
476
+
477
+ - **Hook của Codex vẫn hỏng trên Windows sau v0.3.1 — chẩn đoán trước đó sai nguyên nhân.**
478
+ Đo lại trên `codex-cli 0.153.0` (bản native `codex.exe`, cài qua winget) bằng cách nhét
479
+ nhiều cách viết lệnh vào cùng một mảng `hooks.SessionStart` rồi xem cách nào thật sự chạy:
480
+ Codex **tự tách argv**, nó không đưa chuỗi qua `cmd /C`. Luật thật là *token đầu tiên không
481
+ được bọc nháy* — mọi lệnh bắt đầu bằng `"` đều báo `hook: SessionStart Failed`, không in gì.
482
+ Nên cả `"<node>" "<script>"` lẫn dạng thêm một cặp nháy `""<node>" "<script>""` mà v0.3.1
483
+ phát hành đều hỏng như nhau; đường dẫn có dấu cách chỉ là điều kiện đủ, không phải nguyên
484
+ nhân. Đã đo: `<node> "<script>"`, `node "<script>"`, `C:\PROGRA~1\…\node.exe "<script>"` và
485
+ `cmd /c "<node>" "<script>"` chạy được; `"C:\PROGRA~1\…\node.exe" "<script>"` (không dấu
486
+ cách, chỉ có nháy đầu) thì hỏng. Nay interpreter đi vào trần: dùng thẳng `process.execPath`
487
+ khi nó không có dấu cách, còn khi có — `C:\Program Files\nodejs\node.exe`, tức bản cài mặc
488
+ định — thì dùng `node` trên PATH, đúng thứ mà shim `alp.cmd` lúc cài vốn đã phụ thuộc. Đường
489
+ dẫn script vẫn được bọc nháy vì nó có thể chứa dấu cách. Kiểm chứng end-to-end: session
490
+ context tới được model (agent trả đúng role id đặt trong file context) thay vì tự xưng là
491
+ "Codex". Claude Code vẫn giữ dạng cũ — nó spawn qua `cmd /d /s /c "<lệnh>"` và dạng bọc nháy
492
+ là dạng đang chạy đúng ở đó.
493
+
494
+ ## [0.3.1] - 2026-09-03
495
+
496
+ ### Sửa
497
+
498
+ - **Hook của Codex không chạy trên Windows, nên phiên Codex không có identity.** Cả hai hook
499
+ báo `hook exited with code 1` và không in gì; agent tự xưng là "Codex" thay vì role của nó.
500
+ Nguyên nhân nằm ở shell: Codex chạy hook qua `cmd.exe /C` trần, mà shell này có luật — dòng
501
+ lệnh bắt đầu bằng dấu nháy và mang hơn hai dấu nháy thì nó **xoá dấu nháy đầu và cuối** rồi
502
+ chạy phần còn lại. Chuỗi `"<node>" "<script>"` vì thế tới nơi thành
503
+ `C:\Program Files\…\node.exe" "…\session-boot.cjs`, bị cắt ở dấu cách đầu tiên, và cmd báo
504
+ `'C:\Program' is not recognized`. Chỉ xảy ra khi đường dẫn node có dấu cách — cài mặc định
505
+ vào `C:\Program Files\nodejs` là dính. Bọc thêm một cặp nháy quanh cả chuỗi là cách xử lý
506
+ có tài liệu: cmd bóc đúng cặp nó định bóc, lệnh bên trong còn nguyên. Claude Code **không**
507
+ nhận thay đổi này: nó spawn qua `cmd /d /s /c "<lệnh>"`, mà `/s` đã ăn sẵn một cặp nháy
508
+ ngoài, nên thêm cặp nữa sẽ làm hỏng đúng cái đang chạy tốt.
509
+
510
+ ### Thay đổi
511
+
512
+ - **`alp update` in gọn lại.** Trước đây nó xả toàn bộ output của `git fetch`, `git checkout`
513
+ và `npm ci` + build. Nay còn ba dòng: bản cũ → bản mới, một dòng báo đang build, một dòng
514
+ kết quả. Output của lệnh con được capture chứ không bỏ đi, nên khi hỏng thì thông báo lỗi
515
+ còn rõ hơn trước — `commandFailure` đọc đúng stream đó. `alp update --verbose` trả lại toàn
516
+ bộ output, cần khi build hỏng và phải nhìn lỗi thật.
517
+
518
+ ## [0.3.0] - 2026-09-03
519
+
520
+ ### Thay đổi
521
+
522
+ - **Mở phiên interactive không còn tốn một lượt trả lời.** Gõ `alp` trước đây là agent đáp ngay
523
+ trước khi principal kịp gõ gì — và thứ nó đáp lại là một task không có thật, vì phiên interactive
524
+ chưa có task nào cho tới khi principal gửi. Nguyên nhân không nằm ở chữ trong prompt: session
525
+ context và task input có vòng đời khác nhau nhưng đi chung một kênh. Nay tách hai:
526
+ `session-context.md` mô tả agent cho cả phiên (identity, quyền hạn thực tế, invariants, policy,
527
+ reporting contract) và không bao giờ tạo lượt; `task.md` mang memory đã chọn cùng task, và **chính
528
+ là** lượt đầu tiên. Phiên interactive không sinh `task.md`, nên không còn gì để adapter lỡ tay đưa
529
+ thành positional prompt. Delegated execution không đổi: vẫn submit task đúng một lần.
530
+ - **Codex nhận identity qua `SessionStart` hook, giống Claude.** Đo trên `codex-cli 0.149.0`: hook
531
+ chạy đúng một lần và `additionalContext` vào transcript thành message `role: developer`, **trước**
532
+ lượt của người dùng. Ghi nhận cũ "Codex báo `SessionStart Failed`" đã lỗi thời, nên mục
533
+ `## Identity` thừa trong prompt Codex bị gỡ — một kênh cho mỗi runtime, nếu không identity vào
534
+ context hai lần. Hệ quả thấy được: cả hai runtime nay nhận file session context byte-identical, và
535
+ phiên interactive biết rõ workspace, invariants, policy trước câu hỏi đầu tiên — trước đây những
536
+ thứ này chỉ đến qua prompt, tức là qua lượt giả.
537
+ - **Phiên `alp` interactive chạy không guardrail.** Claude nhận `--dangerously-skip-permissions`,
538
+ Codex nhận `--dangerously-bypass-approvals-and-sandbox`. Principal ngồi ngay đó và tự duyệt được
539
+ từng bước, nên prompt quyền chỉ là ma sát. Đánh đổi ghi rõ trong `docs/architecture.md`: cờ này vô
540
+ hiệu hoá `permissions.deny` (Claude) và sandbox (Codex) **cho riêng phiên đó**, gồm cả cách ly
541
+ private memory giữa các role. Nó không phải công tắc toàn cục — chỉ `run-main` đặt
542
+ `interactive: true`, còn `alp delegate` luôn `false`, nên mọi delegated execution giữ nguyên deny
543
+ list, sandbox và bất biến read-only. Ở Codex, `-s` bị bỏ hẳn khi bypass thay vì để lẫn: Codex
544
+ nhận cả hai mà không báo lỗi và cờ bypass thắng, nên giữ `-s` chỉ để lại một tham số nói sai về
545
+ chế độ đang chạy.
546
+
547
+ ### Thêm
548
+
549
+ - `CODE_CRAFT_RULES` trong `src/agents/shared/house-rules.ts` — bốn quy tắc tay nghề phỏng theo
550
+ [ghi chép của Andrej Karpathy](https://x.com/karpathy/status/2015883857489522876) về các lỗi
551
+ code thường gặp của LLM: nêu giả định thay vì hành động theo nó, chọn lời giải nhỏ nhất, sửa
552
+ đúng phạm vi được yêu cầu, biến task thành một check chạy được. Chỉ spread vào `main`,
553
+ `review`, `oracle` là các vai viết hoặc phán xét code; `search`, `librarian`, `read-thread`,
554
+ `compaction`, `titling` không nhận vì không hành động theo được.
555
+ - `docs/orchestrator-vision.md` — đề xuất role built-in thứ 9 `orchestrator`, điều phối nhiều
556
+ execution dài chạy song song trên workspace tách biệt (mô hình orchestration của Paseo). Ghi rõ ba
557
+ ràng buộc: nó phải là built-in vì `delegatesTo` khác rỗng mà §5.5 chốt custom agent là lá; nó
558
+ **không** được miễn trừ khỏi invariant cấm `create_agent`/`paseo` — cái phải lớn lên là
559
+ `DelegationService`, không phải danh sách ngoại lệ; và §4.10 (budget, cancellation, trace) phải
560
+ xong trước, vì orchestrator thiếu hai thứ đó là fork bomb kèm file policy. Doc triết lý giữ §5.9
561
+ làm đoạn trỏ sang, cùng một dòng điều kiện mở khoá trong bảng hoãn §8.
562
+
563
+ ### Sửa
564
+
565
+ - `docs/alp-design-philosophy-and-vision.md` viết trước v0.2.0 nên còn mô tả thế giới cũ: backend
566
+ Herdr, `hooks/acl-guard.cjs`, `instructions: (context) =>`, và output `kind: json`. Nay bám đúng
567
+ code hiện tại. Hai chỗ đáng chú ý hơn sửa chữ: §5.4 đổi tiền đề — output JSON đã bị gỡ khỏi cả 8
568
+ role nên `kind: text` là lựa chọn duy nhất cho custom agent v1; và §5.7 phải sống chung với việc
569
+ v0.2.0 đã chiếm trước `.alp/agents/` bằng file phẳng `<role>.md`, nên custom agent trùng tên
570
+ built-in role phải bị từ chối lúc load.
571
+ - `docs/delegation.md` còn nói `acl-guard.cjs` kiểm raw-runtime target — hook đó đã bị gỡ; việc kiểm
572
+ nằm ở `src/policy/invariants.ts` cộng deny rule khai báo của từng runtime.
573
+ - `docs/model-routing.md` còn nói adapter "có thể dùng Herdr hoặc Paseo".
574
+
575
+ ## [0.2.0] - 2026-09-02
576
+
577
+ ### Thay đổi
578
+
579
+ - **Role trả lời bằng văn xuôi, không còn JSON.** Trước đây `renderCapsulePrompt` nhét
580
+ JSON Schema (sinh từ Zod) vào prompt và Stop hook trả `{"decision":"block"}` khi output
581
+ không parse được — nên mọi phiên, kể cả phiên `main` nói chuyện trực tiếp với principal,
582
+ đều đáp lại bằng một cục JSON. Cả 8 role nay dùng contract `textOutput` vốn đã có sẵn
583
+ trong `shared/voice.ts`; chỉ chuỗi rỗng bị từ chối. Không consumer nào đọc field lẻ nên
584
+ giữ schema cho specialist không mang lại gì.
585
+ - **Identity vào context qua `SessionStart` hook thay vì con trỏ trong `prompt.md`.**
586
+ `hooks/session-boot.cjs` đọc đúng một file `.alp/agents/<role>.md` phẳng và không
587
+ `require()` gì từ `dist/` (~45ms). Trước đó agent phải đốt một tool call `Read` trước khi
588
+ làm bất cứ việc gì. Hook fail-open: lỗi thì trả context rỗng kèm cảnh báo, vì phiên thiếu
589
+ identity còn cứu được còn phiên bị chặn thì không.
590
+ - **ACL chuyển từ chặn từng tool call sang khai báo trong runtime config.** Claude nhận
591
+ `permissions.{additionalDirectories,deny}`; Codex nhận `[sandbox_workspace_write]` và
592
+ `[[rules]]`. `hooks/acl-guard.cjs` spawn một process Node và load `dist/` cho **mọi** tool
593
+ call — đây là nửa còn lại của việc boot chậm.
594
+ - `AgentDefinition.instructions` không còn nhận tham số. Identity vì thế giống hệt nhau
595
+ giữa các execution, điều kiện để render một lần ra file cho hook đọc; workspace và task
596
+ chuyển sang prompt của từng execution.
597
+ - Backend mặc định là `paseo`. `fallback_backend` cố ý để trống: âm thầm nhảy sang backend
598
+ khác khi backend chính có vẻ unhealthy thì khó chẩn đoán hơn là fail rõ ràng — chọn
599
+ `local` tường minh bằng `alp delegation switch local`.
600
+
601
+ ### Thêm
602
+
603
+ - `alp identity sync` — render identity của cả 8 role ra `.alp/agents/<role>.md` (mode 0600).
604
+ `alp init` cũng gọi tự động và cài `SessionStart` hook vào `.claude/settings.local.json`
605
+ của project, loại trừ qua `.git/info/exclude` nên `git status` của project không đổi.
606
+
607
+ ### Sửa
608
+
609
+ - `LocalProcessBackend` không spawn được runtime cài qua npm trên Windows: Node từ chối
610
+ chạy thẳng `.cmd`/`.bat`, nên `alp run` và `alp delegate` đều chết với `EINVAL` khi gặp
611
+ `claude.cmd`/`codex.cmd`. Bản cài native (`.exe`) không dính, nên lỗi này lọt lâu.
612
+ `shell: true` không phải cách sửa ở đây — cmd.exe sẽ diễn giải lại tham số prompt vốn
613
+ chứa dấu cách và dấu nháy; `resolveSpawnCommand` đọc shim, lấy ra script Node bên trong
614
+ rồi spawn trực tiếp, argv qua nguyên vẹn.
615
+ - `hookCommand` quote bằng `JSON.stringify` — sai loại: nó escape backslash chứ không quote
616
+ shell, nên path Windows nằm trong settings.json dưới dạng `C:\\Users\\…`.
617
+ - `scripts/test-cli-link.cjs` **xoá `node_modules` của chính repo**. Nó chạy `bootstrap.cjs`
618
+ với `cwd` trỏ vào repo này, nhưng bootstrap lấy root từ `__dirname` nên `cwd` vô tác dụng;
619
+ bước đầu của bootstrap là `npm ci`, lệnh này xoá `node_modules` trước khi cài lại, và với
620
+ `npm_config_offline` bật cứng thì chỉ cần cache thiếu một tarball là bỏ lại checkout rỗng.
621
+ Nay bootstrap trên một bản copy tạm và spawn `bootstrap.cjs` của chính bản copy đó.
622
+ - `alp delegate --runtime claude` chết ngay lúc khởi động trên Windows: adapter xin sandbox
623
+ kèm `failIfUnavailable` nhưng Claude Code không kích hoạt filesystem sandbox trên nền tảng
624
+ này. Nay chỉ xin sandbox ở nơi cấp được, và bù lại bằng cách rút `Bash` khỏi role read-only
625
+ — mất shell chứ không mất bất biến read-only.
626
+ - Phiên Codex không nhận được identity: cùng `session-boot.cjs` chạy tốt trên Claude Code lại
627
+ bị Codex báo `SessionStart Failed`. Prompt của Codex mang thêm mục `## Identity`; Claude
628
+ Code vẫn đi đường hook.
629
+ - Test suite chạy được thật trên Windows. Harness e2e ghi fake runtime là script `#!` không
630
+ đuôi và ghim adapter vào `platform: "linux"` — cả sáu test e2e chết ở `spawn ENOENT` và
631
+ không phủ gì; bốn assertion `mode & 0o777` không thể pass vì Windows không có POSIX
632
+ permission bit; và `rm` recursive trên thư mục temp mới tạo trả `ENOTEMPTY` đủ thường để
633
+ khoảng một nửa số lần chạy đỏ ở `afterEach`, mỗi lần một test khác nhau.
634
+ - …và chạy được cả trên macOS/Linux: assertion về deny rule của Claude tự chép lại format
635
+ thay vì gọi hàm sinh ra nó, nên nối `//` vào một path POSIX vốn đã có `/` đầu và kỳ vọng
636
+ ba dấu gạch. Nó chỉ xanh trên Windows, nơi `C:\…` không có gạch đầu để cộng dồn.
637
+ `absoluteRule` nay được export và test gọi thẳng, kèm assertion ghim format cho cả hai
638
+ nền tảng. Deny list sinh ra không đổi.
639
+
640
+ ### Gỡ
641
+
642
+ - Backend Herdr (`scripts/lib/delegation/backends/herdr/`, `herdr-fleet.cjs`, skill
643
+ `herdr`). `LocalProcessBackend` nay luôn được register — nó không cần daemon, nên là
644
+ backend giữ cho delegation chạy được trên máy chưa cài gì. Regex chặn `herdr`/`paseo`
645
+ trong `src/policy/invariants.ts` giữ nguyên làm defense-in-depth.
646
+ - Cụm CJS delegation đã chết: `create-service`, `index`, `init-backend`, `runtime-installer`,
647
+ `core/{backend,backend-registry,context-builder,logger,policy,role-registry,service}`,
648
+ `testing/fake-backend` và `scripts/lib/delegation.cjs`. Composition root thật chỉ load 6
649
+ file từ thư mục này lúc chạy; phần còn lại đã được TypeScript trong `src/` thay thế và chỉ
650
+ còn test của chính nó gọi tới. Thư mục từ 18 file còn 6.
651
+ - Skill `delegation-switch` — lệnh `alp delegation switch` mà nó bọc thì giữ nguyên.
652
+ - Đoạn docs mô tả `alp init` hỏi và tự cài runtime: `alp init` chỉ ghi backend đã chọn vào
653
+ `~/.alp/projects.json` và không cài gì, nên prompt tương tác và bước
654
+ `npm install -g @getpaseo/cli` được tả trong docs là một flow không còn tồn tại.
655
+
656
+ **Mất mát phải chấp nhận, ghi trong `docs/architecture.md`:** ACL khai báo không diễn đạt
657
+ được ba thứ mà hook cũ cưỡng chế — guardrail `hasIndirectCommand` (`$(...)`, `eval`,
658
+ `bash -c`, `xargs`), tool gating theo workflow state, và cách ly private-memory phía **đọc**
659
+ trên Codex (sandbox của nó chặn ghi, không chặn đọc). `PolicyEngine` vẫn chạy lúc prepare.
660
+
661
+ ## [0.1.4] - 2026-08-28
662
+
663
+ ### Sửa
664
+
665
+ - `RuntimeAdapter.probe()`/`prepare()` của Claude và Codex hardcode đuôi `claude.cmd`/
666
+ `codex.cmd` trên Windows, chỉ khớp bản cài qua npm. Bản cài qua winget/native installer
667
+ (vd. `claude.exe`) đã có sẵn trên PATH và chạy tốt — kể cả chính phiên Claude Code đang
668
+ gõ commit này — nhưng `alp doctor`/`alp` vẫn báo "not found". Thêm
669
+ `resolveRuntimeCommand()` resolve theo PATHEXT thay vì hardcode một đuôi.
670
+
671
+ ## [0.1.3] - 2026-08-28
672
+
673
+ ### Sửa
674
+
675
+ - `install.ps1`: chuỗi lỗi `"$target: checkout release thất bại…"` khiến PowerShell parse
676
+ `$target:` như scope qualifier (giống `$env:`), làm `irm .../install.ps1 | iex` gãy ngay ở
677
+ bước parse trước khi script kịp chạy. Đổi thành `${target}:`.
678
+ - `bootstrap.cjs`/`alp.cjs`/`run-role.cjs`/`delegate.cjs`: gọi thẳng
679
+ `spawnSync("npm.cmd", …)` ăn `EINVAL` trên các bản Node đã vá CVE-2024-27980 (chặn spawn
680
+ `.cmd`/`.bat` khi không có `shell: true`), khiến `npm ci`/`npm run build` gãy trên Windows —
681
+ gồm cả installer một dòng. Route qua `spawnSyncCommand` (đã có sẵn cho delegation backends,
682
+ resolve `npm.cmd` về `npm-cli.js` rồi spawn Node trực tiếp) thay vì tự viết lại yếu hơn.
683
+ - `cut-release.cjs` không cắt được release trên working tree CRLF (vd. Windows với
684
+ `core.autocrlf=true`): `text.indexOf(UNRELEASED + "\n")` không khớp dù nội dung committed
685
+ luôn là LF. Chuẩn hoá CRLF→LF khi đọc CHANGELOG.md trước khi so khớp.
686
+
687
+ ## [0.1.2] - 2026-08-27
688
+
689
+ ### Sửa
690
+
691
+ - `alp update` chạy được trở lại. Từ 0.1.0, `scripts/alp.cjs` gọi `updateInstallation` đồng bộ
692
+ trong khi hàm này đã thành async, nên đọc `result.ok` trên một Promise luôn ra `undefined`:
693
+ lệnh in `ERROR undefined`, thoát 1 và **không update gì cả**. Nay await đúng Promise, in cả
694
+ tag vừa checkout. Thêm test chạy thật `alp.cjs update` để khoá hợp đồng async này.
695
+ - `alp help` không còn bảng hardcode riêng trong `alp.cjs` lệch với `helpText()` — nay hiện
696
+ đủ, gồm `alp --version`.
697
+
698
+ ## [0.1.1] - 2026-08-27
699
+
700
+ ### Sửa
701
+
702
+ - `cut-release.cjs` bump cả `package-lock.json`, không chỉ `package.json`. Trước đó hai file
703
+ lệch version sau mỗi lần cắt release mà `git status` vẫn sạch nên không có gì báo động.
704
+
705
+ ### Gỡ
706
+
707
+ - Bỏ `.github/workflows/release.yml`. Release nay publish bằng `gh release create` từ máy
708
+ maintainer. Workflow không chạy khi cắt `v0.1.0` vì nó vừa được thêm trong chính cú push
709
+ mang tag, và với một maintainer dùng `gh` sẵn thì nó chỉ thêm một bộ phận async có thể im
710
+ lặng hỏng. Bất biến `tag == package.json.version` vẫn do `cut-release.cjs` giữ lúc tạo tag.
711
+
712
+ ## [0.1.0] - 2026-08-27
713
+
714
+ Bản release đánh số đầu tiên. Trước mốc này alp-code chưa có version, chưa có tag, và
715
+ `alp update` fast-forward thẳng nhánh `main`.
716
+
717
+ ### Thêm
718
+
719
+ - Version là nguồn sự thật duy nhất trong `package.json`; `alp --version` / `alp -v` in
720
+ phiên bản đang cài.
721
+ - Phát hành qua git tag + GitHub Release: `.github/workflows/release.yml` chạy trên tag
722
+ `v*.*.*`, verify tag khớp `package.json.version` rồi publish release kèm auto-generated
723
+ notes.
724
+ - Kiểm tra bản mới ở nền mỗi lần chạy `alp`: cache tại `~/.alp/update-check.json` với TTL
725
+ 24h, network chạy trong detached child process nên không bao giờ chặn lệnh hiện tại. Có
726
+ bản mới thì chỉ in một dòng gợi ý `alp update` — không tự cập nhật, không hỏi lại. Đặt
727
+ `ALP_SKIP_UPDATE_CHECK=1` để tắt.
728
+ - `scripts/checkout-release.cjs` — resolve và checkout tag release, dùng chung bởi
729
+ installer và `alp update`.
730
+ - Ghim phiên bản khi cài: `--version <tag>` / `ALP_VERSION` (bash) và `$env:ALP_VERSION`
731
+ (PowerShell).
732
+
733
+ ### Thay đổi
734
+
735
+ - `alp update` và installer chuyển hẳn sang release-based: resolve tag GitHub Release mới
736
+ nhất (`api.github.com/.../releases/latest`, fallback `git ls-remote --tags` khi API không
737
+ tới được) rồi `git checkout --detach <tag>`, thay cho `git pull --ff-only` trên `main`.
738
+ Guarantee cũ giữ nguyên: từ chối khi working tree còn thay đổi chưa commit, và backup/khôi
739
+ phục `memory/`, runtime preference, backend preference quanh mỗi lần update.
740
+ - `--branch` / `ALP_BRANCH` không còn mặc định là `main`. Giờ đây nó là escape hatch tường
741
+ minh cho dev: bỏ qua release resolution và theo dõi trực tiếp một nhánh (hành vi
742
+ fast-forward pull như cũ).
743
+
744
+ ### Nền tảng sẵn có tính đến 0.1.0
745
+
746
+ - Agent registry code-native (`main`, `search`, `librarian`, `read-thread`, `review`,
747
+ `oracle`, `compaction`, `titling`) với `PolicyEngine` fail-closed trước mọi delegation,
748
+ memory operation, workspace access và tool request.
749
+ - Hai runtime adapter Claude/Codex sinh launch spec; backend Herdr/Paseo chỉ quản lifecycle.
750
+ - `MemoryService`/`MemoryStore` storage-neutral với adapter Markdown và remote API.
751
+ - `alp init`/`alp deinit`, `alp delegate`, `alp doctor`, `alp uninstall`, installer một dòng
752
+ cho macOS/Linux/WSL và Windows.
753
+
754
+ [Chưa phát hành]: https://github.com/phucanh08/alp-code/compare/v0.9.0...HEAD
755
+ [0.9.0]: https://github.com/phucanh08/alp-code/compare/v0.8.0...v0.9.0
756
+ [0.8.0]: https://github.com/phucanh08/alp-code/compare/v0.7.0...v0.8.0
757
+ [0.7.0]: https://github.com/phucanh08/alp-code/compare/v0.6.0...v0.7.0
758
+ [0.6.0]: https://github.com/phucanh08/alp-code/compare/v0.5.1...v0.6.0
759
+ [0.5.1]: https://github.com/phucanh08/alp-code/compare/v0.5.0...v0.5.1
760
+ [0.5.0]: https://github.com/phucanh08/alp-code/compare/v0.4.0...v0.5.0
761
+ [0.4.0]: https://github.com/phucanh08/alp-code/compare/v0.3.2...v0.4.0
762
+ [0.3.2]: https://github.com/phucanh08/alp-code/compare/v0.3.1...v0.3.2
763
+ [0.3.1]: https://github.com/phucanh08/alp-code/compare/v0.3.0...v0.3.1
764
+ [0.3.0]: https://github.com/phucanh08/alp-code/compare/v0.2.0...v0.3.0
765
+ [0.2.0]: https://github.com/phucanh08/alp-code/compare/v0.1.4...v0.2.0
766
+ [0.1.4]: https://github.com/phucanh08/alp-code/compare/v0.1.3...v0.1.4
767
+ [0.1.3]: https://github.com/phucanh08/alp-code/compare/v0.1.2...v0.1.3
768
+ [0.1.2]: https://github.com/phucanh08/alp-code/compare/v0.1.1...v0.1.2
769
+ [0.1.1]: https://github.com/phucanh08/alp-code/compare/v0.1.0...v0.1.1
770
+ [0.1.0]: https://github.com/phucanh08/alp-code/releases/tag/v0.1.0