aisef 0.1.0__tar.gz

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 (162) hide show
  1. aisef-0.1.0/PKG-INFO +282 -0
  2. aisef-0.1.0/README.md +274 -0
  3. aisef-0.1.0/aisdlc/__init__.py +0 -0
  4. aisef-0.1.0/aisdlc/cli/__init__.py +101 -0
  5. aisef-0.1.0/aisdlc/cli/__main__.py +9 -0
  6. aisef-0.1.0/aisdlc/cli/_common.py +72 -0
  7. aisef-0.1.0/aisdlc/cli/doctor.py +286 -0
  8. aisef-0.1.0/aisdlc/cli/harness.py +270 -0
  9. aisef-0.1.0/aisdlc/cli/implement.py +552 -0
  10. aisef-0.1.0/aisdlc/cli/parser.py +248 -0
  11. aisef-0.1.0/aisdlc/cli/plan.py +280 -0
  12. aisef-0.1.0/aisdlc/clients/__init__.py +0 -0
  13. aisef-0.1.0/aisdlc/clients/base.py +156 -0
  14. aisef-0.1.0/aisdlc/clients/claude_code.py +151 -0
  15. aisef-0.1.0/aisdlc/clients/compile.py +250 -0
  16. aisef-0.1.0/aisdlc/clients/opencode.py +162 -0
  17. aisef-0.1.0/aisdlc/clients/stream.py +340 -0
  18. aisef-0.1.0/aisdlc/config.py +363 -0
  19. aisef-0.1.0/aisdlc/control/__init__.py +0 -0
  20. aisef-0.1.0/aisdlc/control/acceptance.py +41 -0
  21. aisef-0.1.0/aisdlc/control/approvals.py +367 -0
  22. aisef-0.1.0/aisdlc/control/bmad_status.py +181 -0
  23. aisef-0.1.0/aisdlc/control/change.py +138 -0
  24. aisef-0.1.0/aisdlc/control/complexity.py +533 -0
  25. aisef-0.1.0/aisdlc/control/conformance.py +178 -0
  26. aisef-0.1.0/aisdlc/control/design_contract.py +218 -0
  27. aisef-0.1.0/aisdlc/control/experience.py +214 -0
  28. aisef-0.1.0/aisdlc/control/gate.py +800 -0
  29. aisef-0.1.0/aisdlc/control/impact.py +364 -0
  30. aisef-0.1.0/aisdlc/control/journal.py +356 -0
  31. aisef-0.1.0/aisdlc/control/ledger.py +686 -0
  32. aisef-0.1.0/aisdlc/control/machine_gate.py +318 -0
  33. aisef-0.1.0/aisdlc/control/normalize.py +696 -0
  34. aisef-0.1.0/aisdlc/control/outcome.py +116 -0
  35. aisef-0.1.0/aisdlc/control/preflight.py +741 -0
  36. aisef-0.1.0/aisdlc/control/replay.py +121 -0
  37. aisef-0.1.0/aisdlc/control/scheduler.py +199 -0
  38. aisef-0.1.0/aisdlc/control/security.py +133 -0
  39. aisef-0.1.0/aisdlc/control/state.py +332 -0
  40. aisef-0.1.0/aisdlc/control/tdd.py +84 -0
  41. aisef-0.1.0/aisdlc/control/worktree.py +392 -0
  42. aisef-0.1.0/aisdlc/harness/__init__.py +0 -0
  43. aisef-0.1.0/aisdlc/harness/aria.py +159 -0
  44. aisef-0.1.0/aisdlc/harness/assets/render.mjs +122 -0
  45. aisef-0.1.0/aisdlc/harness/browser.py +152 -0
  46. aisef-0.1.0/aisdlc/harness/context.py +306 -0
  47. aisef-0.1.0/aisdlc/harness/guardrails.py +821 -0
  48. aisef-0.1.0/aisdlc/harness/mockup_map.py +164 -0
  49. aisef-0.1.0/aisdlc/harness/mockup_verify.py +297 -0
  50. aisef-0.1.0/aisdlc/harness/observe.py +320 -0
  51. aisef-0.1.0/aisdlc/harness/prompts.py +116 -0
  52. aisef-0.1.0/aisdlc/harness/routing.py +146 -0
  53. aisef-0.1.0/aisdlc/harness/sandbox.py +489 -0
  54. aisef-0.1.0/aisdlc/harness/testlog.py +245 -0
  55. aisef-0.1.0/aisdlc/harness/tools.py +373 -0
  56. aisef-0.1.0/aisdlc/kit/__init__.py +0 -0
  57. aisef-0.1.0/aisdlc/kit/catalog.json +89 -0
  58. aisef-0.1.0/aisdlc/kit/catalog.py +122 -0
  59. aisef-0.1.0/aisdlc/kit/constitution.py +144 -0
  60. aisef-0.1.0/aisdlc/kit/detect_stack.py +160 -0
  61. aisef-0.1.0/aisdlc/kit/docs.py +102 -0
  62. aisef-0.1.0/aisdlc/kit/fetch.py +128 -0
  63. aisef-0.1.0/aisdlc/kit/install.py +218 -0
  64. aisef-0.1.0/aisdlc/kit/prompts/devsecops.md +50 -0
  65. aisef-0.1.0/aisdlc/kit/prompts/mockup-screen.md +27 -0
  66. aisef-0.1.0/aisdlc/kit/prompts/story-implement.md +112 -0
  67. aisef-0.1.0/aisdlc/kit/prompts/story-review.md +120 -0
  68. aisef-0.1.0/aisdlc/kit/prompts/story-security-review.md +127 -0
  69. aisef-0.1.0/aisdlc/kit/registry.py +434 -0
  70. aisef-0.1.0/aisdlc/kit/router.py +204 -0
  71. aisef-0.1.0/aisdlc/kit/rules/must_never.md +40 -0
  72. aisef-0.1.0/aisdlc/kit/rules/principles.md +64 -0
  73. aisef-0.1.0/aisdlc/kit/security_filter.py +264 -0
  74. aisef-0.1.0/aisdlc/kit/skill_scan.py +225 -0
  75. aisef-0.1.0/aisdlc/kit/skills/aisdlc-mockup-html/SKILL.md +125 -0
  76. aisef-0.1.0/aisdlc/kit/skills.py +132 -0
  77. aisef-0.1.0/aisdlc/phases/__init__.py +1 -0
  78. aisef-0.1.0/aisdlc/phases/deploy.py +486 -0
  79. aisef-0.1.0/aisdlc/phases/implement.py +2020 -0
  80. aisef-0.1.0/aisdlc/phases/improve.py +524 -0
  81. aisef-0.1.0/aisdlc/phases/mockup.py +302 -0
  82. aisef-0.1.0/aisdlc/phases/plan.py +437 -0
  83. aisef-0.1.0/aisdlc/phases/qa.py +455 -0
  84. aisef-0.1.0/aisdlc/phases/report.py +430 -0
  85. aisef-0.1.0/aisdlc/phases/run.py +525 -0
  86. aisef-0.1.0/aisdlc/phases/story_split.py +362 -0
  87. aisef-0.1.0/aisef.egg-info/PKG-INFO +282 -0
  88. aisef-0.1.0/aisef.egg-info/SOURCES.txt +160 -0
  89. aisef-0.1.0/aisef.egg-info/dependency_links.txt +1 -0
  90. aisef-0.1.0/aisef.egg-info/entry_points.txt +2 -0
  91. aisef-0.1.0/aisef.egg-info/top_level.txt +1 -0
  92. aisef-0.1.0/pyproject.toml +23 -0
  93. aisef-0.1.0/setup.cfg +4 -0
  94. aisef-0.1.0/tests/test_acceptance.py +37 -0
  95. aisef-0.1.0/tests/test_approvals.py +230 -0
  96. aisef-0.1.0/tests/test_aria.py +123 -0
  97. aisef-0.1.0/tests/test_bmad_status.py +125 -0
  98. aisef-0.1.0/tests/test_candidate.py +357 -0
  99. aisef-0.1.0/tests/test_catalog.py +133 -0
  100. aisef-0.1.0/tests/test_change.py +54 -0
  101. aisef-0.1.0/tests/test_cli.py +805 -0
  102. aisef-0.1.0/tests/test_clients.py +368 -0
  103. aisef-0.1.0/tests/test_compile.py +238 -0
  104. aisef-0.1.0/tests/test_config.py +209 -0
  105. aisef-0.1.0/tests/test_conformance.py +163 -0
  106. aisef-0.1.0/tests/test_constitution.py +102 -0
  107. aisef-0.1.0/tests/test_context.py +192 -0
  108. aisef-0.1.0/tests/test_deploy.py +614 -0
  109. aisef-0.1.0/tests/test_design_contract_states.py +67 -0
  110. aisef-0.1.0/tests/test_detect_stack.py +164 -0
  111. aisef-0.1.0/tests/test_docs.py +51 -0
  112. aisef-0.1.0/tests/test_experience.py +150 -0
  113. aisef-0.1.0/tests/test_fetch.py +181 -0
  114. aisef-0.1.0/tests/test_findings.py +235 -0
  115. aisef-0.1.0/tests/test_gate.py +699 -0
  116. aisef-0.1.0/tests/test_gate_qualification.py +679 -0
  117. aisef-0.1.0/tests/test_guardrails.py +973 -0
  118. aisef-0.1.0/tests/test_handoff.py +77 -0
  119. aisef-0.1.0/tests/test_impact.py +255 -0
  120. aisef-0.1.0/tests/test_implement.py +1167 -0
  121. aisef-0.1.0/tests/test_improve.py +472 -0
  122. aisef-0.1.0/tests/test_install.py +157 -0
  123. aisef-0.1.0/tests/test_journal.py +234 -0
  124. aisef-0.1.0/tests/test_ledger.py +573 -0
  125. aisef-0.1.0/tests/test_machine_gate.py +228 -0
  126. aisef-0.1.0/tests/test_meta.py +192 -0
  127. aisef-0.1.0/tests/test_mockup.py +245 -0
  128. aisef-0.1.0/tests/test_mockup_map.py +285 -0
  129. aisef-0.1.0/tests/test_mockup_map_seed.py +37 -0
  130. aisef-0.1.0/tests/test_normalize.py +196 -0
  131. aisef-0.1.0/tests/test_observe.py +145 -0
  132. aisef-0.1.0/tests/test_outcome.py +80 -0
  133. aisef-0.1.0/tests/test_plan.py +312 -0
  134. aisef-0.1.0/tests/test_prd_headings.py +47 -0
  135. aisef-0.1.0/tests/test_preflight.py +457 -0
  136. aisef-0.1.0/tests/test_preservation.py +288 -0
  137. aisef-0.1.0/tests/test_prompts.py +223 -0
  138. aisef-0.1.0/tests/test_qa.py +448 -0
  139. aisef-0.1.0/tests/test_registry.py +259 -0
  140. aisef-0.1.0/tests/test_release_gate.py +51 -0
  141. aisef-0.1.0/tests/test_replay.py +191 -0
  142. aisef-0.1.0/tests/test_report.py +293 -0
  143. aisef-0.1.0/tests/test_report_mockup_cell.py +32 -0
  144. aisef-0.1.0/tests/test_requirements_evidence.py +53 -0
  145. aisef-0.1.0/tests/test_router.py +178 -0
  146. aisef-0.1.0/tests/test_run.py +891 -0
  147. aisef-0.1.0/tests/test_sandbox.py +474 -0
  148. aisef-0.1.0/tests/test_scheduler.py +198 -0
  149. aisef-0.1.0/tests/test_security.py +174 -0
  150. aisef-0.1.0/tests/test_security_filter.py +143 -0
  151. aisef-0.1.0/tests/test_skill_scan.py +108 -0
  152. aisef-0.1.0/tests/test_skills_inline.py +66 -0
  153. aisef-0.1.0/tests/test_state.py +267 -0
  154. aisef-0.1.0/tests/test_story_size.py +402 -0
  155. aisef-0.1.0/tests/test_story_split.py +263 -0
  156. aisef-0.1.0/tests/test_stream.py +285 -0
  157. aisef-0.1.0/tests/test_tdd.py +101 -0
  158. aisef-0.1.0/tests/test_testlog.py +161 -0
  159. aisef-0.1.0/tests/test_tools.py +357 -0
  160. aisef-0.1.0/tests/test_verification_contract.py +175 -0
  161. aisef-0.1.0/tests/test_worktree.py +328 -0
  162. aisef-0.1.0/tests/test_write_scope_verify.py +68 -0
aisef-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,282 @@
1
+ Metadata-Version: 2.4
2
+ Name: aisef
3
+ Version: 0.1.0
4
+ Summary: Khung SDLC cho agent: đầu vào là docs/requirements.md, đầu ra là code đã qua cổng kiểm
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.11
7
+ Description-Content-Type: text/markdown
8
+
9
+ # AI-SDLC
10
+
11
+ Khung phát triển phần mềm bằng agent. Đầu vào của mỗi dự án là **một file**
12
+ `docs/requirements.md`; đầu ra là một ứng dụng chạy được, kèm bằng chứng
13
+ cho từng bước.
14
+
15
+ Nguyên tắc nền, xuyên suốt mọi quyết định trong kho này:
16
+
17
+ > **Cần phán đoán thì giao cho model. Cần đảm bảo thì viết code.**
18
+
19
+ Viết PRD, thiết kế kiến trúc, dựng mockup, viết code — đều cần phán đoán,
20
+ đều giao cho model. Còn "mọi yêu cầu phải có story phủ", "không được ghi
21
+ ra ngoài phạm vi", "test phải xanh sau lần sửa cuối" — đều có đáp án đúng,
22
+ nên đều là code. Hệ quả: **không bao giờ giao cho model việc giám sát
23
+ chính nó.**
24
+
25
+ ## Cài
26
+
27
+ ```bash
28
+ pip install aisef
29
+ ```
30
+
31
+ Hoặc chạy từ bản sao kho nguồn:
32
+
33
+ ```bash
34
+ git clone <repo> ai-sdlc && cd ai-sdlc && pip install -e .
35
+ python3 -m unittest discover -s tests -q # vài phút, không mở container (tests/__init__.py)
36
+ AISDLC_TEST_DOCKER=1 python3 -m unittest tests.test_sandbox tests.test_tools -q # thêm test Docker thật
37
+ ```
38
+
39
+ Kho skill tham chiếu **không cần clone tay**: `aisdlc setup` tự lấy về
40
+ `~/.cache/ai-sdlc/references` đúng commit mà `aisdlc/kit/catalog.json`
41
+ ghim (khoảng 93 MB, một lần cho mọi dự án). Máy ngoại tuyến hoặc CI trỏ
42
+ sang chỗ khác bằng `AISDLC_REFERENCES=/duong/dan`, hoặc dùng
43
+ `aisdlc setup --no-fetch` để chỉ xài những gì đã có trên đĩa.
44
+
45
+ Không có phụ thuộc Python nào ngoài thư viện chuẩn. Tuỳ chọn:
46
+ `docker` (cách ly khi chạy test), `playwright` (trích hợp đồng thị giác
47
+ từ mockup) — thiếu thì framework **nói thẳng là thiếu** chứ không giả vờ
48
+ vẫn kiểm được.
49
+
50
+ ## Sáu bước
51
+
52
+ ```bash
53
+ cd /duong/dan/du-an-cua-ban
54
+
55
+ aisdlc doctor # môi trường có đủ chưa
56
+ aisdlc setup # dò stack, nạp skill, sinh CLAUDE.md + AGENTS.md
57
+ aisdlc compile # nối guard vào client (hook / plugin)
58
+
59
+ aisdlc plan # PRD → kiến trúc → UX → epic → story
60
+ aisdlc gates # xem cổng nào đang chờ người
61
+ aisdlc review prd # đọc artifact
62
+ aisdlc approve prd # duyệt
63
+
64
+ aisdlc mockup # mỗi màn hình một HTML + hợp đồng thị giác
65
+ aisdlc approve mockups
66
+ aisdlc approve readiness
67
+
68
+ aisdlc run # hiện thực: epic tuần tự, story song song
69
+ aisdlc run --verify-only --story STORY-01-07 # kiểm lại ứng viên đã đóng băng, không mở phiên developer
70
+ aisdlc qa # bộ kiểm định
71
+ aisdlc devsecops # CI + Dockerfile + triển khai + runbook
72
+ aisdlc pre-deploy # cổng cuối
73
+ aisdlc report # báo cáo nghiệm thu + sổ hành vi + INDEX.md
74
+ aisdlc evidence STORY-01-04 # lịch sử một story hay một hành vi (AC-…, FR-…, qa:e2e)
75
+ aisdlc issues --format csv # bảng gap/hồi quy từ sổ hành vi → _bmad-output/ISSUES.csv
76
+ ```
77
+
78
+ Chạy nhanh không cần người duyệt: `aisdlc plan --auto-approve all`. Phê duyệt
79
+ tự động **luôn** được ghi dấu `auto` để về sau truy được tài liệu nào chưa
80
+ từng có người thật xem.
81
+
82
+ ## Sau khi có code
83
+
84
+ ```bash
85
+ aisdlc doc vitest --topic coverage --story STORY-01-02
86
+ ```
87
+
88
+ Tra tài liệu thật của thư viện (context7, có cache) thay vì đoán tên API; có
89
+ `--story` thì lần tra vào bằng chứng. Khi yêu cầu đổi sau phát hành:
90
+
91
+ ```bash
92
+ aisdlc change FR-3 "Slug phải giữ dấu gạch dưới"
93
+ ```
94
+
95
+ Ghi vào `docs/requirements.md`, đánh dấu PRD (cổng `prd` và các cổng sau
96
+ thành stale), sinh story delta `STORY-CH-01` với `covers=[FR-3]` — story cũ
97
+ giữ nguyên `DONE`.
98
+
99
+ ```bash
100
+ aisdlc improve --epic EPIC-01 --max-loops 3 # [--auto] không dừng ở cổng người
101
+ ```
102
+
103
+ Vòng cải tiến theo bằng chứng (ADR-004 R3): QA → sổ hành vi → **một** story
104
+ sửa cho một hành vi GAP/REOPENED (`STORY-RP-01` trong `EPIC-RP-01`, sinh bằng
105
+ code) → `run` như story thường → QA → mốc `loops[]` + `LOOP-REPORT-<n>.md`.
106
+ Dừng bằng code: hết gap, đủ `improve.max_loops`, cải thiện biên ≤ 0
107
+ `improve.flat_loops` vòng liền, vượt `improve.cost_cap_usd`, hay story sửa bế
108
+ tắc kế hoạch (trả người kèm lời reviewer). Trước mỗi vòng ≥ 2 cần
109
+ `aisdlc approve improve` trừ `--auto`.
110
+
111
+ ```bash
112
+ aisdlc run --verify-only --story STORY-01-07
113
+ ```
114
+
115
+ Story trượt chỉ vì môi trường đo (e2e nhạy tải máy) thì không cần trả tiền
116
+ cho một phiên developer để dựng lại mã đã có (ADR-004 R13): lượt kiểm-lại
117
+ lấy ứng viên ở HEAD nhánh story, chạy lại đúng phép kiểm ✗/thiếu ở SHA ấy,
118
+ giữ rà soát và bảo mật đã có ở cùng SHA, chấm đủ cổng; đạt thì merge như lượt
119
+ thường, trượt thì `failed` và không ăn vào `run.max_retries`.
120
+
121
+ ## Cổng
122
+
123
+ Tám cổng, mỗi cổng hai lớp. **Cổng máy** chạy trước — nó bắt được thứ máy
124
+ bắt tốt hơn người (chu trình phụ thuộc, yêu cầu không kiểm chứng được,
125
+ story không khai phạm vi ghi). **Cổng người** chạy sau, trên thứ đã sạch.
126
+
127
+ Phê duyệt là **trạng thái trên đĩa**, không phải câu hỏi trong phiên chat:
128
+ người duyệt có thể là người khác, lúc khác, trên máy khác. Bản ghi phê
129
+ duyệt gắn với **băm nội dung** artifact — sửa tài liệu sau khi duyệt thì
130
+ phê duyệt hết hiệu lực, và sửa tầng trên làm mọi tầng dưới thành `stale`.
131
+
132
+ ## Guard
133
+
134
+ Tám guard, mỗi guard là một lệnh trả mã thoát, nối vào ba mốc vòng đời:
135
+
136
+ | Mốc | Guard |
137
+ |---|---|
138
+ | trước mỗi tool | `write-scope` · `destructive` · `secret` · `git-stage` · `injection` · `process-ref` (luật 6: không mã story/epic trong nguồn) |
139
+ | sau mỗi tool | `diff-scope` |
140
+ | khi agent định dừng | `completion` |
141
+
142
+ Guard nằm ở phía framework, không ở phía client — client không được tin.
143
+ Cả Claude Code và OpenCode đều đã **chứng minh bằng phép thử trên agent
144
+ thật** rằng guard chặn *trước* khi tool chạy, chứ không phải phát hiện
145
+ sau. Client nào không gắn được guard tiền kiểm thì `aisdlc verify` chạy
146
+ lại toàn bộ trên diff, và `aisdlc compile` ghi rõ mức bảo đảm thấp hơn
147
+ vào báo cáo thay vì im lặng — năng lực là thứ được **khai và kiểm**, mặc
148
+ định là "chưa chứng minh", không phải "chắc là được". Trong V1, OpenCode
149
+ là client **hạng hai** theo quyết định V1: guard chặn được (hợp quy 7/7), và từ 2026-09-05 `--format json` cho luồng máy đọc được (tool, token, cost theo nhà cung cấp) — chưa lên hạng nhất vì chưa đủ số lần hợp quy hook ổn định; chi phí trước đó không đo
150
+ được từ harness; nó không chặn phát hành.
151
+
152
+ ## Lỗi thật đã gặp
153
+
154
+ Hai mươi lăm lỗi tìm bằng đo trên agent thật, xếp theo mười một lớp nguyên nhân kèm phép hồi quy: `docs/FAILURE-TAXONOMY.md`. Lỗi mới thì thêm một dòng vào đó cùng commit với test. Thay đổi theo phiên bản, kèm việc phải làm khi nâng cấp: `CHANGELOG.md`.
155
+
156
+ ## Hợp quy client
157
+
158
+ Hook và plugin là tạo tác **biên dịch ra** — đúng cú pháp không có nghĩa là
159
+ client chạy chúng. Bốn lỗi thật (31, 39, 40, 41) đều thuộc lớp này, và unit
160
+ test không bắt được theo định nghĩa. Bộ hợp quy chạy bảy phép thử trên
161
+ client thật, worktree thật, guard thật, `.claude/` không commit:
162
+
163
+ ```bash
164
+ AISDLC_CONFORMANCE=1 python3 -m unittest tests.conformance -v
165
+ ```
166
+
167
+ Kết quả ghép vào `docs/CONFORMANCE.md` — mỗi ô là một phiên agent, đọc từ
168
+ đĩa (tệp còn/mất), từ luồng `tool_use` và bằng chứng guard tự ghi, không từ
169
+ lời agent. Dự án thử và log thô từng phép giữ ở `.conformance/<client>/`
170
+ (đổi bằng `AISDLC_CONFORMANCE_DIR`) để tra lại một ô ✗ mà không phải đoán.
171
+ Bộ chạy **không** thừa hưởng biến `CLAUDE_*` của phiên gọi nó — chạy hợp
172
+ quy từ bên trong một phiên Claude là chuyện có thật, và phiên con thừa hưởng
173
+ cờ của phiên cha thì đo sai. Cổng
174
+ phát hành của chính kho này đọc bảng đó bằng code
175
+ (`AISDLC_RELEASE=1 python3 -m unittest tests.test_release_gate`): cột
176
+ `claude` phải đủ năm ô ✅ và bảng không cũ hơn 14 ngày. OpenCode là hạng
177
+ hai trong V1 — có cột, không chặn. CI: `.github/workflows/conformance.yml`
178
+ chạy tuần.
179
+
180
+ ## Phát hành
181
+
182
+ Gói phân phối tên **`aisef`** trên PyPI (module Python và lệnh vẫn là `aisdlc`), phát hành khi hoàn tất đợt 4 (quyết định 2026-09-05).
183
+ Điều kiện đọc bằng lệnh, không bằng cảm giác:
184
+
185
+ ```bash
186
+ python3 -m unittest discover -s tests -q && AISDLC_RELEASE=1 AISDLC_ACCEPTANCE=<dự án nghiệm thu> python3 -m unittest tests.test_release_gate -q
187
+ ```
188
+
189
+ `AISDLC_ACCEPTANCE` trỏ vào dự án dogfood đã nghiệm thu (v0.1.0: `e9`, phạm vi
190
+ EPIC-01): cổng đọc `pre-deploy-report.json` (đạt, có phạm vi, miễn có lý do)
191
+ và phê duyệt `pre-deploy` trên đúng bản ấy. Không đặt thì bỏ qua có nêu tên —
192
+ không tính là đạt.
193
+
194
+ ```bash
195
+ uv build && uvx twine check dist/*
196
+ ```
197
+
198
+ `.github/workflows/release.yml` publish bằng *trusted publishing* khi đẩy tag
199
+ `v*` — không có token nào trong kho. Việc làm **một lần bằng tay**, bằng tài
200
+ khoản tổ chức: tạo project `aisef` trên PyPI và khai trusted publisher
201
+ (kho này · workflow `release.yml` · environment `pypi`). Sau đó:
202
+
203
+ ```bash
204
+ git tag v0.1.0 && git push --tags
205
+ ```
206
+
207
+ Kho hồi quy dogfood (`tests/dogfood/`, bật bằng `AISDLC_DOGFOOD=1`) dựng lại
208
+ dự án thử `par` từ đầu vào trong kho và so với mốc đã đo — chạy trước mỗi tag.
209
+
210
+ ### Giới hạn đã biết của v0.1.0
211
+
212
+ Khai ở đây vì mọi claim phải có bằng chứng; thứ chưa chứng minh gọi là chưa
213
+ chứng minh (quyết định chủ đầu tư 2026-09-06, `docs/RELEASE-PLAN-v0.1.0.md` §0):
214
+
215
+ - **Phạm vi nghiệm thu dogfood là EPIC-01 của `e9`** (7 story, `aisdlc
216
+ pre-deploy --epic EPIC-01`). EPIC-02..05 (16 story) chưa chạy — báo cáo ghi
217
+ "ngoài phạm vi", không phải "xong". `e9` chưa phải sản phẩm được nghiệm thu
218
+ hoàn chỉnh; nó là corpus nghiệm thu của framework.
219
+ - **OpenCode là client hạng hai**: hợp quy 9/10 (C9 model từ chối, không kết
220
+ luận), không có đầu ra máy đọc ổn định; claim phát hành dựa trên Claude Code.
221
+ - **Agent trong container chưa có cách ly credential** (S1 blocked): V1 chạy
222
+ agent trên host, chỉ kiểm định trong container; `doctor`/`pre-deploy` nêu
223
+ tên bảo đảm thiếu, không im lặng.
224
+ - **`mutation` ở môi trường nghiệm thu là KHÔNG CHẠY ĐƯỢC** (công cụ chưa cài);
225
+ được miễn có lý do ở `verify.waiver_reason`, hiện ◇, không bao giờ thành ✅.
226
+ `image-scan` cùng loại (docker scout đòi đăng nhập, trivy/grype vắng).
227
+ - **`skills.offer`/`skills.inline` tắt** (A/B không thấy gain), **`repo_map`
228
+ tắt** (`context.max_repo_map_chars = 0`, A/B hoãn sau v0.1.0).
229
+ - **`coverage`**: harness đọc số từ runner (`--coverage`/`--cov`); dự án chưa
230
+ bật thì mục cổng là ○ chưa cấu hình, không phải đạt.
231
+
232
+ ## Khi cổng chặn
233
+
234
+ Cổng chặn là framework đang làm việc, không phải framework hỏng. Ba ca hay
235
+ gặp và cách xử đúng:
236
+
237
+ | Cổng báo | Nghĩa là | Làm gì |
238
+ |---|---|---|
239
+ | `mockup còn N chỗ chưa chốt` | mockup gặp câu hỏi chưa ai trả lời và **đánh dấu** thay vì tự quyết | trả lời câu hỏi (thường nằm ở `open_questions` của PRD/UX), sửa tài liệu, dựng lại mockup |
240
+ | `story đụng vào yêu cầu đang bị câu hỏi mở chặn` | epic gán một FR mà PRD ghi là chưa quyết được | trả lời câu hỏi, hoặc bỏ FR đó khỏi story |
241
+ | `merge đụng …` | hai story cùng sửa một file | `write_scope` khai sai — sửa ở story, **không** gỡ conflict cho xong |
242
+
243
+ `--force` có ở `approve` và `run` cho trường hợp cố ý bỏ qua. Dùng nó là
244
+ một quyết định, và nó được ghi lại: bản ghi phê duyệt giữ ghi chú, báo cáo
245
+ nghiệm thu hiện đúng trạng thái từng cổng.
246
+
247
+ ## Chạy song song
248
+
249
+ Epic chạy tuần tự. Trong một epic, hai story chỉ được cùng đợt khi **hết
250
+ phụ thuộc** *và* **phạm vi ghi rời nhau** — thiếu điều kiện thứ hai thì hai
251
+ story cùng sửa một file và người thua là người merge sau. Mỗi story chạy
252
+ trong worktree git riêng; merge tuần tự cuối đợt. Conflict lúc merge không
253
+ được tự gỡ: nó là **bằng chứng `write_scope` khai sai**.
254
+
255
+ ## Cấu trúc
256
+
257
+ ```
258
+ aisdlc/
259
+ cli/ bộ lệnh chia theo pha, mọi lệnh gọi-một-lần, không daemon
260
+ config.py ngưỡng và cấu hình, có kiểu, có kiểm
261
+ clients/ Claude Code · OpenCode; năng lực được **khai**, không giả định
262
+ control/ cổng, phê duyệt, xếp lịch, worktree, chuẩn hoá tài liệu BMAD
263
+ harness/ prompt · tool · sandbox · guard · quan sát · map mockup
264
+ kit/ catalog skill, lọc bảo mật hai tầng, hiến pháp, prompt, skill riêng
265
+ phases/ plan · mockup · implement · run · qa · deploy · report
266
+ docs/
267
+ SOLUTION.md giải pháp tổng thể và vì sao chọn như vậy
268
+ EXECUTION-PLAN.md kế hoạch thực thi, trạng thái từng hạng mục
269
+ REQUIREMENTS-EVIDENCE.md R1–R14 → test chạy được
270
+ SPIKE-REPORT.md kết quả 7 spike kiểm chứng khả thi
271
+ ```
272
+
273
+ ## Bằng chứng, không tự khai
274
+
275
+ Mọi cổng đọc `_bmad-output/evidence/{story}.jsonl` — lần chạy test, lần
276
+ sửa file, lần gọi model kèm chi phí và độ trễ, lần đối chiếu mockup. Câu
277
+ "đã hoàn thành" của agent không được tính là gì cả.
278
+
279
+ Cụ thể, một story chỉ xong khi: test xanh **và** xanh sau lần sửa cuối ·
280
+ lint sạch · thay đổi nằm trong phạm vi khai báo · màn hình thật dựng đủ
281
+ component mockup đã hứa · rà soát độc lập (phiên khác, cấm sửa code) không
282
+ còn mục chặn · không có test nào rỗng khẳng định.
aisef-0.1.0/README.md ADDED
@@ -0,0 +1,274 @@
1
+ # AI-SDLC
2
+
3
+ Khung phát triển phần mềm bằng agent. Đầu vào của mỗi dự án là **một file**
4
+ `docs/requirements.md`; đầu ra là một ứng dụng chạy được, kèm bằng chứng
5
+ cho từng bước.
6
+
7
+ Nguyên tắc nền, xuyên suốt mọi quyết định trong kho này:
8
+
9
+ > **Cần phán đoán thì giao cho model. Cần đảm bảo thì viết code.**
10
+
11
+ Viết PRD, thiết kế kiến trúc, dựng mockup, viết code — đều cần phán đoán,
12
+ đều giao cho model. Còn "mọi yêu cầu phải có story phủ", "không được ghi
13
+ ra ngoài phạm vi", "test phải xanh sau lần sửa cuối" — đều có đáp án đúng,
14
+ nên đều là code. Hệ quả: **không bao giờ giao cho model việc giám sát
15
+ chính nó.**
16
+
17
+ ## Cài
18
+
19
+ ```bash
20
+ pip install aisef
21
+ ```
22
+
23
+ Hoặc chạy từ bản sao kho nguồn:
24
+
25
+ ```bash
26
+ git clone <repo> ai-sdlc && cd ai-sdlc && pip install -e .
27
+ python3 -m unittest discover -s tests -q # vài phút, không mở container (tests/__init__.py)
28
+ AISDLC_TEST_DOCKER=1 python3 -m unittest tests.test_sandbox tests.test_tools -q # thêm test Docker thật
29
+ ```
30
+
31
+ Kho skill tham chiếu **không cần clone tay**: `aisdlc setup` tự lấy về
32
+ `~/.cache/ai-sdlc/references` đúng commit mà `aisdlc/kit/catalog.json`
33
+ ghim (khoảng 93 MB, một lần cho mọi dự án). Máy ngoại tuyến hoặc CI trỏ
34
+ sang chỗ khác bằng `AISDLC_REFERENCES=/duong/dan`, hoặc dùng
35
+ `aisdlc setup --no-fetch` để chỉ xài những gì đã có trên đĩa.
36
+
37
+ Không có phụ thuộc Python nào ngoài thư viện chuẩn. Tuỳ chọn:
38
+ `docker` (cách ly khi chạy test), `playwright` (trích hợp đồng thị giác
39
+ từ mockup) — thiếu thì framework **nói thẳng là thiếu** chứ không giả vờ
40
+ vẫn kiểm được.
41
+
42
+ ## Sáu bước
43
+
44
+ ```bash
45
+ cd /duong/dan/du-an-cua-ban
46
+
47
+ aisdlc doctor # môi trường có đủ chưa
48
+ aisdlc setup # dò stack, nạp skill, sinh CLAUDE.md + AGENTS.md
49
+ aisdlc compile # nối guard vào client (hook / plugin)
50
+
51
+ aisdlc plan # PRD → kiến trúc → UX → epic → story
52
+ aisdlc gates # xem cổng nào đang chờ người
53
+ aisdlc review prd # đọc artifact
54
+ aisdlc approve prd # duyệt
55
+
56
+ aisdlc mockup # mỗi màn hình một HTML + hợp đồng thị giác
57
+ aisdlc approve mockups
58
+ aisdlc approve readiness
59
+
60
+ aisdlc run # hiện thực: epic tuần tự, story song song
61
+ aisdlc run --verify-only --story STORY-01-07 # kiểm lại ứng viên đã đóng băng, không mở phiên developer
62
+ aisdlc qa # bộ kiểm định
63
+ aisdlc devsecops # CI + Dockerfile + triển khai + runbook
64
+ aisdlc pre-deploy # cổng cuối
65
+ aisdlc report # báo cáo nghiệm thu + sổ hành vi + INDEX.md
66
+ aisdlc evidence STORY-01-04 # lịch sử một story hay một hành vi (AC-…, FR-…, qa:e2e)
67
+ aisdlc issues --format csv # bảng gap/hồi quy từ sổ hành vi → _bmad-output/ISSUES.csv
68
+ ```
69
+
70
+ Chạy nhanh không cần người duyệt: `aisdlc plan --auto-approve all`. Phê duyệt
71
+ tự động **luôn** được ghi dấu `auto` để về sau truy được tài liệu nào chưa
72
+ từng có người thật xem.
73
+
74
+ ## Sau khi có code
75
+
76
+ ```bash
77
+ aisdlc doc vitest --topic coverage --story STORY-01-02
78
+ ```
79
+
80
+ Tra tài liệu thật của thư viện (context7, có cache) thay vì đoán tên API; có
81
+ `--story` thì lần tra vào bằng chứng. Khi yêu cầu đổi sau phát hành:
82
+
83
+ ```bash
84
+ aisdlc change FR-3 "Slug phải giữ dấu gạch dưới"
85
+ ```
86
+
87
+ Ghi vào `docs/requirements.md`, đánh dấu PRD (cổng `prd` và các cổng sau
88
+ thành stale), sinh story delta `STORY-CH-01` với `covers=[FR-3]` — story cũ
89
+ giữ nguyên `DONE`.
90
+
91
+ ```bash
92
+ aisdlc improve --epic EPIC-01 --max-loops 3 # [--auto] không dừng ở cổng người
93
+ ```
94
+
95
+ Vòng cải tiến theo bằng chứng (ADR-004 R3): QA → sổ hành vi → **một** story
96
+ sửa cho một hành vi GAP/REOPENED (`STORY-RP-01` trong `EPIC-RP-01`, sinh bằng
97
+ code) → `run` như story thường → QA → mốc `loops[]` + `LOOP-REPORT-<n>.md`.
98
+ Dừng bằng code: hết gap, đủ `improve.max_loops`, cải thiện biên ≤ 0
99
+ `improve.flat_loops` vòng liền, vượt `improve.cost_cap_usd`, hay story sửa bế
100
+ tắc kế hoạch (trả người kèm lời reviewer). Trước mỗi vòng ≥ 2 cần
101
+ `aisdlc approve improve` trừ `--auto`.
102
+
103
+ ```bash
104
+ aisdlc run --verify-only --story STORY-01-07
105
+ ```
106
+
107
+ Story trượt chỉ vì môi trường đo (e2e nhạy tải máy) thì không cần trả tiền
108
+ cho một phiên developer để dựng lại mã đã có (ADR-004 R13): lượt kiểm-lại
109
+ lấy ứng viên ở HEAD nhánh story, chạy lại đúng phép kiểm ✗/thiếu ở SHA ấy,
110
+ giữ rà soát và bảo mật đã có ở cùng SHA, chấm đủ cổng; đạt thì merge như lượt
111
+ thường, trượt thì `failed` và không ăn vào `run.max_retries`.
112
+
113
+ ## Cổng
114
+
115
+ Tám cổng, mỗi cổng hai lớp. **Cổng máy** chạy trước — nó bắt được thứ máy
116
+ bắt tốt hơn người (chu trình phụ thuộc, yêu cầu không kiểm chứng được,
117
+ story không khai phạm vi ghi). **Cổng người** chạy sau, trên thứ đã sạch.
118
+
119
+ Phê duyệt là **trạng thái trên đĩa**, không phải câu hỏi trong phiên chat:
120
+ người duyệt có thể là người khác, lúc khác, trên máy khác. Bản ghi phê
121
+ duyệt gắn với **băm nội dung** artifact — sửa tài liệu sau khi duyệt thì
122
+ phê duyệt hết hiệu lực, và sửa tầng trên làm mọi tầng dưới thành `stale`.
123
+
124
+ ## Guard
125
+
126
+ Tám guard, mỗi guard là một lệnh trả mã thoát, nối vào ba mốc vòng đời:
127
+
128
+ | Mốc | Guard |
129
+ |---|---|
130
+ | trước mỗi tool | `write-scope` · `destructive` · `secret` · `git-stage` · `injection` · `process-ref` (luật 6: không mã story/epic trong nguồn) |
131
+ | sau mỗi tool | `diff-scope` |
132
+ | khi agent định dừng | `completion` |
133
+
134
+ Guard nằm ở phía framework, không ở phía client — client không được tin.
135
+ Cả Claude Code và OpenCode đều đã **chứng minh bằng phép thử trên agent
136
+ thật** rằng guard chặn *trước* khi tool chạy, chứ không phải phát hiện
137
+ sau. Client nào không gắn được guard tiền kiểm thì `aisdlc verify` chạy
138
+ lại toàn bộ trên diff, và `aisdlc compile` ghi rõ mức bảo đảm thấp hơn
139
+ vào báo cáo thay vì im lặng — năng lực là thứ được **khai và kiểm**, mặc
140
+ định là "chưa chứng minh", không phải "chắc là được". Trong V1, OpenCode
141
+ là client **hạng hai** theo quyết định V1: guard chặn được (hợp quy 7/7), và từ 2026-09-05 `--format json` cho luồng máy đọc được (tool, token, cost theo nhà cung cấp) — chưa lên hạng nhất vì chưa đủ số lần hợp quy hook ổn định; chi phí trước đó không đo
142
+ được từ harness; nó không chặn phát hành.
143
+
144
+ ## Lỗi thật đã gặp
145
+
146
+ Hai mươi lăm lỗi tìm bằng đo trên agent thật, xếp theo mười một lớp nguyên nhân kèm phép hồi quy: `docs/FAILURE-TAXONOMY.md`. Lỗi mới thì thêm một dòng vào đó cùng commit với test. Thay đổi theo phiên bản, kèm việc phải làm khi nâng cấp: `CHANGELOG.md`.
147
+
148
+ ## Hợp quy client
149
+
150
+ Hook và plugin là tạo tác **biên dịch ra** — đúng cú pháp không có nghĩa là
151
+ client chạy chúng. Bốn lỗi thật (31, 39, 40, 41) đều thuộc lớp này, và unit
152
+ test không bắt được theo định nghĩa. Bộ hợp quy chạy bảy phép thử trên
153
+ client thật, worktree thật, guard thật, `.claude/` không commit:
154
+
155
+ ```bash
156
+ AISDLC_CONFORMANCE=1 python3 -m unittest tests.conformance -v
157
+ ```
158
+
159
+ Kết quả ghép vào `docs/CONFORMANCE.md` — mỗi ô là một phiên agent, đọc từ
160
+ đĩa (tệp còn/mất), từ luồng `tool_use` và bằng chứng guard tự ghi, không từ
161
+ lời agent. Dự án thử và log thô từng phép giữ ở `.conformance/<client>/`
162
+ (đổi bằng `AISDLC_CONFORMANCE_DIR`) để tra lại một ô ✗ mà không phải đoán.
163
+ Bộ chạy **không** thừa hưởng biến `CLAUDE_*` của phiên gọi nó — chạy hợp
164
+ quy từ bên trong một phiên Claude là chuyện có thật, và phiên con thừa hưởng
165
+ cờ của phiên cha thì đo sai. Cổng
166
+ phát hành của chính kho này đọc bảng đó bằng code
167
+ (`AISDLC_RELEASE=1 python3 -m unittest tests.test_release_gate`): cột
168
+ `claude` phải đủ năm ô ✅ và bảng không cũ hơn 14 ngày. OpenCode là hạng
169
+ hai trong V1 — có cột, không chặn. CI: `.github/workflows/conformance.yml`
170
+ chạy tuần.
171
+
172
+ ## Phát hành
173
+
174
+ Gói phân phối tên **`aisef`** trên PyPI (module Python và lệnh vẫn là `aisdlc`), phát hành khi hoàn tất đợt 4 (quyết định 2026-09-05).
175
+ Điều kiện đọc bằng lệnh, không bằng cảm giác:
176
+
177
+ ```bash
178
+ python3 -m unittest discover -s tests -q && AISDLC_RELEASE=1 AISDLC_ACCEPTANCE=<dự án nghiệm thu> python3 -m unittest tests.test_release_gate -q
179
+ ```
180
+
181
+ `AISDLC_ACCEPTANCE` trỏ vào dự án dogfood đã nghiệm thu (v0.1.0: `e9`, phạm vi
182
+ EPIC-01): cổng đọc `pre-deploy-report.json` (đạt, có phạm vi, miễn có lý do)
183
+ và phê duyệt `pre-deploy` trên đúng bản ấy. Không đặt thì bỏ qua có nêu tên —
184
+ không tính là đạt.
185
+
186
+ ```bash
187
+ uv build && uvx twine check dist/*
188
+ ```
189
+
190
+ `.github/workflows/release.yml` publish bằng *trusted publishing* khi đẩy tag
191
+ `v*` — không có token nào trong kho. Việc làm **một lần bằng tay**, bằng tài
192
+ khoản tổ chức: tạo project `aisef` trên PyPI và khai trusted publisher
193
+ (kho này · workflow `release.yml` · environment `pypi`). Sau đó:
194
+
195
+ ```bash
196
+ git tag v0.1.0 && git push --tags
197
+ ```
198
+
199
+ Kho hồi quy dogfood (`tests/dogfood/`, bật bằng `AISDLC_DOGFOOD=1`) dựng lại
200
+ dự án thử `par` từ đầu vào trong kho và so với mốc đã đo — chạy trước mỗi tag.
201
+
202
+ ### Giới hạn đã biết của v0.1.0
203
+
204
+ Khai ở đây vì mọi claim phải có bằng chứng; thứ chưa chứng minh gọi là chưa
205
+ chứng minh (quyết định chủ đầu tư 2026-09-06, `docs/RELEASE-PLAN-v0.1.0.md` §0):
206
+
207
+ - **Phạm vi nghiệm thu dogfood là EPIC-01 của `e9`** (7 story, `aisdlc
208
+ pre-deploy --epic EPIC-01`). EPIC-02..05 (16 story) chưa chạy — báo cáo ghi
209
+ "ngoài phạm vi", không phải "xong". `e9` chưa phải sản phẩm được nghiệm thu
210
+ hoàn chỉnh; nó là corpus nghiệm thu của framework.
211
+ - **OpenCode là client hạng hai**: hợp quy 9/10 (C9 model từ chối, không kết
212
+ luận), không có đầu ra máy đọc ổn định; claim phát hành dựa trên Claude Code.
213
+ - **Agent trong container chưa có cách ly credential** (S1 blocked): V1 chạy
214
+ agent trên host, chỉ kiểm định trong container; `doctor`/`pre-deploy` nêu
215
+ tên bảo đảm thiếu, không im lặng.
216
+ - **`mutation` ở môi trường nghiệm thu là KHÔNG CHẠY ĐƯỢC** (công cụ chưa cài);
217
+ được miễn có lý do ở `verify.waiver_reason`, hiện ◇, không bao giờ thành ✅.
218
+ `image-scan` cùng loại (docker scout đòi đăng nhập, trivy/grype vắng).
219
+ - **`skills.offer`/`skills.inline` tắt** (A/B không thấy gain), **`repo_map`
220
+ tắt** (`context.max_repo_map_chars = 0`, A/B hoãn sau v0.1.0).
221
+ - **`coverage`**: harness đọc số từ runner (`--coverage`/`--cov`); dự án chưa
222
+ bật thì mục cổng là ○ chưa cấu hình, không phải đạt.
223
+
224
+ ## Khi cổng chặn
225
+
226
+ Cổng chặn là framework đang làm việc, không phải framework hỏng. Ba ca hay
227
+ gặp và cách xử đúng:
228
+
229
+ | Cổng báo | Nghĩa là | Làm gì |
230
+ |---|---|---|
231
+ | `mockup còn N chỗ chưa chốt` | mockup gặp câu hỏi chưa ai trả lời và **đánh dấu** thay vì tự quyết | trả lời câu hỏi (thường nằm ở `open_questions` của PRD/UX), sửa tài liệu, dựng lại mockup |
232
+ | `story đụng vào yêu cầu đang bị câu hỏi mở chặn` | epic gán một FR mà PRD ghi là chưa quyết được | trả lời câu hỏi, hoặc bỏ FR đó khỏi story |
233
+ | `merge đụng …` | hai story cùng sửa một file | `write_scope` khai sai — sửa ở story, **không** gỡ conflict cho xong |
234
+
235
+ `--force` có ở `approve` và `run` cho trường hợp cố ý bỏ qua. Dùng nó là
236
+ một quyết định, và nó được ghi lại: bản ghi phê duyệt giữ ghi chú, báo cáo
237
+ nghiệm thu hiện đúng trạng thái từng cổng.
238
+
239
+ ## Chạy song song
240
+
241
+ Epic chạy tuần tự. Trong một epic, hai story chỉ được cùng đợt khi **hết
242
+ phụ thuộc** *và* **phạm vi ghi rời nhau** — thiếu điều kiện thứ hai thì hai
243
+ story cùng sửa một file và người thua là người merge sau. Mỗi story chạy
244
+ trong worktree git riêng; merge tuần tự cuối đợt. Conflict lúc merge không
245
+ được tự gỡ: nó là **bằng chứng `write_scope` khai sai**.
246
+
247
+ ## Cấu trúc
248
+
249
+ ```
250
+ aisdlc/
251
+ cli/ bộ lệnh chia theo pha, mọi lệnh gọi-một-lần, không daemon
252
+ config.py ngưỡng và cấu hình, có kiểu, có kiểm
253
+ clients/ Claude Code · OpenCode; năng lực được **khai**, không giả định
254
+ control/ cổng, phê duyệt, xếp lịch, worktree, chuẩn hoá tài liệu BMAD
255
+ harness/ prompt · tool · sandbox · guard · quan sát · map mockup
256
+ kit/ catalog skill, lọc bảo mật hai tầng, hiến pháp, prompt, skill riêng
257
+ phases/ plan · mockup · implement · run · qa · deploy · report
258
+ docs/
259
+ SOLUTION.md giải pháp tổng thể và vì sao chọn như vậy
260
+ EXECUTION-PLAN.md kế hoạch thực thi, trạng thái từng hạng mục
261
+ REQUIREMENTS-EVIDENCE.md R1–R14 → test chạy được
262
+ SPIKE-REPORT.md kết quả 7 spike kiểm chứng khả thi
263
+ ```
264
+
265
+ ## Bằng chứng, không tự khai
266
+
267
+ Mọi cổng đọc `_bmad-output/evidence/{story}.jsonl` — lần chạy test, lần
268
+ sửa file, lần gọi model kèm chi phí và độ trễ, lần đối chiếu mockup. Câu
269
+ "đã hoàn thành" của agent không được tính là gì cả.
270
+
271
+ Cụ thể, một story chỉ xong khi: test xanh **và** xanh sau lần sửa cuối ·
272
+ lint sạch · thay đổi nằm trong phạm vi khai báo · màn hình thật dựng đủ
273
+ component mockup đã hứa · rà soát độc lập (phiên khác, cấm sửa code) không
274
+ còn mục chặn · không có test nào rỗng khẳng định.
File without changes
@@ -0,0 +1,101 @@
1
+ """Giao diện dòng lệnh.
2
+
3
+ Mọi lệnh đều **gọi-một-lần**: đọc trạng thái trên đĩa, làm việc, ghi lại,
4
+ rồi thoát. Không lệnh nào giả định mình là tiến trình chính, không lệnh
5
+ nào chạy nền. Đó là điều kiện để cùng bộ lệnh này dùng được ở hai chế độ
6
+ (quyết định Đ2):
7
+
8
+ * **driver-led** — script hoặc CI gọi ``aisdlc run``;
9
+ * **agent-led** — chính agent gọi ``aisdlc next`` / ``verify`` / ``complete``
10
+ qua Bash, ngay trong phiên chat của Claude Desktop hay OpenCode.
11
+
12
+ Quy ước mã thoát: ``0`` thành công · ``1`` lỗi dùng sai · ``2`` trạng thái
13
+ chưa đạt (cổng chưa duyệt, doctor không đạt) — để CI phân biệt được
14
+ "hỏng" với "chưa xong".
15
+
16
+ Bố cục gói (chia theo pha, không đổi hành vi):
17
+
18
+ * :mod:`._common` — mã thoát, gốc artifact, kho duyệt/trạng thái, adapter;
19
+ * :mod:`.doctor` — lệnh ``doctor``;
20
+ * :mod:`.plan` — cổng người + pha lập kế hoạch;
21
+ * :mod:`.implement` — pha hiện thực và nghiệm thu;
22
+ * :mod:`.harness` — dựng và vận hành harness;
23
+ * :mod:`.parser` — bộ phân tích tham số và ``main``.
24
+
25
+ Mọi tên module-level cũ được xuất lại ở đây, nên ``from aisdlc.cli import
26
+ main`` và bạn bè vẫn chạy y như khi còn là một file.
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ from ._common import (
32
+ ARTIFACT_ROOT,
33
+ _GATE_MARK,
34
+ EXIT_NOT_READY,
35
+ EXIT_OK,
36
+ EXIT_USAGE,
37
+ _approvals,
38
+ _artifact_root,
39
+ _client,
40
+ _gate_arg,
41
+ _state,
42
+ )
43
+ from .doctor import _hook_paths_elsewhere, cmd_doctor
44
+ from .harness import cmd_compile, cmd_doc, cmd_guard, cmd_init, cmd_setup, cmd_skill
45
+ from .implement import (
46
+ _project_has_ui,
47
+ cmd_devsecops,
48
+ cmd_evidence,
49
+ cmd_predeploy,
50
+ cmd_qa,
51
+ cmd_report,
52
+ cmd_run,
53
+ cmd_status,
54
+ cmd_tool,
55
+ cmd_verify,
56
+ )
57
+ from .parser import build_parser, main
58
+ from .plan import (
59
+ _preflight_lines,
60
+ cmd_approve,
61
+ cmd_auto_approve,
62
+ cmd_change,
63
+ cmd_gates,
64
+ cmd_mockup,
65
+ cmd_plan,
66
+ cmd_reject,
67
+ cmd_review,
68
+ )
69
+
70
+ __all__ = [
71
+ "ARTIFACT_ROOT",
72
+ "EXIT_NOT_READY",
73
+ "EXIT_OK",
74
+ "EXIT_USAGE",
75
+ "build_parser",
76
+ "cmd_approve",
77
+ "cmd_auto_approve",
78
+ "cmd_change",
79
+ "cmd_compile",
80
+ "cmd_devsecops",
81
+ "cmd_doc",
82
+ "cmd_doctor",
83
+ "cmd_evidence",
84
+ "cmd_gates",
85
+ "cmd_guard",
86
+ "cmd_init",
87
+ "cmd_mockup",
88
+ "cmd_plan",
89
+ "cmd_predeploy",
90
+ "cmd_qa",
91
+ "cmd_reject",
92
+ "cmd_report",
93
+ "cmd_review",
94
+ "cmd_run",
95
+ "cmd_setup",
96
+ "cmd_skill",
97
+ "cmd_status",
98
+ "cmd_tool",
99
+ "cmd_verify",
100
+ "main",
101
+ ]
@@ -0,0 +1,9 @@
1
+ """Giữ nguyên `python -m aisdlc.cli` — trước khi tách, `cli.py` có khối
2
+ ``if __name__ == "__main__"`` làm đúng việc này."""
3
+
4
+ import sys
5
+
6
+ from . import main
7
+
8
+ if __name__ == "__main__":
9
+ sys.exit(main())